Feature/extended active campaign (#928)

* feat: 🎸 node/activecampaign account, tag, account contact

* feat: 🎸 node/ActiveCampaign Update an accountContact assoc

* feat: 🎸 node/activecampaign Update an account

* feat: 🎸 node/activecampaign Get an account

* feat: 🎸 node/activecampaign GetAll & Delete an account

* feat: 🎸 node/activecampaign change ID's type to number

* refactor: 💡 node/activecampaign merge getAll properties

*  Improvements to #923

*  Improvements

*  Improvements

*  Add breaking change message

Co-authored-by: Ronald Diquélou <rdiquelou@opensafepro.com>
This commit is contained in:
Ricardo Espinoza 2020-09-18 03:42:01 -04:00 committed by GitHub
parent e18d7934ad
commit a552febab4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 1584 additions and 316 deletions

View file

@ -2,6 +2,28 @@
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.83.0
### What changed?
In the Active Campaign Node, we have changed how the operation `getAll` works on various resources to keep consistency across them. To achive this a new parameter called 'Simple' was added.
### When is action necessary?
When one of the following resources/operations is used:
| Resource | Operation |
|--|--|
| Deal | Get All |
| Connector | Get All |
| E-commerce Order | Get All |
| E-commerce Customer | Get All |
| E-commerce Order Products | Get All |
### How to upgrade:
Open the affected resource/operation and set the parameter `Simple` to false.
## 0.79.0 ## 0.79.0
### What changed? ### What changed?

View file

@ -0,0 +1,175 @@
import {
INodeProperties,
} from 'n8n-workflow';
export const accountContactOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'accountContact',
],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create an association',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete an association',
},
{
name: 'Update',
value: 'update',
description: 'Update an association',
},
],
default: 'create',
description: 'The operation to perform.',
},
] as INodeProperties[];
export const accountContactFields = [
// ----------------------------------
// accountContact:create
// ----------------------------------
{
displayName: 'Account ID',
name: 'account',
type: 'number',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'create',
],
resource: [
'accountContact',
],
},
},
description: 'Account ID',
},
{
displayName: 'Contact ID',
name: 'contact',
type: 'number',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'create',
],
resource: [
'accountContact',
],
},
},
description: 'Contact ID',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: [
'create',
],
resource: [
'accountContact',
],
},
},
default: {},
options: [
{
displayName: 'Job title',
name: 'jobTitle',
type: 'string',
default: '',
description: 'Job Title of the contact at the account',
},
],
},
// ----------------------------------
// accountContact:delete
// ----------------------------------
{
displayName: 'Account Contact ID',
name: 'accountContactId',
type: 'number',
displayOptions: {
show: {
operation: [
'delete',
],
resource: [
'accountContact',
],
},
},
default: 0,
required: true,
description: 'ID of the account contact to delete.',
},
// ----------------------------------
// accountContact:update
// ----------------------------------
{
displayName: 'Account Contact ID',
name: 'accountContactId',
type: 'number',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'update',
],
resource: [
'accountContact',
],
},
},
description: 'Account ID',
},
{
displayName: 'Update Fields',
name: 'updateFields',
type: 'collection',
description: 'The fields to update.',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: [
'update',
],
resource: [
'accountContact',
],
},
},
default: {},
options: [
{
displayName: 'Job title',
name: 'jobTitle',
type: 'string',
default: '',
description: 'Job Title of the contact at the account',
},
],
},
] as INodeProperties[];

View file

@ -0,0 +1,302 @@
import {
INodeProperties,
} from 'n8n-workflow';
import {
activeCampaignDefaultGetAllProperties,
} from './GenericFunctions';
export const accountOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'account',
],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create an account',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete an account',
},
{
name: 'Get',
value: 'get',
description: 'Get data of an account',
},
{
name: 'Get All',
value: 'getAll',
description: 'Get data of all accounts',
},
{
name: 'Update',
value: 'update',
description: 'Update an account',
},
],
default: 'create',
description: 'The operation to perform.',
},
] as INodeProperties[];
export const accountFields = [
// ----------------------------------
// contact:create
// ----------------------------------
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'create',
],
resource: [
'account',
],
},
},
description: 'Account\'s name.',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: [
'create',
],
resource: [
'account',
],
},
},
default: {},
options: [
{
displayName: 'Account URL',
name: 'accountUrl',
type: 'string',
default: '',
description: `Account's website`,
},
{
displayName: 'Fields',
name: 'fields',
placeholder: 'Add Custom Fields',
description: 'Adds a custom fields to set also values which have not been predefined.',
type: 'fixedCollection',
typeOptions: {
multipleValues: true,
},
default: {},
options: [
{
name: 'property',
displayName: 'Field',
values: [
{
displayName: 'Field ID',
name: 'customFieldId',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getAccountCustomFields',
},
default: '',
description: 'ID of the field to set.',
},
{
displayName: 'Field Value',
name: 'fieldValue',
type: 'string',
default: '',
description: 'Value of the field to set.',
},
],
},
],
},
],
},
// ----------------------------------
// contact:update
// ----------------------------------
{
displayName: 'Account ID',
name: 'accountId',
type: 'number',
displayOptions: {
show: {
operation: [
'update',
],
resource: [
'account',
],
},
},
default: 0,
required: true,
description: 'ID of the account to update.',
},
{
displayName: 'Update Fields',
name: 'updateFields',
type: 'collection',
description: 'The fields to update.',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: [
'update',
],
resource: [
'account',
],
},
},
default: {},
options: [
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
description: 'Account\'s name.',
},
{
displayName: 'Account URL',
name: 'accountUrl',
type: 'string',
default: '',
description: 'Account\'s website',
},
{
displayName: 'Fields',
name: 'fields',
placeholder: 'Add Fields',
description: 'Adds a custom fields to set also values which have not been predefined.',
type: 'fixedCollection',
typeOptions: {
multipleValues: true,
},
default: {},
options: [
{
name: 'property',
displayName: 'Field',
values: [
{
displayName: 'Field ID',
name: 'customFieldId',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getAccountCustomFields',
},
default: '',
description: 'ID of the field to set.',
},
{
displayName: 'Field Value',
name: 'fieldValue',
type: 'string',
default: '',
description: 'Value of the field to set.',
},
],
},
],
},
],
},
// ----------------------------------
// account:delete
// ----------------------------------
{
displayName: 'Account ID',
name: 'accountId',
type: 'number',
displayOptions: {
show: {
operation: [
'delete',
],
resource: [
'account',
],
},
},
default: 0,
required: true,
description: 'ID of the account to delete.',
},
// ----------------------------------
// account:get
// ----------------------------------
{
displayName: 'Account ID',
name: 'accountId',
type: 'number',
displayOptions: {
show: {
operation: [
'get',
],
resource: [
'account',
],
},
},
default: 0,
required: true,
description: 'ID of the account to get.',
},
// ----------------------------------
// account:getAll
// ----------------------------------
...activeCampaignDefaultGetAllProperties('account', 'getAll'),
{
displayName: 'Filters',
name: 'filters',
type: 'collection',
placeholder: 'Add Filter',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'account',
],
},
},
default: {},
options: [
{
displayName: 'Search',
name: 'search',
type: 'string',
default: '',
description: 'Search by name',
},
],
},
] as INodeProperties[];

View file

@ -7,6 +7,8 @@ import {
INodeTypeDescription, INodeTypeDescription,
INodeExecutionData, INodeExecutionData,
INodeType, INodeType,
ILoadOptionsFunctions,
INodePropertyOptions,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { import {
@ -45,12 +47,31 @@ import {
connectionFields connectionFields
} from './ConnectionDescription'; } from './ConnectionDescription';
import {
accountFields,
accountOperations
} from "./AccountDescription";
import {
tagFields,
tagOperations
} from "./TagDescription";
import {
accountContactFields,
accountContactOperations
} from "./AccountContactDescription";
import {
contactTagFields,
contactTagOperations,
} from "./ContactTagDescription";
interface CustomProperty { interface CustomProperty {
name: string; name: string;
value: string; value: string;
} }
/** /**
* Add the additional fields to the body * Add the additional fields to the body
* *
@ -63,6 +84,10 @@ function addAdditionalFields(body: IDataObject, additionalFields: IDataObject) {
for (const customProperty of (additionalFields.customProperties as IDataObject)!.property! as CustomProperty[]) { for (const customProperty of (additionalFields.customProperties as IDataObject)!.property! as CustomProperty[]) {
body[customProperty.name] = customProperty.value; body[customProperty.name] = customProperty.value;
} }
} else if (key === 'fieldValues' && (additionalFields.fieldValues as IDataObject).property !== undefined) {
body.fieldValues = (additionalFields.fieldValues as IDataObject).property;
} else if (key === 'fields' && (additionalFields.fields as IDataObject).property !== undefined) {
body.fields = (additionalFields.fields as IDataObject).property;
} else { } else {
body[key] = additionalFields[key]; body[key] = additionalFields[key];
} }
@ -88,7 +113,7 @@ export class ActiveCampaign implements INodeType {
{ {
name: 'activeCampaignApi', name: 'activeCampaignApi',
required: true, required: true,
} },
], ],
properties: [ properties: [
// ---------------------------------- // ----------------------------------
@ -99,18 +124,30 @@ export class ActiveCampaign implements INodeType {
name: 'resource', name: 'resource',
type: 'options', type: 'options',
options: [ options: [
{
name: 'Account',
value: 'account',
},
{
name: 'Account Contact',
value: 'accountContact',
},
{ {
name: 'Contact', name: 'Contact',
value: 'contact', value: 'contact',
}, },
{ {
name: 'Deal', name: 'Contact Tag',
value: 'deal', value: 'contactTag',
}, },
{ {
name: 'Connection', name: 'Connection',
value: 'connection' value: 'connection'
}, },
{
name: 'Deal',
value: 'deal',
},
{ {
name: 'E-commerce Order', name: 'E-commerce Order',
value: 'ecommerceOrder', value: 'ecommerceOrder',
@ -122,7 +159,11 @@ export class ActiveCampaign implements INodeType {
{ {
name: 'E-commerce Order Products', name: 'E-commerce Order Products',
value: 'ecommerceOrderProducts' value: 'ecommerceOrderProducts'
} },
{
name: 'Tag',
value: 'tag',
},
], ],
default: 'contact', default: 'contact',
description: 'The resource to operate on.', description: 'The resource to operate on.',
@ -131,7 +172,11 @@ export class ActiveCampaign implements INodeType {
// ---------------------------------- // ----------------------------------
// operations // operations
// ---------------------------------- // ----------------------------------
...accountOperations,
...contactOperations, ...contactOperations,
...accountContactOperations,
...contactTagOperations,
...tagOperations,
...dealOperations, ...dealOperations,
...connectionOperations, ...connectionOperations,
...ecomOrderOperations, ...ecomOrderOperations,
@ -141,6 +186,26 @@ export class ActiveCampaign implements INodeType {
// ---------------------------------- // ----------------------------------
// fields // fields
// ---------------------------------- // ----------------------------------
// ----------------------------------
// tag
// ----------------------------------
...tagFields,
// ----------------------------------
// tag
// ----------------------------------
...contactTagFields,
// ----------------------------------
// account
// ----------------------------------
...accountFields,
// ----------------------------------
// account
// ----------------------------------
...accountContactFields,
// ---------------------------------- // ----------------------------------
// contact // contact
// ---------------------------------- // ----------------------------------
@ -174,6 +239,40 @@ export class ActiveCampaign implements INodeType {
], ],
}; };
methods = {
loadOptions: {
// Get all the available custom fields to display them to user so that he can
// select them easily
async getContactCustomFields(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = [];
const { fields } = await activeCampaignApiRequest.call(this, 'GET', '/api/3/fields', {});
for (const field of fields) {
const fieldName = field.title;
const fieldId = field.id;
returnData.push({
name: fieldName,
value: fieldId,
});
}
return returnData;
},
// Get all the available custom fields to display them to user so that he can
// select them easily
async getAccountCustomFields(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = [];
const { accountCustomFieldMeta: fields } = await activeCampaignApiRequest.call(this, 'GET', '/api/3/accountCustomFieldMeta', {});
for (const field of fields) {
const fieldName = field.fieldLabel;
const fieldId = field.id;
returnData.push({
name: fieldName,
value: fieldId,
});
}
return returnData;
},
},
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData(); const items = this.getInputData();
@ -254,11 +353,24 @@ export class ActiveCampaign implements INodeType {
requestMethod = 'GET'; requestMethod = 'GET';
returnAll = this.getNodeParameter('returnAll', i) as boolean; returnAll = this.getNodeParameter('returnAll', i) as boolean;
const simple = this.getNodeParameter('simple', i, true) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (returnAll === false) { if (returnAll === false) {
qs.limit = this.getNodeParameter('limit', i) as number; qs.limit = this.getNodeParameter('limit', i) as number;
} }
Object.assign(qs, additionalFields);
if (qs.orderBy) {
qs[qs.orderBy as string] = true;
delete qs.orderBy;
}
if (simple === true) {
dataKey = 'contacts'; dataKey = 'contacts';
}
endpoint = `/api/3/contacts`; endpoint = `/api/3/contacts`;
} else if (operation === 'update') { } else if (operation === 'update') {
@ -278,6 +390,246 @@ export class ActiveCampaign implements INodeType {
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
addAdditionalFields(body.contact as IDataObject, updateFields); addAdditionalFields(body.contact as IDataObject, updateFields);
} else {
throw new Error(`The operation "${operation}" is not known`);
}
} else if (resource === 'account') {
if (operation === 'create') {
// ----------------------------------
// account:create
// ----------------------------------
requestMethod = 'POST';
endpoint = '/api/3/accounts';
dataKey = 'account';
body.account = {
name: this.getNodeParameter('name', i) as string,
} as IDataObject;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
addAdditionalFields(body.account as IDataObject, additionalFields);
} else if (operation === 'delete') {
// ----------------------------------
// account:delete
// ----------------------------------
requestMethod = 'DELETE';
const accountId = this.getNodeParameter('accountId', i) as number;
endpoint = `/api/3/accounts/${accountId}`;
} else if (operation === 'get') {
// ----------------------------------
// account:get
// ----------------------------------
requestMethod = 'GET';
const accountId = this.getNodeParameter('accountId', i) as number;
endpoint = `/api/3/accounts/${accountId}`;
} else if (operation === 'getAll') {
// ----------------------------------
// account:getAll
// ----------------------------------
requestMethod = 'GET';
const simple = this.getNodeParameter('simple', i, true) as boolean;
returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll === false) {
qs.limit = this.getNodeParameter('limit', i) as number;
}
if (simple === true) {
dataKey = 'accounts';
}
endpoint = `/api/3/accounts`;
const filters = this.getNodeParameter('filters', i) as IDataObject;
Object.assign(qs, filters);
} else if (operation === 'update') {
// ----------------------------------
// account:update
// ----------------------------------
requestMethod = 'PUT';
const accountId = this.getNodeParameter('accountId', i) as number;
endpoint = `/api/3/accounts/${accountId}`;
dataKey = 'account';
body.account = {} as IDataObject;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
addAdditionalFields(body.account as IDataObject, updateFields);
} else {
throw new Error(`The operation "${operation}" is not known`);
}
} else if (resource === 'accountContact') {
if (operation === 'create') {
// ----------------------------------
// account:create
// ----------------------------------
requestMethod = 'POST';
endpoint = '/api/3/accountContacts';
dataKey = 'accountContact';
body.accountContact = {
contact: this.getNodeParameter('contact', i) as string,
account: this.getNodeParameter('account', i) as string,
} as IDataObject;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
addAdditionalFields(body.account as IDataObject, additionalFields);
} else if (operation === 'update') {
// ----------------------------------
// accountContact:update
// ----------------------------------
requestMethod = 'PUT';
const accountContactId = this.getNodeParameter('accountContactId', i) as number;
endpoint = `/api/3/accountContacts/${accountContactId}`;
dataKey = 'accountContact';
body.accountContact = {} as IDataObject;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
addAdditionalFields(body.accountContact as IDataObject, updateFields);
} else if (operation === 'delete') {
// ----------------------------------
// accountContact:delete
// ----------------------------------
requestMethod = 'DELETE';
const accountContactId = this.getNodeParameter('accountContactId', i) as number;
endpoint = `/api/3/accountContacts/${accountContactId}`;
} else {
throw new Error(`The operation "${operation}" is not known`);
}
} else if (resource === 'contactTag') {
if (operation === 'add') {
// ----------------------------------
// contactTag:add
// ----------------------------------
requestMethod = 'POST';
endpoint = '/api/3/contactTags';
dataKey = 'contactTag';
body.contactTag = {
contact: this.getNodeParameter('contactId', i) as string,
tag: this.getNodeParameter('tagId', i) as string,
} as IDataObject;
} else if (operation === 'remove') {
// ----------------------------------
// contactTag:remove
// ----------------------------------
requestMethod = 'DELETE';
const contactTagId = this.getNodeParameter('contactTagId', i) as number;
endpoint = `/api/3/contactTags/${contactTagId}`;
} else {
throw new Error(`The operation "${operation}" is not known`);
}
} else if (resource === 'tag') {
if (operation === 'create') {
// ----------------------------------
// tag:create
// ----------------------------------
requestMethod = 'POST';
endpoint = '/api/3/tags';
dataKey = 'tag';
body.tag = {
tag: this.getNodeParameter('name', i) as string,
tagType: this.getNodeParameter('tagType', i) as string,
} as IDataObject;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
addAdditionalFields(body.tag as IDataObject, additionalFields);
} else if (operation === 'delete') {
// ----------------------------------
// tag:delete
// ----------------------------------
requestMethod = 'DELETE';
const tagId = this.getNodeParameter('tagId', i) as number;
endpoint = `/api/3/tags/${tagId}`;
} else if (operation === 'get') {
// ----------------------------------
// tag:get
// ----------------------------------
requestMethod = 'GET';
const tagId = this.getNodeParameter('tagId', i) as number;
endpoint = `/api/3/tags/${tagId}`;
} else if (operation === 'getAll') {
// ----------------------------------
// tags:getAll
// ----------------------------------
requestMethod = 'GET';
const simple = this.getNodeParameter('simple', i, true) as boolean;
returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll === false) {
qs.limit = this.getNodeParameter('limit', i) as number;
}
if (simple === true) {
dataKey = 'tags';
}
endpoint = `/api/3/tags`;
} else if (operation === 'update') {
// ----------------------------------
// tags:update
// ----------------------------------
requestMethod = 'PUT';
const tagId = this.getNodeParameter('tagId', i) as number;
endpoint = `/api/3/tags/${tagId}`;
dataKey = 'tag';
body.tag = {} as IDataObject;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
addAdditionalFields(body.tag as IDataObject, updateFields);
} else { } else {
throw new Error(`The operation "${operation}" is not known`); throw new Error(`The operation "${operation}" is not known`);
} }
@ -358,11 +710,16 @@ export class ActiveCampaign implements INodeType {
requestMethod = 'GET'; requestMethod = 'GET';
const simple = this.getNodeParameter('simple', i, true) as boolean;
returnAll = this.getNodeParameter('returnAll', i) as boolean; returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll === false) { if (returnAll === false) {
qs.limit = this.getNodeParameter('limit', i) as number; qs.limit = this.getNodeParameter('limit', i) as number;
} }
if (simple === true) {
dataKey = 'deals';
}
endpoint = `/api/3/deals`; endpoint = `/api/3/deals`;
} else if (operation === 'createNote') { } else if (operation === 'createNote') {
@ -455,11 +812,16 @@ export class ActiveCampaign implements INodeType {
requestMethod = 'GET'; requestMethod = 'GET';
const simple = this.getNodeParameter('simple', i, true) as boolean;
returnAll = this.getNodeParameter('returnAll', i) as boolean; returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll === false) { if (returnAll === false) {
qs.limit = this.getNodeParameter('limit', i) as number; qs.limit = this.getNodeParameter('limit', i) as number;
} }
if (simple === true) {
dataKey = 'connections';
}
endpoint = `/api/3/connections`; endpoint = `/api/3/connections`;
} else { } else {
@ -548,11 +910,16 @@ export class ActiveCampaign implements INodeType {
requestMethod = 'GET'; requestMethod = 'GET';
const simple = this.getNodeParameter('simple', i, true) as boolean;
returnAll = this.getNodeParameter('returnAll', i) as boolean; returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll === false) { if (returnAll === false) {
qs.limit = this.getNodeParameter('limit', i) as number; qs.limit = this.getNodeParameter('limit', i) as number;
} }
if (simple === true) {
dataKey = 'ecomOrders';
}
endpoint = `/api/3/ecomOrders`; endpoint = `/api/3/ecomOrders`;
} else { } else {
@ -633,11 +1000,16 @@ export class ActiveCampaign implements INodeType {
requestMethod = 'GET'; requestMethod = 'GET';
const simple = this.getNodeParameter('simple', i, true) as boolean;
returnAll = this.getNodeParameter('returnAll', i) as boolean; returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll === false) { if (returnAll === false) {
qs.limit = this.getNodeParameter('limit', i) as number; qs.limit = this.getNodeParameter('limit', i) as number;
} }
if (simple === true) {
dataKey = 'ecomCustomers';
}
endpoint = `/api/3/ecomCustomers`; endpoint = `/api/3/ecomCustomers`;
} else { } else {
@ -662,6 +1034,8 @@ export class ActiveCampaign implements INodeType {
requestMethod = 'GET'; requestMethod = 'GET';
//dataKey = 'ecomOrderProducts';
const orderId = this.getNodeParameter('orderId', i) as number; const orderId = this.getNodeParameter('orderId', i) as number;
endpoint = `/api/3/ecomOrders/${orderId}/orderProducts`; endpoint = `/api/3/ecomOrders/${orderId}/orderProducts`;
@ -672,11 +1046,16 @@ export class ActiveCampaign implements INodeType {
requestMethod = 'GET'; requestMethod = 'GET';
const simple = this.getNodeParameter('simple', i, true) as boolean;
returnAll = this.getNodeParameter('returnAll', i) as boolean; returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll === false) { if (returnAll === false) {
qs.limit = this.getNodeParameter('limit', i) as number; qs.limit = this.getNodeParameter('limit', i) as number;
} }
if (simple === true) {
dataKey = 'ecomOrderProducts';
}
endpoint = `/api/3/ecomOrderProducts`; endpoint = `/api/3/ecomOrderProducts`;
} else { } else {

View file

@ -1,4 +1,10 @@
import { INodeProperties } from "n8n-workflow"; import {
INodeProperties,
} from "n8n-workflow";
import {
activeCampaignDefaultGetAllProperties,
} from "./GenericFunctions";
export const connectionOperations = [ export const connectionOperations = [
{ {
@ -278,45 +284,6 @@ export const connectionFields = [
// ---------------------------------- // ----------------------------------
// connection:getAll // connection:getAll
// ---------------------------------- // ----------------------------------
{ ...activeCampaignDefaultGetAllProperties('connection', 'getAll'),
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'connection',
],
},
},
default: false,
description: 'If all results should be returned or only up to a given limit.',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'connection',
],
returnAll: [
false,
],
},
},
typeOptions: {
minValue: 1,
maxValue: 500,
},
default: 100,
description: 'How many results to return.',
},
] as INodeProperties[]; ] as INodeProperties[];

View file

@ -1,4 +1,10 @@
import { INodeProperties } from "n8n-workflow"; import {
INodeProperties,
} from 'n8n-workflow';
import {
activeCampaignDefaultGetAllProperties,
} from './GenericFunctions';
export const contactOperations = [ export const contactOperations = [
{ {
@ -100,6 +106,42 @@ export const contactFields = [
}, },
default: {}, default: {},
options: [ options: [
{
displayName: 'Custom Fields',
name: 'fieldValues',
placeholder: 'Add Custom Fields',
description: 'Adds a custom fields to set also values which have not been predefined.',
type: 'fixedCollection',
typeOptions: {
multipleValues: true,
},
default: {},
options: [
{
name: 'property',
displayName: 'Custom Field',
values: [
{
displayName: 'Field ID',
name: 'field',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getContactCustomFields',
},
default: '',
description: 'ID of the field to set.',
},
{
displayName: 'Field Value',
name: 'value',
type: 'string',
default: '',
description: 'Value of the field to set.',
},
]
},
],
},
{ {
displayName: 'First Name', displayName: 'First Name',
name: 'firstName', name: 'firstName',
@ -121,39 +163,6 @@ export const contactFields = [
default: '', default: '',
description: 'Phone number of the contact.', description: 'Phone number of the contact.',
}, },
{
displayName: 'Custom Properties',
name: 'customProperties',
placeholder: 'Add Custom Property',
description: 'Adds a custom property to set also values which have not been predefined.',
type: 'fixedCollection',
typeOptions: {
multipleValues: true,
},
default: {},
options: [
{
name: 'property',
displayName: 'Property',
values: [
{
displayName: 'Property Name',
name: 'name',
type: 'string',
default: '',
description: 'Name of the property to set.',
},
{
displayName: 'Property Value',
name: 'value',
type: 'string',
default: '',
description: 'Value of the property to set.',
},
]
},
],
},
], ],
}, },
@ -196,6 +205,42 @@ export const contactFields = [
}, },
default: {}, default: {},
options: [ options: [
{
displayName: 'Custom Fields',
name: 'fieldValues',
placeholder: 'Add Custom Fields',
description: 'Adds a custom fields to set also values which have not been predefined.',
type: 'fixedCollection',
typeOptions: {
multipleValues: true,
},
default: {},
options: [
{
name: 'property',
displayName: 'Custom Field',
values: [
{
displayName: 'Field ID',
name: 'field',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getContactCustomFields',
},
default: '',
description: 'ID of the field to set.',
},
{
displayName: 'Field Value',
name: 'value',
type: 'string',
default: '',
description: 'Value of the field to set.',
},
]
},
],
},
{ {
displayName: 'Email', displayName: 'Email',
name: 'email', name: 'email',
@ -224,39 +269,6 @@ export const contactFields = [
default: '', default: '',
description: 'Phone number of the contact.', description: 'Phone number of the contact.',
}, },
{
displayName: 'Custom Properties',
name: 'customProperties',
placeholder: 'Add Custom Property',
description: 'Adds a custom property to set also values which have not been predefined.',
type: 'fixedCollection',
typeOptions: {
multipleValues: true,
},
default: {},
options: [
{
name: 'property',
displayName: 'Property',
values: [
{
displayName: 'Property Name',
name: 'name',
type: 'string',
default: '',
description: 'Name of the property to set.',
},
{
displayName: 'Property Value',
name: 'value',
type: 'string',
default: '',
description: 'Value of the property to set.',
},
]
},
],
},
], ],
}, },
@ -307,10 +319,12 @@ export const contactFields = [
// ---------------------------------- // ----------------------------------
// contact:getAll // contact:getAll
// ---------------------------------- // ----------------------------------
...activeCampaignDefaultGetAllProperties('contact', 'getAll'),
{ {
displayName: 'Return All', displayName: 'Additional Fields',
name: 'returnAll', name: 'additionalFields',
type: 'boolean', type: 'collection',
placeholder: 'Add Field',
displayOptions: { displayOptions: {
show: { show: {
operation: [ operation: [
@ -321,31 +335,179 @@ export const contactFields = [
], ],
}, },
}, },
default: false, default: {},
description: 'If all results should be returned or only up to a given limit.', options: [
{
displayName: 'Datetime',
name: 'datetime',
type: 'dateTime',
default: '',
description: 'Contacts created on the specified date',
}, },
{ {
displayName: 'Limit', displayName: 'Email',
name: 'limit', name: 'email',
type: 'number', type: 'string',
displayOptions: { default: '',
show: { description: 'Email address of the contact you want to get',
operation: [
'getAll',
],
resource: [
'contact',
],
returnAll: [
false,
],
}, },
{
displayName: 'Email Like',
name: 'email_like',
type: 'string',
default: '',
description: 'Filter contacts that contain the given value in the email address',
}, },
typeOptions: { {
minValue: 1, displayName: 'Exclude',
maxValue: 500, name: 'exclude',
type: 'string',
default: '',
description: 'Exclude from the response the contact with the given ID',
}, },
default: 100, {
description: 'How many results to return.', displayName: 'Form ID',
name: 'formid',
type: 'string',
default: '',
description: 'Filter contacts associated with the given form',
},
{
displayName: 'List ID',
name: 'listid',
type: 'string',
default: '',
description: 'Filter contacts associated with the given list',
},
{
displayName: 'Search',
name: 'search',
type: 'string',
default: '',
description: 'Filter contacts that match the given value in the contact names, organization, phone or email',
},
{
displayName: 'Segment ID',
name: 'segmentid',
type: 'string',
default: '',
description: 'Return only contacts that match a list segment',
},
{
displayName: 'Series ID',
name: 'seriesid',
type: 'string',
default: '',
description: 'Filter contacts associated with the given automation',
},
{
displayName: 'Status',
name: 'status',
type: 'options',
options: [
{
name: 'Any',
value: -1,
},
{
name: 'Unconfirmed',
value: 0,
},
{
name: 'Active',
value: 1,
},
{
name: 'Unsubscribed',
value: 2,
},
{
name: 'Bounced',
value: 3,
},
],
default: '',
},
{
displayName: 'Tag ID',
name: 'tagid',
type: 'string',
default: '',
description: 'Filter contacts associated with the given tag',
},
{
displayName: 'Created Before',
name: 'filters[created_before]',
type: 'dateTime',
default: '',
description: 'Filter contacts that were created prior to this date',
},
{
displayName: 'Created After',
name: 'filters[created_after]',
type: 'dateTime',
default: '',
description: 'Filter contacts that were created after this date',
},
{
displayName: 'Updated Before',
name: 'filters[updated_before]',
type: 'dateTime',
default: '',
description: 'Filter contacts that were updated before this date',
},
{
displayName: 'Updated After',
name: 'filters[updated_after]',
type: 'dateTime',
default: '',
description: 'Filter contacts that were updated after this date',
},
{
displayName: 'Wait ID',
name: 'waitid',
type: 'string',
default: '',
description: 'Filter by contacts in the wait queue of an automation block',
},
{
displayName: 'Order By',
name: 'orderBy',
type: 'options',
options: [
{
name: 'Creation Date',
value: 'orders[cdate]',
description: 'Order contacts by creation date',
},
{
name: 'Email',
value: 'orders[email]',
description: 'Order contacts by email',
},
{
name: 'First Name',
value: 'orders[first_name]',
description: 'Order contacts by first name',
},
{
name: 'Last Name',
value: 'orders[last_name]',
description: 'Order contacts by last name',
},
{
name: 'Name',
value: 'orders[name]',
description: 'Order contacts by full name',
},
{
name: 'Score',
value: 'orders[score]',
description: 'Order contacts by score',
},
],
default: '',
},
],
}, },
] as INodeProperties[]; ] as INodeProperties[];

View file

@ -0,0 +1,95 @@
import {
INodeProperties,
} from 'n8n-workflow';
export const contactTagOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'contactTag',
],
},
},
options: [
{
name: 'Add',
value: 'add',
description: 'Add a tag to a contact',
},
{
name: 'Remove',
value: 'remove',
description: 'Remove a tag from a contact',
},
],
default: 'add',
description: 'The operation to perform.',
},
] as INodeProperties[];
export const contactTagFields = [
// ----------------------------------
// contactTag:add
// ----------------------------------
{
displayName: 'Tag ID',
name: 'tagId',
type: 'number',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'add',
],
resource: [
'contactTag',
],
},
},
description: 'Tag ID',
},
{
displayName: 'Contact ID',
name: 'contactId',
type: 'number',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'add',
],
resource: [
'contactTag',
],
},
},
description: 'Contact ID',
},
// ----------------------------------
// contactTag:delete
// ----------------------------------
{
displayName: 'Contact Tag ID',
name: 'contactTagId',
type: 'number',
displayOptions: {
show: {
operation: [
'remove',
],
resource: [
'contactTag',
],
},
},
default: 0,
required: true,
description: 'ID of the contact tag to delete.',
},
] as INodeProperties[];

View file

@ -1,6 +1,14 @@
import { INodeProperties } from "n8n-workflow"; import {
INodeProperties,
} from "n8n-workflow";
import { allCurrencies } from './currencies'; import {
allCurrencies,
} from './currencies';
import {
activeCampaignDefaultGetAllProperties,
} from "./GenericFunctions";
export const dealOperations = [ export const dealOperations = [
{ {
@ -387,47 +395,7 @@ export const dealFields = [
// ---------------------------------- // ----------------------------------
// deal:getAll // deal:getAll
// ---------------------------------- // ----------------------------------
{ ...activeCampaignDefaultGetAllProperties('deal', 'getAll'),
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'deal',
],
},
},
default: false,
description: 'If all results should be returned or only up to a given limit.',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'deal',
],
returnAll: [
false,
],
},
},
typeOptions: {
minValue: 1,
maxValue: 500,
},
default: 100,
description: 'How many results to return.',
},
// ---------------------------------- // ----------------------------------
// dealNote:create // dealNote:create

View file

@ -1,4 +1,10 @@
import { INodeProperties } from "n8n-workflow"; import {
INodeProperties,
} from 'n8n-workflow';
import {
activeCampaignDefaultGetAllProperties,
} from './GenericFunctions';
export const ecomCustomerOperations = [ export const ecomCustomerOperations = [
{ {
@ -246,45 +252,5 @@ export const ecomCustomerFields = [
// ---------------------------------- // ----------------------------------
// ecommerceCustomer:getAll // ecommerceCustomer:getAll
// ---------------------------------- // ----------------------------------
{ ...activeCampaignDefaultGetAllProperties('ecommerceCustomer', 'getAll'),
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'ecommerceCustomer',
],
},
},
default: false,
description: 'If all results should be returned or only up to a given limit.',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'ecommerceCustomer',
],
returnAll: [
false,
],
},
},
typeOptions: {
minValue: 1,
maxValue: 500,
},
default: 100,
description: 'How many results to return.',
},
] as INodeProperties[]; ] as INodeProperties[];

View file

@ -1,6 +1,14 @@
import { INodeProperties } from "n8n-workflow"; import {
INodeProperties,
} from "n8n-workflow";
import { allCurrencies } from './currencies'; import {
allCurrencies,
} from './currencies';
import {
activeCampaignDefaultGetAllProperties,
} from './GenericFunctions';
export const ecomOrderOperations = [ export const ecomOrderOperations = [
{ {
@ -672,45 +680,6 @@ export const ecomOrderFields = [
// ---------------------------------- // ----------------------------------
// ecommerceOrder:getAll // ecommerceOrder:getAll
// ---------------------------------- // ----------------------------------
{ ...activeCampaignDefaultGetAllProperties('ecommerceOrder', 'getAll'),
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'ecommerceOrder',
],
},
},
default: false,
description: 'If all results should be returned or only up to a given limit.',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'ecommerceOrder',
],
returnAll: [
false,
],
},
},
typeOptions: {
minValue: 1,
maxValue: 500,
},
default: 100,
description: 'How many results to return.',
},
] as INodeProperties[]; ] as INodeProperties[];

View file

@ -1,4 +1,10 @@
import { INodeProperties } from "n8n-workflow"; import {
INodeProperties,
} from "n8n-workflow";
import {
activeCampaignDefaultGetAllProperties,
} from './GenericFunctions';
export const ecomOrderProductsOperations = [ export const ecomOrderProductsOperations = [
{ {
@ -80,45 +86,5 @@ export const ecomOrderProductsFields = [
// ---------------------------------- // ----------------------------------
// ecommerceOrderProducts:getAll // ecommerceOrderProducts:getAll
// ---------------------------------- // ----------------------------------
{ ...activeCampaignDefaultGetAllProperties('ecommerceOrderProducts', 'getAll'),
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'ecommerceOrderProducts',
],
},
},
default: false,
description: 'If all results should be returned or only up to a given limit.',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'ecommerceOrderProducts',
],
returnAll: [
false,
],
},
},
typeOptions: {
minValue: 1,
maxValue: 500,
},
default: 100,
description: 'How many results to return.',
},
] as INodeProperties[]; ] as INodeProperties[];

View file

@ -4,7 +4,7 @@ import {
} from 'n8n-core'; } from 'n8n-core';
import { import {
IDataObject, ILoadOptionsFunctions, IDataObject, ILoadOptionsFunctions, INodeProperties,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { OptionsWithUri } from 'request'; import { OptionsWithUri } from 'request';
@ -49,6 +49,8 @@ export async function activeCampaignApiRequest(this: IHookFunctions | IExecuteFu
options.body = body; options.body = body;
} }
console.log(options);
try { try {
const responseData = await this.helpers.request!(options); const responseData = await this.helpers.request!(options);
@ -124,3 +126,66 @@ export async function activeCampaignApiRequestAllItems(this: IHookFunctions | IE
return returnData; return returnData;
} }
export function activeCampaignDefaultGetAllProperties (resource: string, operation: string): INodeProperties [] {
return [
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
operation: [
operation,
],
resource: [
resource,
],
},
},
default: false,
description: 'If all results should be returned or only up to a given limit.',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
operation: [
operation,
],
resource: [
resource,
],
returnAll: [
false,
],
},
},
typeOptions: {
minValue: 1,
maxValue: 500,
},
default: 100,
description: 'How many results to return.',
},
{
displayName: 'Simple',
name: 'simple',
type: 'boolean',
displayOptions: {
show: {
operation: [
operation,
],
resource: [
resource,
],
},
},
default: true,
description: 'When set to true a simplify version of the response will be used else the raw data will be used',
},
];
}

View file

@ -0,0 +1,232 @@
import {
INodeProperties,
} from 'n8n-workflow';
import {
activeCampaignDefaultGetAllProperties,
} from './GenericFunctions';
export const tagOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'tag',
],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a tag',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a tag',
},
{
name: 'Get',
value: 'get',
description: 'Get data of a tag',
},
{
name: 'Get All',
value: 'getAll',
description: 'Get data of all tags',
},
{
name: 'Update',
value: 'update',
description: 'Update a tag',
},
],
default: 'create',
description: 'The operation to perform.',
},
] as INodeProperties[];
export const tagFields = [
// ----------------------------------
// contact:create
// ----------------------------------
{
displayName: 'Type',
name: 'tagType',
type: 'options',
default: 'contact',
required: true,
displayOptions: {
show: {
operation: [
'create',
],
resource: [
'tag',
],
},
},
options: [
{
name: 'Contact',
value: 'contact',
description: 'Tag contact',
},
{
name: 'Template',
value: 'template',
description: 'Tag template',
},
],
description: 'Tag-type of the new tag',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'create',
],
resource: [
'tag',
],
},
},
description: 'Name of the new tag',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: [
'create',
],
resource: [
'tag',
],
},
},
default: {},
options: [
{
displayName: 'Description',
name: 'description',
type: 'string',
default: '',
description: 'Description of the new tag',
},
],
},
// ----------------------------------
// tag:update
// ----------------------------------
{
displayName: 'Tag ID',
name: 'tagId',
type: 'number',
displayOptions: {
show: {
operation: [
'update',
],
resource: [
'tag',
],
},
},
default: 0,
required: true,
description: 'ID of the tag to update.',
},
{
displayName: 'Update Fields',
name: 'updateFields',
type: 'collection',
description: 'The fields to update.',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: [
'update',
],
resource: [
'tag',
],
},
},
default: {},
options: [
{
displayName: 'Tag',
name: 'tag',
type: 'string',
default: '',
description: 'Name of the contact.',
},
{
displayName: 'Description',
name: 'description',
type: 'string',
default: '',
description: 'Description of the tag being updated',
},
],
},
// ----------------------------------
// tag:delete
// ----------------------------------
{
displayName: 'Tag ID',
name: 'tagId',
type: 'number',
displayOptions: {
show: {
operation: [
'delete',
],
resource: [
'tag',
],
},
},
default: 0,
required: true,
description: 'ID of the tag to delete.',
},
// ----------------------------------
// contact:get
// ----------------------------------
{
displayName: 'Tag ID',
name: 'tagId',
type: 'number',
displayOptions: {
show: {
operation: [
'get',
],
resource: [
'tag',
],
},
},
default: 0,
required: true,
description: 'ID of the tag to get.',
},
// ----------------------------------
// tag:getAll
// ----------------------------------
...activeCampaignDefaultGetAllProperties('tag', 'getAll')
] as INodeProperties[];