first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.actionNetwork",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Sales", "Marketing"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/actionnetwork/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.actionnetwork/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,498 @@
|
||||
import type {
|
||||
IDataObject,
|
||||
IExecuteFunctions,
|
||||
INodeExecutionData,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
attendanceFields,
|
||||
attendanceOperations,
|
||||
eventFields,
|
||||
eventOperations,
|
||||
personFields,
|
||||
personOperations,
|
||||
personTagFields,
|
||||
personTagOperations,
|
||||
petitionFields,
|
||||
petitionOperations,
|
||||
signatureFields,
|
||||
signatureOperations,
|
||||
tagFields,
|
||||
tagOperations,
|
||||
} from './descriptions';
|
||||
import {
|
||||
actionNetworkApiRequest,
|
||||
adjustEventPayload,
|
||||
adjustPersonPayload,
|
||||
adjustPetitionPayload,
|
||||
handleListing,
|
||||
makeOsdiLink,
|
||||
resourceLoaders,
|
||||
simplifyResponse,
|
||||
} from './GenericFunctions';
|
||||
import type {
|
||||
AllFieldsUi,
|
||||
EmailAddressUi,
|
||||
Operation,
|
||||
PersonResponse,
|
||||
Resource,
|
||||
Response,
|
||||
} from './types';
|
||||
|
||||
export class ActionNetwork implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Action Network',
|
||||
name: 'actionNetwork',
|
||||
icon: 'file:actionNetwork.svg',
|
||||
group: ['transform'],
|
||||
version: 1,
|
||||
subtitle: '={{$parameter["resource"] + ": " + $parameter["operation"]}}',
|
||||
description: 'Consume the Action Network API',
|
||||
defaults: {
|
||||
name: 'Action Network',
|
||||
},
|
||||
usableAsTool: true,
|
||||
inputs: [NodeConnectionTypes.Main],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'actionNetworkApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
options: [
|
||||
{
|
||||
name: 'Attendance',
|
||||
value: 'attendance',
|
||||
},
|
||||
{
|
||||
name: 'Event',
|
||||
value: 'event',
|
||||
},
|
||||
{
|
||||
name: 'Person',
|
||||
value: 'person',
|
||||
},
|
||||
{
|
||||
name: 'Person Tag',
|
||||
value: 'personTag',
|
||||
},
|
||||
{
|
||||
name: 'Petition',
|
||||
value: 'petition',
|
||||
},
|
||||
{
|
||||
name: 'Signature',
|
||||
value: 'signature',
|
||||
},
|
||||
{
|
||||
name: 'Tag',
|
||||
value: 'tag',
|
||||
},
|
||||
],
|
||||
default: 'attendance',
|
||||
},
|
||||
...attendanceOperations,
|
||||
...attendanceFields,
|
||||
...eventOperations,
|
||||
...eventFields,
|
||||
...personOperations,
|
||||
...personFields,
|
||||
...petitionOperations,
|
||||
...petitionFields,
|
||||
...signatureOperations,
|
||||
...signatureFields,
|
||||
...tagOperations,
|
||||
...tagFields,
|
||||
...personTagOperations,
|
||||
...personTagFields,
|
||||
],
|
||||
};
|
||||
|
||||
methods = {
|
||||
loadOptions: resourceLoaders,
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const returnData: IDataObject[] = [];
|
||||
|
||||
const resource = this.getNodeParameter('resource', 0) as Resource;
|
||||
const operation = this.getNodeParameter('operation', 0) as Operation;
|
||||
|
||||
let response;
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
try {
|
||||
if (resource === 'attendance') {
|
||||
// **********************************************************************
|
||||
// attendance
|
||||
// **********************************************************************
|
||||
|
||||
// https://actionnetwork.org/docs/v2/attendances
|
||||
|
||||
if (operation === 'create') {
|
||||
// ----------------------------------------
|
||||
// attendance: create
|
||||
// ----------------------------------------
|
||||
|
||||
const personId = this.getNodeParameter('personId', i) as string;
|
||||
const eventId = this.getNodeParameter('eventId', i);
|
||||
|
||||
const body = makeOsdiLink(personId) as IDataObject;
|
||||
|
||||
const endpoint = `/events/${eventId}/attendances`;
|
||||
response = await actionNetworkApiRequest.call(this, 'POST', endpoint, body);
|
||||
} else if (operation === 'get') {
|
||||
// ----------------------------------------
|
||||
// attendance: get
|
||||
// ----------------------------------------
|
||||
|
||||
const eventId = this.getNodeParameter('eventId', i);
|
||||
const attendanceId = this.getNodeParameter('attendanceId', i);
|
||||
|
||||
const endpoint = `/events/${eventId}/attendances/${attendanceId}`;
|
||||
response = await actionNetworkApiRequest.call(this, 'GET', endpoint);
|
||||
} else if (operation === 'getAll') {
|
||||
// ----------------------------------------
|
||||
// attendance: getAll
|
||||
// ----------------------------------------
|
||||
|
||||
const eventId = this.getNodeParameter('eventId', i);
|
||||
|
||||
const endpoint = `/events/${eventId}/attendances`;
|
||||
response = await handleListing.call(this, 'GET', endpoint);
|
||||
}
|
||||
} else if (resource === 'event') {
|
||||
// **********************************************************************
|
||||
// event
|
||||
// **********************************************************************
|
||||
|
||||
// https://actionnetwork.org/docs/v2/events
|
||||
|
||||
if (operation === 'create') {
|
||||
// ----------------------------------------
|
||||
// event: create
|
||||
// ----------------------------------------
|
||||
|
||||
const body = {
|
||||
origin_system: this.getNodeParameter('originSystem', i),
|
||||
title: this.getNodeParameter('title', i),
|
||||
} as IDataObject;
|
||||
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i) as AllFieldsUi;
|
||||
|
||||
if (Object.keys(additionalFields).length) {
|
||||
Object.assign(body, adjustEventPayload(additionalFields));
|
||||
}
|
||||
|
||||
response = await actionNetworkApiRequest.call(this, 'POST', '/events', body);
|
||||
} else if (operation === 'get') {
|
||||
// ----------------------------------------
|
||||
// event: get
|
||||
// ----------------------------------------
|
||||
|
||||
const eventId = this.getNodeParameter('eventId', i);
|
||||
|
||||
response = await actionNetworkApiRequest.call(this, 'GET', `/events/${eventId}`);
|
||||
} else if (operation === 'getAll') {
|
||||
// ----------------------------------------
|
||||
// event: getAll
|
||||
// ----------------------------------------
|
||||
|
||||
response = await handleListing.call(this, 'GET', '/events');
|
||||
}
|
||||
} else if (resource === 'person') {
|
||||
// **********************************************************************
|
||||
// person
|
||||
// **********************************************************************
|
||||
|
||||
// https://actionnetwork.org/docs/v2/people
|
||||
|
||||
if (operation === 'create') {
|
||||
// ----------------------------------------
|
||||
// person: create
|
||||
// ----------------------------------------
|
||||
|
||||
const emailAddresses = this.getNodeParameter('email_addresses', i) as EmailAddressUi;
|
||||
|
||||
const body = {
|
||||
person: {
|
||||
email_addresses: [emailAddresses.email_addresses_fields], // only one accepted by API
|
||||
},
|
||||
} as IDataObject;
|
||||
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
|
||||
if (Object.keys(additionalFields).length && body.person) {
|
||||
Object.assign(body.person, adjustPersonPayload(additionalFields));
|
||||
}
|
||||
|
||||
response = await actionNetworkApiRequest.call(this, 'POST', '/people', body);
|
||||
} else if (operation === 'get') {
|
||||
// ----------------------------------------
|
||||
// person: get
|
||||
// ----------------------------------------
|
||||
|
||||
const personId = this.getNodeParameter('personId', i);
|
||||
|
||||
response = (await actionNetworkApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/people/${personId}`,
|
||||
)) as PersonResponse;
|
||||
} else if (operation === 'getAll') {
|
||||
// ----------------------------------------
|
||||
// person: getAll
|
||||
// ----------------------------------------
|
||||
|
||||
response = (await handleListing.call(this, 'GET', '/people')) as PersonResponse[];
|
||||
} else if (operation === 'update') {
|
||||
// ----------------------------------------
|
||||
// person: update
|
||||
// ----------------------------------------
|
||||
|
||||
const personId = this.getNodeParameter('personId', i);
|
||||
const body = {} as IDataObject;
|
||||
const updateFields = this.getNodeParameter('updateFields', i);
|
||||
|
||||
if (Object.keys(updateFields).length) {
|
||||
Object.assign(body, adjustPersonPayload(updateFields));
|
||||
} else {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
`Please enter at least one field to update for the ${resource}.`,
|
||||
{ itemIndex: i },
|
||||
);
|
||||
}
|
||||
|
||||
response = await actionNetworkApiRequest.call(this, 'PUT', `/people/${personId}`, body);
|
||||
}
|
||||
} else if (resource === 'petition') {
|
||||
// **********************************************************************
|
||||
// petition
|
||||
// **********************************************************************
|
||||
|
||||
// https://actionnetwork.org/docs/v2/petitions
|
||||
|
||||
if (operation === 'create') {
|
||||
// ----------------------------------------
|
||||
// petition: create
|
||||
// ----------------------------------------
|
||||
|
||||
const body = {
|
||||
origin_system: this.getNodeParameter('originSystem', i),
|
||||
title: this.getNodeParameter('title', i),
|
||||
} as IDataObject;
|
||||
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i) as AllFieldsUi;
|
||||
|
||||
if (Object.keys(additionalFields).length) {
|
||||
Object.assign(body, adjustPetitionPayload(additionalFields));
|
||||
}
|
||||
|
||||
response = await actionNetworkApiRequest.call(this, 'POST', '/petitions', body);
|
||||
} else if (operation === 'get') {
|
||||
// ----------------------------------------
|
||||
// petition: get
|
||||
// ----------------------------------------
|
||||
|
||||
const petitionId = this.getNodeParameter('petitionId', i);
|
||||
|
||||
const endpoint = `/petitions/${petitionId}`;
|
||||
response = await actionNetworkApiRequest.call(this, 'GET', endpoint);
|
||||
} else if (operation === 'getAll') {
|
||||
// ----------------------------------------
|
||||
// petition: getAll
|
||||
// ----------------------------------------
|
||||
|
||||
response = await handleListing.call(this, 'GET', '/petitions');
|
||||
} else if (operation === 'update') {
|
||||
// ----------------------------------------
|
||||
// petition: update
|
||||
// ----------------------------------------
|
||||
|
||||
const petitionId = this.getNodeParameter('petitionId', i);
|
||||
const body = {} as IDataObject;
|
||||
const updateFields = this.getNodeParameter('updateFields', i) as AllFieldsUi;
|
||||
|
||||
if (Object.keys(updateFields).length) {
|
||||
Object.assign(body, adjustPetitionPayload(updateFields));
|
||||
} else {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
`Please enter at least one field to update for the ${resource}.`,
|
||||
{ itemIndex: i },
|
||||
);
|
||||
}
|
||||
|
||||
response = await actionNetworkApiRequest.call(
|
||||
this,
|
||||
'PUT',
|
||||
`/petitions/${petitionId}`,
|
||||
body,
|
||||
);
|
||||
}
|
||||
} else if (resource === 'signature') {
|
||||
// **********************************************************************
|
||||
// signature
|
||||
// **********************************************************************
|
||||
|
||||
// https://actionnetwork.org/docs/v2/signatures
|
||||
|
||||
if (operation === 'create') {
|
||||
// ----------------------------------------
|
||||
// signature: create
|
||||
// ----------------------------------------
|
||||
|
||||
const personId = this.getNodeParameter('personId', i) as string;
|
||||
const petitionId = this.getNodeParameter('petitionId', i);
|
||||
|
||||
const body = makeOsdiLink(personId) as IDataObject;
|
||||
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
|
||||
if (Object.keys(additionalFields).length) {
|
||||
Object.assign(body, additionalFields);
|
||||
}
|
||||
|
||||
const endpoint = `/petitions/${petitionId}/signatures`;
|
||||
response = await actionNetworkApiRequest.call(this, 'POST', endpoint, body);
|
||||
} else if (operation === 'get') {
|
||||
// ----------------------------------------
|
||||
// signature: get
|
||||
// ----------------------------------------
|
||||
|
||||
const petitionId = this.getNodeParameter('petitionId', i);
|
||||
const signatureId = this.getNodeParameter('signatureId', i);
|
||||
|
||||
const endpoint = `/petitions/${petitionId}/signatures/${signatureId}`;
|
||||
response = await actionNetworkApiRequest.call(this, 'GET', endpoint);
|
||||
} else if (operation === 'getAll') {
|
||||
// ----------------------------------------
|
||||
// signature: getAll
|
||||
// ----------------------------------------
|
||||
|
||||
const petitionId = this.getNodeParameter('petitionId', i);
|
||||
|
||||
const endpoint = `/petitions/${petitionId}/signatures`;
|
||||
response = await handleListing.call(this, 'GET', endpoint);
|
||||
} else if (operation === 'update') {
|
||||
// ----------------------------------------
|
||||
// signature: update
|
||||
// ----------------------------------------
|
||||
|
||||
const petitionId = this.getNodeParameter('petitionId', i);
|
||||
const signatureId = this.getNodeParameter('signatureId', i);
|
||||
const body = {};
|
||||
const updateFields = this.getNodeParameter('updateFields', i) as AllFieldsUi;
|
||||
|
||||
if (Object.keys(updateFields).length) {
|
||||
Object.assign(body, updateFields);
|
||||
} else {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
`Please enter at least one field to update for the ${resource}.`,
|
||||
{ itemIndex: i },
|
||||
);
|
||||
}
|
||||
|
||||
const endpoint = `/petitions/${petitionId}/signatures/${signatureId}`;
|
||||
response = await actionNetworkApiRequest.call(this, 'PUT', endpoint, body);
|
||||
}
|
||||
} else if (resource === 'tag') {
|
||||
// **********************************************************************
|
||||
// tag
|
||||
// **********************************************************************
|
||||
|
||||
// https://actionnetwork.org/docs/v2/tags
|
||||
|
||||
if (operation === 'create') {
|
||||
// ----------------------------------------
|
||||
// tag: create
|
||||
// ----------------------------------------
|
||||
|
||||
const body = {
|
||||
name: this.getNodeParameter('name', i),
|
||||
} as IDataObject;
|
||||
|
||||
response = await actionNetworkApiRequest.call(this, 'POST', '/tags', body);
|
||||
} else if (operation === 'get') {
|
||||
// ----------------------------------------
|
||||
// tag: get
|
||||
// ----------------------------------------
|
||||
|
||||
const tagId = this.getNodeParameter('tagId', i);
|
||||
|
||||
response = await actionNetworkApiRequest.call(this, 'GET', `/tags/${tagId}`);
|
||||
} else if (operation === 'getAll') {
|
||||
// ----------------------------------------
|
||||
// tag: getAll
|
||||
// ----------------------------------------
|
||||
|
||||
response = await handleListing.call(this, 'GET', '/tags');
|
||||
}
|
||||
} else if (resource === 'personTag') {
|
||||
// **********************************************************************
|
||||
// personTag
|
||||
// **********************************************************************
|
||||
|
||||
// https://actionnetwork.org/docs/v2/taggings
|
||||
|
||||
if (operation === 'add') {
|
||||
// ----------------------------------------
|
||||
// personTag: add
|
||||
// ----------------------------------------
|
||||
|
||||
const personId = this.getNodeParameter('personId', i) as string;
|
||||
const tagId = this.getNodeParameter('tagId', i);
|
||||
|
||||
const body = makeOsdiLink(personId) as IDataObject;
|
||||
|
||||
const endpoint = `/tags/${tagId}/taggings`;
|
||||
response = await actionNetworkApiRequest.call(this, 'POST', endpoint, body);
|
||||
} else if (operation === 'remove') {
|
||||
// ----------------------------------------
|
||||
// personTag: remove
|
||||
// ----------------------------------------
|
||||
|
||||
const tagId = this.getNodeParameter('tagId', i);
|
||||
const taggingId = this.getNodeParameter('taggingId', i);
|
||||
|
||||
const endpoint = `/tags/${tagId}/taggings/${taggingId}`;
|
||||
response = await actionNetworkApiRequest.call(this, 'DELETE', endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
const simplify = this.getNodeParameter('simple', i, false) as boolean;
|
||||
|
||||
if (simplify) {
|
||||
response =
|
||||
operation === 'getAll'
|
||||
? response.map((entry: Response) => simplifyResponse(entry, resource))
|
||||
: simplifyResponse(response as Response, resource);
|
||||
}
|
||||
|
||||
Array.isArray(response)
|
||||
? returnData.push(...(response as IDataObject[]))
|
||||
: returnData.push(response as IDataObject);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({ error: error.message });
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
return [this.helpers.returnJsonArray(returnData)];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
import flow from 'lodash/flow';
|
||||
import omit from 'lodash/omit';
|
||||
import type {
|
||||
IDataObject,
|
||||
IExecuteFunctions,
|
||||
IHttpRequestMethods,
|
||||
ILoadOptionsFunctions,
|
||||
IRequestOptions,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import type {
|
||||
AllFieldsUi,
|
||||
FieldWithPrimaryField,
|
||||
LinksFieldContainer,
|
||||
PersonResponse,
|
||||
PetitionResponse,
|
||||
Resource,
|
||||
Response,
|
||||
} from './types';
|
||||
|
||||
export async function actionNetworkApiRequest(
|
||||
this: IExecuteFunctions | ILoadOptionsFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
endpoint: string,
|
||||
body: IDataObject = {},
|
||||
qs: IDataObject = {},
|
||||
) {
|
||||
const options: IRequestOptions = {
|
||||
method,
|
||||
body,
|
||||
qs,
|
||||
uri: `https://actionnetwork.org/api/v2${endpoint}`,
|
||||
json: true,
|
||||
};
|
||||
|
||||
if (!Object.keys(body).length) {
|
||||
delete options.body;
|
||||
}
|
||||
|
||||
if (!Object.keys(qs).length) {
|
||||
delete options.qs;
|
||||
}
|
||||
|
||||
return await this.helpers.requestWithAuthentication.call(this, 'actionNetworkApi', options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an endpoint to the key needed to access data in the response.
|
||||
*/
|
||||
const toItemsKey = (endpoint: string) => {
|
||||
// handle two-resource endpoint
|
||||
if (
|
||||
endpoint.includes('/signatures') ||
|
||||
endpoint.includes('/attendances') ||
|
||||
endpoint.includes('/taggings')
|
||||
) {
|
||||
endpoint = endpoint.split('/').pop()!;
|
||||
}
|
||||
|
||||
return `osdi:${endpoint.replace(/\//g, '')}`;
|
||||
};
|
||||
|
||||
export async function handleListing(
|
||||
this: IExecuteFunctions | ILoadOptionsFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
endpoint: string,
|
||||
body: IDataObject = {},
|
||||
qs: IDataObject = {},
|
||||
options?: { returnAll: true },
|
||||
) {
|
||||
const returnData: IDataObject[] = [];
|
||||
let responseData;
|
||||
|
||||
qs.perPage = 25; // max
|
||||
qs.page = 1;
|
||||
|
||||
const returnAll = options?.returnAll ?? (this.getNodeParameter('returnAll', 0, false) as boolean);
|
||||
const limit = this.getNodeParameter('limit', 0, 0) as number;
|
||||
|
||||
const itemsKey = toItemsKey(endpoint);
|
||||
|
||||
do {
|
||||
responseData = await actionNetworkApiRequest.call(this, method, endpoint, body, qs);
|
||||
const items = responseData._embedded[itemsKey];
|
||||
returnData.push(...(items as IDataObject[]));
|
||||
|
||||
if (!returnAll && returnData.length >= limit) {
|
||||
return returnData.slice(0, limit);
|
||||
}
|
||||
|
||||
if (responseData._links?.next?.href) {
|
||||
const queryString = new URLSearchParams(
|
||||
responseData._links.next.href.split('?')[1] as string,
|
||||
);
|
||||
qs.page = queryString.get('page') as string;
|
||||
}
|
||||
} while (responseData._links?.next);
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
// helpers
|
||||
// ----------------------------------------
|
||||
|
||||
export const extractId = (response: LinksFieldContainer) => {
|
||||
return response._links.self.href.split('/').pop() ?? 'No ID';
|
||||
};
|
||||
|
||||
export const makeOsdiLink = (personId: string) => {
|
||||
return {
|
||||
_links: {
|
||||
'osdi:person': {
|
||||
href: `https://actionnetwork.org/api/v2/people/${personId}`,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const isPrimary = (field: FieldWithPrimaryField) => field.primary;
|
||||
|
||||
// ----------------------------------------
|
||||
// field adjusters
|
||||
// ----------------------------------------
|
||||
|
||||
function adjustLanguagesSpoken(allFields: AllFieldsUi) {
|
||||
if (!allFields.languages_spoken) return allFields;
|
||||
|
||||
return {
|
||||
...omit(allFields, ['languages_spoken']),
|
||||
languages_spoken: [allFields.languages_spoken],
|
||||
};
|
||||
}
|
||||
|
||||
function adjustPhoneNumbers(allFields: AllFieldsUi) {
|
||||
if (!allFields.phone_numbers) return allFields;
|
||||
|
||||
return {
|
||||
...omit(allFields, ['phone_numbers']),
|
||||
phone_numbers: [allFields.phone_numbers.phone_numbers_fields],
|
||||
};
|
||||
}
|
||||
|
||||
function adjustPostalAddresses(allFields: AllFieldsUi) {
|
||||
if (!allFields.postal_addresses) return allFields;
|
||||
|
||||
if (allFields.postal_addresses.postal_addresses_fields.length) {
|
||||
const adjusted = allFields.postal_addresses.postal_addresses_fields.map((field) => {
|
||||
const copy: IDataObject = {
|
||||
...omit(field, ['address_lines', 'location']),
|
||||
};
|
||||
|
||||
if (field.address_lines) {
|
||||
copy.address_lines = [field.address_lines];
|
||||
}
|
||||
|
||||
if (field.location) {
|
||||
copy.location = field.location.location_fields;
|
||||
}
|
||||
|
||||
return copy;
|
||||
});
|
||||
|
||||
return {
|
||||
...omit(allFields, ['postal_addresses']),
|
||||
postal_addresses: adjusted,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function adjustLocation(allFields: AllFieldsUi) {
|
||||
if (!allFields.location) return allFields;
|
||||
|
||||
const locationFields = allFields.location.postal_addresses_fields;
|
||||
|
||||
const adjusted: IDataObject = {
|
||||
...omit(locationFields, ['address_lines', 'location']),
|
||||
};
|
||||
|
||||
if (locationFields.address_lines) {
|
||||
adjusted.address_lines = [locationFields.address_lines];
|
||||
}
|
||||
|
||||
if (locationFields.location) {
|
||||
adjusted.location = locationFields.location.location_fields;
|
||||
}
|
||||
|
||||
return {
|
||||
...omit(allFields, ['location']),
|
||||
location: adjusted,
|
||||
};
|
||||
}
|
||||
|
||||
function adjustTargets(allFields: AllFieldsUi) {
|
||||
if (!allFields.target) return allFields;
|
||||
|
||||
const adjusted = allFields.target.split(',').map((value) => ({ name: value }));
|
||||
|
||||
return {
|
||||
...omit(allFields, ['target']),
|
||||
target: adjusted,
|
||||
};
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
// payload adjusters
|
||||
// ----------------------------------------
|
||||
|
||||
export const adjustPersonPayload = flow(
|
||||
adjustLanguagesSpoken,
|
||||
adjustPhoneNumbers,
|
||||
adjustPostalAddresses,
|
||||
);
|
||||
|
||||
export const adjustPetitionPayload = adjustTargets;
|
||||
|
||||
export const adjustEventPayload = adjustLocation;
|
||||
|
||||
// ----------------------------------------
|
||||
// resource loaders
|
||||
// ----------------------------------------
|
||||
|
||||
async function loadResource(this: ILoadOptionsFunctions, resource: string) {
|
||||
return await handleListing.call(this, 'GET', `/${resource}`, {}, {}, { returnAll: true });
|
||||
}
|
||||
|
||||
export const resourceLoaders = {
|
||||
async getTags(this: ILoadOptionsFunctions) {
|
||||
const tags = (await loadResource.call(this, 'tags')) as Array<
|
||||
{ name: string } & LinksFieldContainer
|
||||
>;
|
||||
|
||||
return tags.map((tag) => ({ name: tag.name, value: extractId(tag) }));
|
||||
},
|
||||
|
||||
async getTaggings(this: ILoadOptionsFunctions) {
|
||||
const tagId = this.getNodeParameter('tagId', 0);
|
||||
const endpoint = `/tags/${tagId}/taggings`;
|
||||
|
||||
// two-resource endpoint, so direct call
|
||||
const taggings = (await handleListing.call(
|
||||
this,
|
||||
'GET',
|
||||
endpoint,
|
||||
{},
|
||||
{},
|
||||
{ returnAll: true },
|
||||
)) as LinksFieldContainer[];
|
||||
|
||||
return taggings.map((tagging) => {
|
||||
const taggingId = extractId(tagging);
|
||||
|
||||
return {
|
||||
name: taggingId,
|
||||
value: taggingId,
|
||||
};
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// ----------------------------------------
|
||||
// response simplifiers
|
||||
// ----------------------------------------
|
||||
const simplifyPersonResponse = (response: PersonResponse) => {
|
||||
const emailAddress = response.email_addresses.filter(isPrimary);
|
||||
const phoneNumber = response.phone_numbers.filter(isPrimary);
|
||||
const postalAddress = response.postal_addresses.filter(isPrimary);
|
||||
|
||||
const fieldsToSimplify = [
|
||||
'identifiers',
|
||||
'email_addresses',
|
||||
'phone_numbers',
|
||||
'postal_addresses',
|
||||
'languages_spoken',
|
||||
'_links',
|
||||
];
|
||||
|
||||
return {
|
||||
id: extractId(response),
|
||||
...omit(response, fieldsToSimplify),
|
||||
...{ email_address: emailAddress[0].address || '' },
|
||||
...{ phone_number: phoneNumber[0].number || '' },
|
||||
...{
|
||||
postal_address: {
|
||||
...(postalAddress && omit(postalAddress[0], 'address_lines')),
|
||||
address_lines: postalAddress[0].address_lines ?? '',
|
||||
},
|
||||
},
|
||||
language_spoken: response.languages_spoken[0],
|
||||
};
|
||||
};
|
||||
|
||||
const simplifyPetitionResponse = (response: PetitionResponse) => {
|
||||
const fieldsToSimplify = ['identifiers', '_links', 'action_network:hidden', '_embedded'];
|
||||
|
||||
return {
|
||||
id: extractId(response),
|
||||
...omit(response, fieldsToSimplify),
|
||||
creator: simplifyPersonResponse(response._embedded['osdi:creator']),
|
||||
};
|
||||
};
|
||||
|
||||
export const simplifyResponse = (response: Response, resource: Resource) => {
|
||||
if (resource === 'person') {
|
||||
return simplifyPersonResponse(response as PersonResponse);
|
||||
} else if (resource === 'petition') {
|
||||
return simplifyPetitionResponse(response as PetitionResponse);
|
||||
}
|
||||
|
||||
const fieldsToSimplify = ['identifiers', '_links', 'action_network:sponsor', 'reminders'];
|
||||
|
||||
return {
|
||||
id: extractId(response),
|
||||
...omit(response, fieldsToSimplify),
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 1 79.89 75.96"><defs><style>.cls-1{fill:#9dd3ed}</style></defs><circle cx="40.42" cy="5.43" r="5.43" class="cls-1"/><path d="M26.32 15.92c9.94-2.11 15.06 5.25 16.52 11.47.92 3.93 4.28 3.87 6.58 2.73S56 28.48 53 21.23c-1.82-4.41-4.14-8.44-8.26-11.08A6.42 6.42 0 0 1 34.66 8.3a7 7 0 0 1-.44-1.14c-8.85.1-14.7 8-16.45 13.26a18.85 18.85 0 0 1 8.55-4.5" class="cls-1"/><circle cx="5.43" cy="29.87" r="5.43" class="cls-1"/><path d="M11.23 46.45c1-10.11 9.51-12.8 15.88-12.33 4 .29 5-2.93 4.57-5.47s.4-6.78-7.41-6.1C19.52 23 15 24 11.23 27.12a6.37 6.37 0 0 1 .34 4.67 6.6 6.6 0 0 1-.93 1.86 6.4 6.4 0 0 1-4.19 2.57 6.3 6.3 0 0 1-1.22.08C2.68 44.78 8.52 52.73 13 56a18.9 18.9 0 0 1-1.75-9.51" class="cls-1"/><circle cx="18.08" cy="70.13" r="5.43" class="cls-1"/><path d="M35.65 69.73c-9.33-4-9.25-13-6.83-18.91 1.52-3.74-1.25-5.64-3.79-6S18.7 42.31 16.94 50c-1.07 4.64-1.51 9.27.32 13.81a6.44 6.44 0 0 1 4.55 1.12 6.47 6.47 0 0 1 2.63 6.24 7.6 7.6 0 0 1-.3 1.18c7.27 5 16.64 2 21.09-1.3a18.8 18.8 0 0 1-9.58-1.27" class="cls-1"/><circle cx="60.58" cy="70.53" r="5.43" class="cls-1"/><path d="M65.83 53.76c-6.81 7.55-15.28 4.6-20.11.42-3-2.64-5.74-.62-6.93 1.66S34.42 61 41.1 65.16c4.06 2.5 8.3 4.4 13.19 4.11a6.43 6.43 0 0 1 2.51-4 6.8 6.8 0 0 1 1.86-.93 6.38 6.38 0 0 1 4.9.44 6 6 0 0 1 1 .66c7.1-5.28 7.17-15.14 5.52-20.4a18.9 18.9 0 0 1-4.27 8.67" class="cls-1"/><circle cx="74.46" cy="30.68" r="5.43" class="cls-1"/><path d="M60.13 20.51c5.08 8.81-.34 16-5.8 19.25-3.46 2.09-2.33 5.24-.57 7.11s3.6 5.76 9.57.68c3.64-3.08 6.75-6.54 8-11.27A6.42 6.42 0 0 1 70 26.09a6 6 0 0 1 .94-.77c-2.83-8.39-12.19-11.49-17.69-11.55a18.94 18.94 0 0 1 6.92 6.74" class="cls-1"/></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,152 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { makeSimpleField } from './SharedFields';
|
||||
|
||||
export const attendanceOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['attendance'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
action: 'Create an attendance',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
action: 'Get an attendance',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
action: 'Get many attendances',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const attendanceFields: INodeProperties[] = [
|
||||
// ----------------------------------------
|
||||
// attendance: create
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Person ID',
|
||||
name: 'personId',
|
||||
description: 'ID of the person to create an attendance for',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['attendance'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Event ID',
|
||||
name: 'eventId',
|
||||
description: 'ID of the event to create an attendance for',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['attendance'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('attendance', 'create'),
|
||||
|
||||
// ----------------------------------------
|
||||
// attendance: get
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Event ID',
|
||||
name: 'eventId',
|
||||
description: 'ID of the event whose attendance to retrieve',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['attendance'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Attendance ID',
|
||||
name: 'attendanceId',
|
||||
description: 'ID of the attendance to retrieve',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['attendance'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('attendance', 'get'),
|
||||
|
||||
// ----------------------------------------
|
||||
// attendance: getAll
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Event ID',
|
||||
name: 'eventId',
|
||||
description: 'ID of the event to create an attendance for',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['attendance'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['attendance'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['attendance'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('attendance', 'getAll'),
|
||||
];
|
||||
@@ -0,0 +1,138 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { eventAdditionalFieldsOptions, makeSimpleField } from './SharedFields';
|
||||
|
||||
export const eventOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['event'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
action: 'Create an event',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
action: 'Get an event',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
action: 'Get many events',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const eventFields: INodeProperties[] = [
|
||||
// ----------------------------------------
|
||||
// event: create
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Origin System',
|
||||
name: 'originSystem',
|
||||
description: 'Source where the event originated',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['event'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Title',
|
||||
name: 'title',
|
||||
description: 'Title of the event to create',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['event'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('event', 'create'),
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['event'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: eventAdditionalFieldsOptions,
|
||||
},
|
||||
|
||||
// ----------------------------------------
|
||||
// event: get
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Event ID',
|
||||
name: 'eventId',
|
||||
description: 'ID of the event to retrieve',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['event'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('event', 'get'),
|
||||
|
||||
// ----------------------------------------
|
||||
// event: getAll
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['event'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['event'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('event', 'getAll'),
|
||||
];
|
||||
@@ -0,0 +1,218 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { makeSimpleField, personAdditionalFieldsOptions } from './SharedFields';
|
||||
|
||||
export const personOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
action: 'Create a person',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
action: 'Get a person',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
action: 'Get many people',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
action: 'Update a person',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const personFields: INodeProperties[] = [
|
||||
// ----------------------------------------
|
||||
// person: create
|
||||
// ----------------------------------------
|
||||
makeSimpleField('person', 'create'),
|
||||
{
|
||||
displayName: 'Email Address', // on create, only _one_ must be passed in
|
||||
name: 'email_addresses',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
placeholder: 'Add Email Address Field',
|
||||
description: 'Person’s email addresses',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Email Addresses Fields',
|
||||
name: 'email_addresses_fields',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Address',
|
||||
name: 'address',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: "Person's email address",
|
||||
},
|
||||
{
|
||||
displayName: 'Primary',
|
||||
name: 'primary',
|
||||
type: 'hidden',
|
||||
default: true,
|
||||
description: "Whether this is the person's primary email address",
|
||||
},
|
||||
{
|
||||
displayName: 'Status',
|
||||
name: 'status',
|
||||
type: 'options',
|
||||
default: 'subscribed',
|
||||
description: 'Subscription status of this email address',
|
||||
options: [
|
||||
{
|
||||
name: 'Bouncing',
|
||||
value: 'bouncing',
|
||||
},
|
||||
{
|
||||
name: 'Previous Bounce',
|
||||
value: 'previous bounce',
|
||||
},
|
||||
{
|
||||
name: 'Previous Spam Complaint',
|
||||
value: 'previous spam complaint',
|
||||
},
|
||||
{
|
||||
name: 'Spam Complaint',
|
||||
value: 'spam complaint',
|
||||
},
|
||||
{
|
||||
name: 'Subscribed',
|
||||
value: 'subscribed',
|
||||
},
|
||||
{
|
||||
name: 'Unsubscribed',
|
||||
value: 'unsubscribed',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: personAdditionalFieldsOptions,
|
||||
},
|
||||
|
||||
// ----------------------------------------
|
||||
// person: get
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Person ID',
|
||||
name: 'personId',
|
||||
description: 'ID of the person to retrieve',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('person', 'get'),
|
||||
|
||||
// ----------------------------------------
|
||||
// person: getAll
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
default: 25,
|
||||
description: 'Max number of results to return',
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 25,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('person', 'getAll'),
|
||||
|
||||
// ----------------------------------------
|
||||
// person: update
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Person ID',
|
||||
name: 'personId',
|
||||
description: 'ID of the person to update',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('person', 'update'),
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
options: personAdditionalFieldsOptions,
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,107 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const personTagOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['personTag'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Add',
|
||||
value: 'add',
|
||||
action: 'Add a person tag',
|
||||
},
|
||||
{
|
||||
name: 'Remove',
|
||||
value: 'remove',
|
||||
action: 'Remove a person tag',
|
||||
},
|
||||
],
|
||||
default: 'add',
|
||||
},
|
||||
];
|
||||
|
||||
export const personTagFields: INodeProperties[] = [
|
||||
// ----------------------------------------
|
||||
// personTag: add
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Tag Name or ID',
|
||||
name: 'tagId',
|
||||
description:
|
||||
'ID of the tag to add. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getTags',
|
||||
},
|
||||
required: true,
|
||||
default: [],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['personTag'],
|
||||
operation: ['add'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Person ID',
|
||||
name: 'personId',
|
||||
description: 'ID of the person to add the tag to',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['personTag'],
|
||||
operation: ['add'],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ----------------------------------------
|
||||
// personTag: remove
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Tag Name or ID',
|
||||
name: 'tagId',
|
||||
description:
|
||||
'ID of the tag whose tagging to delete. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getTags',
|
||||
},
|
||||
default: [],
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['personTag'],
|
||||
operation: ['remove'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Tagging Name or ID',
|
||||
name: 'taggingId',
|
||||
description:
|
||||
'ID of the tagging to remove. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsDependsOn: ['tagId'],
|
||||
loadOptionsMethod: 'getTaggings',
|
||||
},
|
||||
required: true,
|
||||
default: [],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['personTag'],
|
||||
operation: ['remove'],
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,176 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { makeSimpleField, petitionAdditionalFieldsOptions } from './SharedFields';
|
||||
|
||||
export const petitionOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['petition'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
action: 'Create a petition',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
action: 'Get a petition',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
action: 'Get many petitions',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
action: 'Update a petition',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const petitionFields: INodeProperties[] = [
|
||||
// ----------------------------------------
|
||||
// petition: create
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Origin System',
|
||||
name: 'originSystem',
|
||||
description: 'Source where the petition originated',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['petition'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Title',
|
||||
name: 'title',
|
||||
description: 'Title of the petition to create',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['petition'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('petition', 'create'),
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['petition'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: petitionAdditionalFieldsOptions,
|
||||
},
|
||||
|
||||
// ----------------------------------------
|
||||
// petition: get
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Petition ID',
|
||||
name: 'petitionId',
|
||||
description: 'ID of the petition to retrieve',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['petition'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('petition', 'get'),
|
||||
|
||||
// ----------------------------------------
|
||||
// petition: getAll
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['petition'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['petition'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('petition', 'getAll'),
|
||||
|
||||
// ----------------------------------------
|
||||
// petition: update
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Petition ID',
|
||||
name: 'petitionId',
|
||||
description: 'ID of the petition to update',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['petition'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('petition', 'update'),
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['petition'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
options: petitionAdditionalFieldsOptions,
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,372 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import type { Operation, Resource, LanguageOptions } from '../types';
|
||||
|
||||
export const languageOptions: LanguageOptions = [
|
||||
{
|
||||
name: 'Danish',
|
||||
value: 'da',
|
||||
},
|
||||
{
|
||||
name: 'Dutch',
|
||||
value: 'nl',
|
||||
},
|
||||
{
|
||||
name: 'English',
|
||||
value: 'en',
|
||||
},
|
||||
{
|
||||
name: 'Finnish',
|
||||
value: 'fi',
|
||||
},
|
||||
{
|
||||
name: 'French',
|
||||
value: 'fr',
|
||||
},
|
||||
{
|
||||
name: 'German',
|
||||
value: 'de',
|
||||
},
|
||||
{
|
||||
name: 'Hungarian',
|
||||
value: 'hu',
|
||||
},
|
||||
{
|
||||
name: 'Indonesian',
|
||||
value: 'id',
|
||||
},
|
||||
{
|
||||
name: 'Japanese',
|
||||
value: 'ja',
|
||||
},
|
||||
{
|
||||
name: 'Portuguese - Portugal',
|
||||
value: 'pt',
|
||||
},
|
||||
{
|
||||
name: 'Portuguese - Brazil',
|
||||
value: 'br',
|
||||
},
|
||||
{
|
||||
name: 'Rumanian',
|
||||
value: 'ru',
|
||||
},
|
||||
{
|
||||
name: 'Spanish',
|
||||
value: 'es',
|
||||
},
|
||||
{
|
||||
name: 'Swedish',
|
||||
value: 'sv',
|
||||
},
|
||||
{
|
||||
name: 'Turkish',
|
||||
value: 'tr',
|
||||
},
|
||||
{
|
||||
name: 'Welsh',
|
||||
value: 'cy',
|
||||
},
|
||||
];
|
||||
|
||||
const postalAddressesFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Primary',
|
||||
name: 'primary',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: "Whether this is the person's primary address",
|
||||
},
|
||||
{
|
||||
displayName: 'Address Line',
|
||||
name: 'address_lines',
|
||||
type: 'string', // The Action Network API expects a string array but ignores any string beyond the first, so this input field is simplified to string.
|
||||
default: '',
|
||||
description: "Line for a person's address",
|
||||
},
|
||||
{
|
||||
displayName: 'Locality',
|
||||
name: 'locality',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
"City or other local administrative area. If blank, this will be filled in based on Action Network's geocoding.",
|
||||
},
|
||||
{
|
||||
displayName: 'Region',
|
||||
name: 'region',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'State or subdivision code per ISO 3166-2',
|
||||
},
|
||||
{
|
||||
displayName: 'Postal Code',
|
||||
name: 'postal_code',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Region specific postal code, such as ZIP code',
|
||||
},
|
||||
{
|
||||
displayName: 'Country',
|
||||
name: 'country',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Country code according to ISO 3166-1 Alpha-2. Defaults to US.',
|
||||
},
|
||||
{
|
||||
displayName: 'Language',
|
||||
name: 'language',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Language in which the address is recorded, per ISO 639',
|
||||
},
|
||||
{
|
||||
displayName: 'Location',
|
||||
name: 'location',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Location Fields',
|
||||
name: 'location_fields',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Latitude',
|
||||
name: 'latitude',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Latitude of the location of the address',
|
||||
},
|
||||
{
|
||||
displayName: 'Longitude',
|
||||
name: 'longitude',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Longitude of the location of the address',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const eventAdditionalFieldsOptions: INodeProperties['options'] = [
|
||||
{
|
||||
displayName: 'Browser URL',
|
||||
name: 'browser_url',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'URL to this event’s page on the Action Network or a third party',
|
||||
},
|
||||
{
|
||||
displayName: 'Description',
|
||||
name: 'description',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Description of the event. HTML supported.',
|
||||
},
|
||||
{
|
||||
displayName: 'End Date',
|
||||
name: 'end_date',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'End date and time of the event',
|
||||
},
|
||||
{
|
||||
displayName: 'Featured Image URL',
|
||||
name: 'featured_image_url',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'URL to this event’s featured image on the Action Network',
|
||||
},
|
||||
{
|
||||
displayName: 'Instructions',
|
||||
name: 'instructions',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: "Event's instructions for activists, visible after they RSVP. HTML supported.",
|
||||
},
|
||||
{
|
||||
displayName: 'Location',
|
||||
name: 'location',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
placeholder: 'Add Location Field',
|
||||
typeOptions: {
|
||||
multipleValues: false,
|
||||
},
|
||||
options: [
|
||||
// different name, identical structure
|
||||
{
|
||||
displayName: 'Postal Addresses Fields',
|
||||
name: 'postal_addresses_fields',
|
||||
placeholder: 'Add Postal Address Field',
|
||||
values: postalAddressesFields,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Internal (not public) title of the event',
|
||||
},
|
||||
{
|
||||
displayName: 'Start Date',
|
||||
name: 'start_date',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'Start date and time of the event',
|
||||
},
|
||||
];
|
||||
|
||||
export const personAdditionalFieldsOptions: INodeProperties['options'] = [
|
||||
{
|
||||
displayName: 'Family Name',
|
||||
name: 'family_name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Person’s last name',
|
||||
},
|
||||
{
|
||||
displayName: 'Given Name',
|
||||
name: 'given_name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Person’s first name',
|
||||
},
|
||||
{
|
||||
displayName: 'Language Spoken',
|
||||
name: 'languages_spoken',
|
||||
type: 'options', // Action Network accepts a `string[]` of language codes, but supports only one language per person - sending an array of 2+ languages will result in the first valid language being set as the preferred language for the person. Therefore, the user may select only one option in the n8n UI.
|
||||
default: [],
|
||||
description: 'Language spoken by the person',
|
||||
options: languageOptions,
|
||||
},
|
||||
{
|
||||
displayName: 'Phone Number', // on create, only _one_ must be passed in
|
||||
name: 'phone_numbers',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
placeholder: 'Add Phone Numbers Field',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Phone Numbers Fields',
|
||||
name: 'phone_numbers_fields',
|
||||
placeholder: 'Add Phone Number Field',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Number',
|
||||
name: 'number',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: "Person's mobile number, in international format without the plus sign",
|
||||
},
|
||||
{
|
||||
displayName: 'Primary',
|
||||
name: 'primary',
|
||||
type: 'hidden',
|
||||
default: true,
|
||||
description: "Whether this is the person's primary phone number",
|
||||
},
|
||||
{
|
||||
displayName: 'Status',
|
||||
name: 'status',
|
||||
type: 'options',
|
||||
default: 'subscribed',
|
||||
description: 'Subscription status of this number',
|
||||
options: [
|
||||
{
|
||||
name: 'Bouncing',
|
||||
value: 'bouncing',
|
||||
},
|
||||
{
|
||||
name: 'Previous Bounce',
|
||||
value: 'previous bounce',
|
||||
},
|
||||
{
|
||||
name: 'Subscribed',
|
||||
value: 'subscribed',
|
||||
},
|
||||
{
|
||||
name: 'Unsubscribed',
|
||||
value: 'unsubscribed',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Postal Addresses',
|
||||
name: 'postal_addresses',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
placeholder: 'Add Postal Addresses Field',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Postal Addresses Fields',
|
||||
name: 'postal_addresses_fields',
|
||||
placeholder: 'Add Postal Address Field',
|
||||
values: postalAddressesFields,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const petitionAdditionalFieldsOptions: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Browser URL',
|
||||
name: 'browser_url',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'URL to this petition’s page on the Action Network or a third party',
|
||||
},
|
||||
{
|
||||
displayName: 'Featured Image URL',
|
||||
name: 'featured_image_url',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'URL to this action’s featured image on the Action Network',
|
||||
},
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Internal (not public) title of the petition',
|
||||
},
|
||||
{
|
||||
displayName: 'Petition Text',
|
||||
name: 'petition_text',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Text of the letter to the petition’s target',
|
||||
},
|
||||
{
|
||||
displayName: 'Targets',
|
||||
name: 'target',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Comma-separated names of targets for this petition',
|
||||
},
|
||||
];
|
||||
|
||||
export const makeSimpleField = (resource: Resource, operation: Operation): INodeProperties => ({
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [resource],
|
||||
operation: [operation],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
});
|
||||
@@ -0,0 +1,234 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { makeSimpleField } from './SharedFields';
|
||||
|
||||
export const signatureOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['signature'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
action: 'Create a signature',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
action: 'Get a signature',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
action: 'Get many signatures',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
action: 'Update a signature',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const signatureFields: INodeProperties[] = [
|
||||
// ----------------------------------------
|
||||
// signature: create
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Petition ID',
|
||||
name: 'petitionId',
|
||||
description: 'ID of the petition to sign',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['signature'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Person ID',
|
||||
name: 'personId',
|
||||
description: 'ID of the person whose signature to create',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['signature'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('signature', 'create'),
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['signature'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Comments',
|
||||
name: 'comments',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Comments to leave when signing this petition',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------------
|
||||
// signature: get
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Petition ID',
|
||||
name: 'petitionId',
|
||||
description: 'ID of the petition whose signature to retrieve',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['signature'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Signature ID',
|
||||
name: 'signatureId',
|
||||
description: 'ID of the signature to retrieve',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['signature'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('signature', 'get'),
|
||||
|
||||
// ----------------------------------------
|
||||
// signature: getAll
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Petition ID',
|
||||
name: 'petitionId',
|
||||
description: 'ID of the petition whose signatures to retrieve',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['signature'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['signature'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['signature'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('signature', 'getAll'),
|
||||
|
||||
// ----------------------------------------
|
||||
// signature: update
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Petition ID',
|
||||
name: 'petitionId',
|
||||
description: 'ID of the petition whose signature to update',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['signature'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Signature ID',
|
||||
name: 'signatureId',
|
||||
description: 'ID of the signature to update',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['signature'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('signature', 'update'),
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['signature'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Comments',
|
||||
name: 'comments',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Comments to leave when signing this petition',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,110 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { makeSimpleField } from './SharedFields';
|
||||
|
||||
export const tagOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['tag'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
action: 'Create a tag',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
action: 'Get a tag',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
action: 'Get many tags',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const tagFields: INodeProperties[] = [
|
||||
// ----------------------------------------
|
||||
// tag: create
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
description: 'Name of the tag to create',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['tag'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('tag', 'create'),
|
||||
|
||||
// ----------------------------------------
|
||||
// tag: get
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Tag ID',
|
||||
name: 'tagId',
|
||||
description: 'ID of the tag to retrieve',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['tag'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('tag', 'get'),
|
||||
|
||||
// ----------------------------------------
|
||||
// tag: getAll
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['tag'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['tag'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
},
|
||||
makeSimpleField('tag', 'getAll'),
|
||||
];
|
||||
@@ -0,0 +1,7 @@
|
||||
export * from './AttendanceDescription';
|
||||
export * from './EventDescription';
|
||||
export * from './PersonDescription';
|
||||
export * from './PersonTagDescription';
|
||||
export * from './PetitionDescription';
|
||||
export * from './SignatureDescription';
|
||||
export * from './TagDescription';
|
||||
@@ -0,0 +1,106 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export type LanguageOptions = INodeProperties['options'];
|
||||
|
||||
export type Resource =
|
||||
| 'attendance'
|
||||
| 'event'
|
||||
| 'person'
|
||||
| 'personTag'
|
||||
| 'petition'
|
||||
| 'signature'
|
||||
| 'tag';
|
||||
|
||||
export type Operation = 'create' | 'delete' | 'get' | 'getAll' | 'update' | 'add' | 'remove';
|
||||
|
||||
// @ts-ignore
|
||||
export type LanguageCodes = LanguageOptions[number]['value'];
|
||||
|
||||
// ----------------------------------------
|
||||
// UI fields
|
||||
// ----------------------------------------
|
||||
|
||||
export type AllFieldsUi = {
|
||||
email_addresses: EmailAddressUi;
|
||||
postal_addresses: PostalAddressesUi;
|
||||
phone_numbers: PhoneNumberUi;
|
||||
languages_spoken: LanguageCodes;
|
||||
target: string;
|
||||
location: LocationUi;
|
||||
};
|
||||
|
||||
export type EmailAddressUi = {
|
||||
email_addresses_fields: EmailAddressField;
|
||||
};
|
||||
|
||||
export type EmailAddressField = {
|
||||
primary: boolean;
|
||||
address: string;
|
||||
status: EmailStatus;
|
||||
};
|
||||
|
||||
type BaseStatus = 'subscribed' | 'unsubscribed' | 'bouncing' | 'previous bounce';
|
||||
|
||||
type EmailStatus = BaseStatus | 'spam complaint' | 'previous spam complaint';
|
||||
|
||||
type PhoneNumberUi = {
|
||||
phone_numbers_fields: PhoneNumberField[];
|
||||
};
|
||||
|
||||
export type PhoneNumberField = {
|
||||
primary: boolean;
|
||||
number: string;
|
||||
status: BaseStatus;
|
||||
};
|
||||
|
||||
type PostalAddressesUi = {
|
||||
postal_addresses_fields: PostalAddressField[];
|
||||
};
|
||||
|
||||
type LocationUi = {
|
||||
postal_addresses_fields: PostalAddressField;
|
||||
};
|
||||
|
||||
export type PostalAddressField = {
|
||||
primary: boolean;
|
||||
address_lines: string;
|
||||
locality: string;
|
||||
region: string;
|
||||
postal_code: string;
|
||||
country: string;
|
||||
language: LanguageCodes;
|
||||
location: { location_fields: LatitudeLongitude };
|
||||
};
|
||||
|
||||
type LatitudeLongitude = {
|
||||
latitude: string;
|
||||
longitude: string;
|
||||
};
|
||||
|
||||
export type FieldWithPrimaryField = EmailAddressField | PhoneNumberField | PostalAddressField;
|
||||
|
||||
// ----------------------------------------
|
||||
// responses
|
||||
// ----------------------------------------
|
||||
|
||||
export type LinksFieldContainer = { _links: { self: { href: string } } };
|
||||
|
||||
export type Response = JsonObject & LinksFieldContainer;
|
||||
|
||||
export type PersonResponse = Response & {
|
||||
identifiers: string[];
|
||||
email_addresses: EmailAddressField[];
|
||||
phone_numbers: PhoneNumberField[];
|
||||
postal_addresses: PostalAddressField[];
|
||||
languages_spoken: LanguageCodes[];
|
||||
};
|
||||
|
||||
export type PetitionResponse = Response & { _embedded: { 'osdi:creator': PersonResponse } };
|
||||
|
||||
// ----------------------------------------
|
||||
// utils
|
||||
// ----------------------------------------
|
||||
|
||||
export type JsonValue = string | number | boolean | null | JsonObject | JsonValue[];
|
||||
|
||||
export type JsonObject = { [key: string]: JsonValue };
|
||||
@@ -0,0 +1,148 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const accountContactOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['accountContact'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create an association',
|
||||
action: 'Create an account contact',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete an association',
|
||||
action: 'Delete an account contact',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update an association',
|
||||
action: 'Update an account contact',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const accountContactFields: INodeProperties[] = [
|
||||
// ----------------------------------
|
||||
// accountContact:create
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Account ID',
|
||||
name: 'account',
|
||||
type: 'number',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['accountContact'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Contact ID',
|
||||
name: 'contact',
|
||||
type: 'number',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['accountContact'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
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',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,274 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { activeCampaignDefaultGetAllProperties } from './GenericFunctions';
|
||||
|
||||
export const accountOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['account'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create an account',
|
||||
action: 'Create an account',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete an account',
|
||||
action: 'Delete an account',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get data of an account',
|
||||
action: 'Get an account',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get data of many accounts',
|
||||
action: 'Get many accounts',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update an account',
|
||||
action: 'Update an account',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const accountFields: INodeProperties[] = [
|
||||
// ----------------------------------
|
||||
// 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 Name or ID',
|
||||
name: 'customFieldId',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getAccountCustomFields',
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'ID of the field to set. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
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 Name or ID',
|
||||
name: 'customFieldId',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getAccountCustomFields',
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'ID of the field to set. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
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',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.activeCampaign",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"details": "ActiveCampaign is a cloud software platform that allows customer experience automation, which combines email marketing, marketing automation, sales automation, and CRM categories. Use this node when you want to interact with your ActiveCampaign account.",
|
||||
"categories": ["Marketing"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/activecampaign/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.activecampaign/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.activeCampaignTrigger",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Marketing"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/activecampaign/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.activecampaigntrigger/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
import type {
|
||||
IHookFunctions,
|
||||
IWebhookFunctions,
|
||||
IDataObject,
|
||||
ILoadOptionsFunctions,
|
||||
INodePropertyOptions,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
IWebhookResponseData,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionTypes } from 'n8n-workflow';
|
||||
|
||||
import { activeCampaignApiRequest, activeCampaignApiRequestAllItems } from './GenericFunctions';
|
||||
|
||||
export class ActiveCampaignTrigger implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'ActiveCampaign Trigger',
|
||||
name: 'activeCampaignTrigger',
|
||||
icon: { light: 'file:activeCampaign.svg', dark: 'file:activeCampaign.dark.svg' },
|
||||
group: ['trigger'],
|
||||
version: 1,
|
||||
description: 'Handle ActiveCampaign events via webhooks',
|
||||
defaults: {
|
||||
name: 'ActiveCampaign Trigger',
|
||||
},
|
||||
inputs: [],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'activeCampaignApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
webhooks: [
|
||||
{
|
||||
name: 'default',
|
||||
httpMethod: 'POST',
|
||||
responseMode: 'onReceived',
|
||||
path: 'webhook',
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Event Names or IDs',
|
||||
name: 'events',
|
||||
type: 'multiOptions',
|
||||
description:
|
||||
'Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getEvents',
|
||||
},
|
||||
default: [],
|
||||
options: [],
|
||||
},
|
||||
{
|
||||
displayName: 'Source',
|
||||
name: 'sources',
|
||||
type: 'multiOptions',
|
||||
options: [
|
||||
{
|
||||
name: 'Public',
|
||||
value: 'public',
|
||||
description: 'Run the hooks when a contact triggers the action',
|
||||
},
|
||||
{
|
||||
name: 'Admin',
|
||||
value: 'admin',
|
||||
description: 'Run the hooks when an admin user triggers the action',
|
||||
},
|
||||
{
|
||||
name: 'Api',
|
||||
value: 'api',
|
||||
description: 'Run the hooks when an API call triggers the action',
|
||||
},
|
||||
{
|
||||
name: 'System',
|
||||
value: 'system',
|
||||
description: 'Run the hooks when automated systems triggers the action',
|
||||
},
|
||||
],
|
||||
default: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
methods = {
|
||||
loadOptions: {
|
||||
// Get all the events to display them to user so that they can
|
||||
// select them easily
|
||||
async getEvents(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const events = await activeCampaignApiRequestAllItems.call(
|
||||
this,
|
||||
'GET',
|
||||
'/api/3/webhook/events',
|
||||
{},
|
||||
{},
|
||||
'webhookEvents',
|
||||
);
|
||||
for (const event of events) {
|
||||
const eventName = event;
|
||||
const eventId = event;
|
||||
returnData.push({
|
||||
name: eventName,
|
||||
value: eventId,
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
webhookMethods = {
|
||||
default: {
|
||||
async checkExists(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
if (webhookData.webhookId === undefined) {
|
||||
return false;
|
||||
}
|
||||
const endpoint = `/api/3/webhooks/${webhookData.webhookId}`;
|
||||
try {
|
||||
await activeCampaignApiRequest.call(this, 'GET', endpoint, {});
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
async create(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookUrl = this.getNodeWebhookUrl('default') as string;
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
const events = this.getNodeParameter('events', []) as string[];
|
||||
const sources = this.getNodeParameter('sources', '') as string[];
|
||||
const body: IDataObject = {
|
||||
webhook: {
|
||||
name: `n8n-webhook:${webhookUrl}`,
|
||||
url: webhookUrl,
|
||||
events,
|
||||
sources,
|
||||
},
|
||||
};
|
||||
const { webhook } = await activeCampaignApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
'/api/3/webhooks',
|
||||
body,
|
||||
);
|
||||
webhookData.webhookId = webhook.id;
|
||||
return true;
|
||||
},
|
||||
async delete(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
try {
|
||||
await activeCampaignApiRequest.call(
|
||||
this,
|
||||
'DELETE',
|
||||
`/api/3/webhooks/${webhookData.webhookId}`,
|
||||
{},
|
||||
);
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
delete webhookData.webhookId;
|
||||
return true;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
|
||||
const req = this.getRequestObject();
|
||||
return {
|
||||
workflowData: [this.helpers.returnJsonArray(req.body as IDataObject[])],
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { activeCampaignDefaultGetAllProperties } from './GenericFunctions';
|
||||
|
||||
export const connectionOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['connection'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a connection',
|
||||
action: 'Create a connection',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete a connection',
|
||||
action: 'Delete a connection',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get data of a connection',
|
||||
action: 'Get a connection',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get data of many connections',
|
||||
action: 'Get many connections',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update a connection',
|
||||
action: 'Update a connection',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const connectionFields: INodeProperties[] = [
|
||||
// ----------------------------------
|
||||
// connection:create
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Service',
|
||||
name: 'service',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['connection'],
|
||||
},
|
||||
},
|
||||
description: 'The name of the service',
|
||||
},
|
||||
{
|
||||
displayName: 'External Account ID',
|
||||
name: 'externalid',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['connection'],
|
||||
},
|
||||
},
|
||||
description: 'The ID of the account in the external service',
|
||||
},
|
||||
{
|
||||
displayName: 'Account Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['connection'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The name associated with the account in the external service. Often this will be a company name (e.g., "My Toystore, Inc.").',
|
||||
},
|
||||
{
|
||||
displayName: 'Logo URL',
|
||||
name: 'logoUrl',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['connection'],
|
||||
},
|
||||
},
|
||||
description: 'The URL to a logo image for the external service',
|
||||
},
|
||||
{
|
||||
displayName: 'Link URL',
|
||||
name: 'linkUrl',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['connection'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
"The URL to a page where the integration with the external service can be managed in the third-party's website",
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// connection:update
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Connection ID',
|
||||
name: 'connectionId',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['update'],
|
||||
resource: ['connection'],
|
||||
},
|
||||
},
|
||||
default: 0,
|
||||
required: true,
|
||||
description: 'ID of the connection to update',
|
||||
},
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
description: 'The fields to update',
|
||||
placeholder: 'Add Field',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['update'],
|
||||
resource: ['connection'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Service',
|
||||
name: 'service',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The name of the service',
|
||||
},
|
||||
{
|
||||
displayName: 'External Account ID',
|
||||
name: 'externalid',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The ID of the account in the external service',
|
||||
},
|
||||
{
|
||||
displayName: 'Account Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'The name associated with the account in the external service. Often this will be a company name (e.g., "My Toystore, Inc.").',
|
||||
},
|
||||
{
|
||||
displayName: 'Logo URL',
|
||||
name: 'logoUrl',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The URL to a logo image for the external service',
|
||||
},
|
||||
{
|
||||
displayName: 'Link URL',
|
||||
name: 'linkUrl',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
"The URL to a page where the integration with the external service can be managed in the third-party's website",
|
||||
},
|
||||
{
|
||||
displayName: 'Status',
|
||||
name: 'status',
|
||||
type: 'number',
|
||||
default: 1,
|
||||
description: 'The status of the connection (0 = error; 1 = connected)',
|
||||
},
|
||||
{
|
||||
displayName: 'Syncronisation Status',
|
||||
name: 'syncStatus',
|
||||
type: 'number',
|
||||
default: 1,
|
||||
description:
|
||||
'The status of a sync triggered on the connection (0 = sync stopped; 1 = sync running)',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// connection:delete
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Connection ID',
|
||||
name: 'connectionId',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['delete'],
|
||||
resource: ['connection'],
|
||||
},
|
||||
},
|
||||
default: 0,
|
||||
required: true,
|
||||
description: 'ID of the connection to delete',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// connection:get
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Connection ID',
|
||||
name: 'connectionId',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['get'],
|
||||
resource: ['connection'],
|
||||
},
|
||||
},
|
||||
default: 0,
|
||||
required: true,
|
||||
description: 'ID of the connection to get',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// connection:getAll
|
||||
// ----------------------------------
|
||||
...activeCampaignDefaultGetAllProperties('connection', 'getAll'),
|
||||
];
|
||||
@@ -0,0 +1,487 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { activeCampaignDefaultGetAllProperties } from './GenericFunctions';
|
||||
|
||||
export const contactOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['contact'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a contact',
|
||||
action: 'Create a contact',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete a contact',
|
||||
action: 'Delete a contact',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get data of a contact',
|
||||
action: 'Get a contact',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get data of many contacts',
|
||||
action: 'Get many contacts',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update a contact',
|
||||
action: 'Update a contact',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const contactFields: INodeProperties[] = [
|
||||
// ----------------------------------
|
||||
// contact:create
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Email',
|
||||
name: 'email',
|
||||
type: 'string',
|
||||
placeholder: 'name@email.com',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['contact'],
|
||||
},
|
||||
},
|
||||
description: 'The email of the contact to create',
|
||||
},
|
||||
{
|
||||
displayName: 'Update if Exists',
|
||||
name: 'updateIfExists',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['contact'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description:
|
||||
'Whether to update user if it exists already. If not set and user exists it will error instead.',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['contact'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
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 Name or ID',
|
||||
name: 'field',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getContactCustomFields',
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'ID of the field to set. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Field Value',
|
||||
name: 'value',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Value of the field to set',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'First Name',
|
||||
name: 'firstName',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The first name of the contact to create',
|
||||
},
|
||||
{
|
||||
displayName: 'Last Name',
|
||||
name: 'lastName',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The last name of the contact to create',
|
||||
},
|
||||
{
|
||||
displayName: 'Phone',
|
||||
name: 'phone',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Phone number of the contact',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// contact:update
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Contact ID',
|
||||
name: 'contactId',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['update'],
|
||||
resource: ['contact'],
|
||||
},
|
||||
},
|
||||
default: 0,
|
||||
required: true,
|
||||
description: 'ID of the contact to update',
|
||||
},
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
description: 'The fields to update',
|
||||
placeholder: 'Add Field',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['update'],
|
||||
resource: ['contact'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
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 Name or ID',
|
||||
name: 'field',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getContactCustomFields',
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'ID of the field to set. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Field Value',
|
||||
name: 'value',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Value of the field to set',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Email',
|
||||
name: 'email',
|
||||
type: 'string',
|
||||
placeholder: 'name@email.com',
|
||||
default: '',
|
||||
description: 'Email of the contact',
|
||||
},
|
||||
{
|
||||
displayName: 'First Name',
|
||||
name: 'firstName',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'First name of the contact',
|
||||
},
|
||||
{
|
||||
displayName: 'Last Name',
|
||||
name: 'lastName',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Last name of the contact',
|
||||
},
|
||||
{
|
||||
displayName: 'Phone',
|
||||
name: 'phone',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Phone number of the contact',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// contact:delete
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Contact ID',
|
||||
name: 'contactId',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['delete'],
|
||||
resource: ['contact'],
|
||||
},
|
||||
},
|
||||
default: 0,
|
||||
required: true,
|
||||
description: 'ID of the contact to delete',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// contact:get
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Contact ID',
|
||||
name: 'contactId',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['get'],
|
||||
resource: ['contact'],
|
||||
},
|
||||
},
|
||||
default: 0,
|
||||
required: true,
|
||||
description: 'ID of the contact to get',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// contact:getAll
|
||||
// ----------------------------------
|
||||
...activeCampaignDefaultGetAllProperties('contact', 'getAll'),
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['getAll'],
|
||||
resource: ['contact'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Datetime',
|
||||
name: 'datetime',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'Contacts created on the specified date',
|
||||
},
|
||||
{
|
||||
displayName: 'Email',
|
||||
name: 'email',
|
||||
type: 'string',
|
||||
placeholder: 'name@email.com',
|
||||
default: '',
|
||||
description: 'Email address of the contact you want to get',
|
||||
},
|
||||
{
|
||||
displayName: 'Email Like',
|
||||
name: 'email_like',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Filter contacts that contain the given value in the email address',
|
||||
},
|
||||
{
|
||||
displayName: 'Exclude',
|
||||
name: 'exclude',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Exclude from the response the contact with the given ID',
|
||||
},
|
||||
{
|
||||
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: 'Active',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: 'Any',
|
||||
value: -1,
|
||||
},
|
||||
{
|
||||
name: 'Bounced',
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
name: 'Unconfirmed',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: 'Unsubscribed',
|
||||
value: 2,
|
||||
},
|
||||
],
|
||||
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: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,92 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const contactListOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['contactList'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Add',
|
||||
value: 'add',
|
||||
description: 'Add contact to a list',
|
||||
action: 'Add a contact to a list',
|
||||
},
|
||||
{
|
||||
name: 'Remove',
|
||||
value: 'remove',
|
||||
description: 'Remove contact from a list',
|
||||
action: 'Remove a contact from a list',
|
||||
},
|
||||
],
|
||||
default: 'add',
|
||||
},
|
||||
];
|
||||
|
||||
export const contactListFields: INodeProperties[] = [
|
||||
// ----------------------------------
|
||||
// contactList:add
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'List ID',
|
||||
name: 'listId',
|
||||
type: 'number',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['add'],
|
||||
resource: ['contactList'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Contact ID',
|
||||
name: 'contactId',
|
||||
type: 'number',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['add'],
|
||||
resource: ['contactList'],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// contactList:remove
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'List ID',
|
||||
name: 'listId',
|
||||
type: 'number',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['remove'],
|
||||
resource: ['contactList'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Contact ID',
|
||||
name: 'contactId',
|
||||
type: 'number',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['remove'],
|
||||
resource: ['contactList'],
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,84 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const contactTagOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['contactTag'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Add',
|
||||
value: 'add',
|
||||
description: 'Add a tag to a contact',
|
||||
action: 'Add a contact tag',
|
||||
},
|
||||
{
|
||||
name: 'Remove',
|
||||
value: 'remove',
|
||||
description: 'Remove a tag from a contact',
|
||||
action: 'Remove a contact tag',
|
||||
},
|
||||
],
|
||||
default: 'add',
|
||||
},
|
||||
];
|
||||
|
||||
export const contactTagFields: INodeProperties[] = [
|
||||
// ----------------------------------
|
||||
// contactTag:add
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Tag Name or ID',
|
||||
name: 'tagId',
|
||||
type: 'options',
|
||||
description:
|
||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getTags',
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['add'],
|
||||
resource: ['contactTag'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Contact ID',
|
||||
name: 'contactId',
|
||||
type: 'number',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['add'],
|
||||
resource: ['contactTag'],
|
||||
},
|
||||
},
|
||||
},
|
||||
// ----------------------------------
|
||||
// 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',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,425 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { allCurrencies } from './currencies';
|
||||
import { activeCampaignDefaultGetAllProperties } from './GenericFunctions';
|
||||
|
||||
export const dealOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a deal',
|
||||
action: 'Create a deal',
|
||||
},
|
||||
{
|
||||
name: 'Create Note',
|
||||
value: 'createNote',
|
||||
description: 'Create a deal note',
|
||||
action: 'Create a deal note',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete a deal',
|
||||
action: 'Delete a deal',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get data of a deal',
|
||||
action: 'Get a deal',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get data of many deals',
|
||||
action: 'Get many deals',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update a deal',
|
||||
action: 'Update a deal',
|
||||
},
|
||||
{
|
||||
name: 'Update Deal Note',
|
||||
value: 'updateNote',
|
||||
description: 'Update a deal note',
|
||||
action: 'Update a deal note',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const dealFields: INodeProperties[] = [
|
||||
// ----------------------------------
|
||||
// deal:create
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Title',
|
||||
name: 'title',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
description: 'The title of the deal',
|
||||
},
|
||||
{
|
||||
displayName: "Deal's Contact ID",
|
||||
name: 'contact',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
description: "The ID of the deal's contact",
|
||||
},
|
||||
{
|
||||
displayName: 'Deal Value',
|
||||
name: 'value',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
description: 'The value of the deal in cents',
|
||||
},
|
||||
{
|
||||
displayName: 'Currency',
|
||||
name: 'currency',
|
||||
type: 'options',
|
||||
default: 'eur',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
options: allCurrencies,
|
||||
description: 'The currency of the deal in 3-character ISO format',
|
||||
},
|
||||
{
|
||||
displayName: 'Deal Pipeline ID',
|
||||
name: 'group',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
description: 'The pipeline ID of the deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Deal Stage ID',
|
||||
name: 'stage',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
description: 'The stage ID of the deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Deal Owner ID',
|
||||
name: 'owner',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
description: 'The owner ID of the deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Description',
|
||||
name: 'description',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The description of the deal',
|
||||
},
|
||||
|
||||
{
|
||||
displayName: 'Deal Percentage',
|
||||
name: 'percent',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The percentage of the deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Deal Status',
|
||||
name: 'status',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The status of the deal',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// deal:update
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Deal ID',
|
||||
name: 'dealId',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['update'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
default: 0,
|
||||
required: true,
|
||||
description: 'ID of the deal to update',
|
||||
},
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
description: 'The fields to update',
|
||||
placeholder: 'Add Field',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['update'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Title',
|
||||
name: 'title',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The title of the deal',
|
||||
},
|
||||
{
|
||||
displayName: "Deal's Contact ID",
|
||||
name: 'contact',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: "The ID of the deal's contact",
|
||||
},
|
||||
{
|
||||
displayName: 'Deal Value',
|
||||
name: 'value',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The value of the deal in cents',
|
||||
},
|
||||
{
|
||||
displayName: 'Currency',
|
||||
name: 'currency',
|
||||
type: 'options',
|
||||
options: allCurrencies,
|
||||
default: 'eur',
|
||||
description: 'The currency of the deal in 3-character ISO format',
|
||||
},
|
||||
{
|
||||
displayName: 'Description',
|
||||
name: 'description',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The description of the deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Deal Pipeline ID',
|
||||
name: 'group',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The pipeline ID of the deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Deal Stage ID',
|
||||
name: 'stage',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The stage ID of the deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Deal Owner ID',
|
||||
name: 'owner',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The owner ID of the deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Deal Percentage',
|
||||
name: 'percent',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The percentage of the deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Deal Status',
|
||||
name: 'status',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The status of the deal',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// deal:delete
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Deal ID',
|
||||
name: 'dealId',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['delete'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
description: 'The ID of the deal to delete',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// deal:get
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Deal ID',
|
||||
name: 'dealId',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['get'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
description: 'The ID of the deal to get',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// deal:getAll
|
||||
// ----------------------------------
|
||||
...activeCampaignDefaultGetAllProperties('deal', 'getAll'),
|
||||
|
||||
// ----------------------------------
|
||||
// dealNote:create
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Deal ID',
|
||||
name: 'dealId',
|
||||
type: 'number',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['createNote'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
description: 'The ID of the deal note',
|
||||
},
|
||||
{
|
||||
displayName: 'Deal Note',
|
||||
name: 'dealNote',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['createNote'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
description: 'The content of the deal note',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// dealNote:update
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Deal ID',
|
||||
name: 'dealId',
|
||||
type: 'number',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['updateNote'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
description: 'The ID of the deal note',
|
||||
},
|
||||
{
|
||||
displayName: 'Deal Note ID',
|
||||
name: 'dealNoteId',
|
||||
type: 'number',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['updateNote'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
description: 'The ID of the deal note',
|
||||
},
|
||||
{
|
||||
displayName: 'Deal Note',
|
||||
name: 'dealNote',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['updateNote'],
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
description: 'The content of the deal note',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,226 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { activeCampaignDefaultGetAllProperties } from './GenericFunctions';
|
||||
|
||||
export const ecomCustomerOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['ecommerceCustomer'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a E-commerce Customer',
|
||||
action: 'Create an e-commerce customer',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete a E-commerce Customer',
|
||||
action: 'Delete an e-commerce customer',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get data of a E-commerce Customer',
|
||||
action: 'Get an e-commerce customer',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get data of many E-commerce Customers',
|
||||
action: 'Get many e-commerce customers',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update a E-commerce Customer',
|
||||
action: 'Update an e-commerce customer',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const ecomCustomerFields: INodeProperties[] = [
|
||||
// ----------------------------------
|
||||
// ecommerceCustomer:create
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Service ID',
|
||||
name: 'connectionid',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceCustomer'],
|
||||
},
|
||||
},
|
||||
description: 'The ID of the connection object for the service where the customer originates',
|
||||
},
|
||||
{
|
||||
displayName: 'Customer ID',
|
||||
name: 'externalid',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceCustomer'],
|
||||
},
|
||||
},
|
||||
description: 'The ID of the customer in the external service',
|
||||
},
|
||||
{
|
||||
displayName: 'Customer Email',
|
||||
name: 'email',
|
||||
type: 'string',
|
||||
placeholder: 'name@email.com',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceCustomer'],
|
||||
},
|
||||
},
|
||||
description: 'The email address of the customer',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceCustomer'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Accepts Marketing',
|
||||
name: 'acceptsMarketing',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether customer has opt-ed in to marketing communications',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// ecommerceCustomer:update
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Customer ID',
|
||||
name: 'ecommerceCustomerId',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['update'],
|
||||
resource: ['ecommerceCustomer'],
|
||||
},
|
||||
},
|
||||
default: 0,
|
||||
required: true,
|
||||
description: 'ID of the E-commerce customer to update',
|
||||
},
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
description: 'The fields to update',
|
||||
placeholder: 'Add Field',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['update'],
|
||||
resource: ['ecommerceCustomer'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Service ID',
|
||||
name: 'connectionid',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'The ID of the connection object for the service where the customer originates',
|
||||
},
|
||||
{
|
||||
displayName: 'Customer ID',
|
||||
name: 'externalid',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The ID of the customer in the external service',
|
||||
},
|
||||
{
|
||||
displayName: 'Customer Email',
|
||||
name: 'email',
|
||||
type: 'string',
|
||||
placeholder: 'name@email.com',
|
||||
default: '',
|
||||
description: 'The email address of the customer',
|
||||
},
|
||||
{
|
||||
displayName: 'Accepts Marketing',
|
||||
name: 'acceptsMarketing',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether customer has opt-ed in to marketing communications',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// ecommerceCustomer:delete
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Customer ID',
|
||||
name: 'ecommerceCustomerId',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['delete'],
|
||||
resource: ['ecommerceCustomer'],
|
||||
},
|
||||
},
|
||||
default: 0,
|
||||
required: true,
|
||||
description: 'ID of the E-commerce customer to delete',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// ecommerceCustomer:get
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Customer ID',
|
||||
name: 'ecommerceCustomerId',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['get'],
|
||||
resource: ['ecommerceCustomer'],
|
||||
},
|
||||
},
|
||||
default: 0,
|
||||
required: true,
|
||||
description: 'ID of the E-commerce customer to get',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// ecommerceCustomer:getAll
|
||||
// ----------------------------------
|
||||
...activeCampaignDefaultGetAllProperties('ecommerceCustomer', 'getAll'),
|
||||
];
|
||||
@@ -0,0 +1,627 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { allCurrencies } from './currencies';
|
||||
import { activeCampaignDefaultGetAllProperties } from './GenericFunctions';
|
||||
|
||||
export const ecomOrderOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a order',
|
||||
action: 'Create an e-commerce order',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete a order',
|
||||
action: 'Delete an e-commerce order',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get data of a order',
|
||||
action: 'Get an e-commerce order',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get data of many orders',
|
||||
action: 'Get many e-commerce orders',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update a order',
|
||||
action: 'Update an e-commerce order',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const ecomOrderFields: INodeProperties[] = [
|
||||
// ----------------------------------
|
||||
// ecommerceOrder:create
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'External ID',
|
||||
name: 'externalid',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The ID of the order in the external service. ONLY REQUIRED IF EXTERNALCHECKOUTID NOT INCLUDED.',
|
||||
},
|
||||
{
|
||||
displayName: 'External Checkout ID',
|
||||
name: 'externalcheckoutid',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The ID of the cart in the external service. ONLY REQUIRED IF EXTERNALID IS NOT INCLUDED.',
|
||||
},
|
||||
{
|
||||
displayName: 'Order Source',
|
||||
name: 'source',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The order source code (0 - will not trigger automations, 1 - will trigger automations)',
|
||||
},
|
||||
{
|
||||
displayName: 'Customer Email',
|
||||
name: 'email',
|
||||
type: 'string',
|
||||
placeholder: 'name@email.com',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
description: 'The email address of the customer who placed the order',
|
||||
},
|
||||
{
|
||||
displayName: 'Total Price',
|
||||
name: 'totalPrice',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The total price of the order in cents, including tax and shipping charges. (i.e. $456.78 => 45678). Must be greater than or equal to zero.',
|
||||
},
|
||||
{
|
||||
displayName: 'Order Currency',
|
||||
name: 'currency',
|
||||
type: 'options',
|
||||
default: 'eur',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
options: allCurrencies,
|
||||
description: 'The currency of the order (3-digit ISO code, e.g., "USD")',
|
||||
},
|
||||
{
|
||||
displayName: 'Connection ID',
|
||||
name: 'connectionid',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
description: 'The ID of the connection from which this order originated',
|
||||
},
|
||||
{
|
||||
displayName: 'Customer ID',
|
||||
name: 'customerid',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
description: 'The ID of the customer associated with this order',
|
||||
},
|
||||
{
|
||||
displayName: 'Creation Date',
|
||||
name: 'externalCreatedDate',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
description: 'The date the order was placed',
|
||||
},
|
||||
{
|
||||
displayName: 'Abandoning Date',
|
||||
name: 'abandonedDate',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
description: 'The date the cart was abandoned. REQUIRED ONLY IF INCLUDING EXTERNALCHECKOUTID.',
|
||||
},
|
||||
{
|
||||
displayName: 'Products',
|
||||
name: 'orderProducts',
|
||||
type: 'collection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add product',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
description: 'All ordered products',
|
||||
placeholder: 'Add product field',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The name of the product',
|
||||
},
|
||||
{
|
||||
displayName: 'Price',
|
||||
name: 'price',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description:
|
||||
'The price of the product, in cents. (i.e. $456.78 => 45678). Must be greater than or equal to zero.',
|
||||
},
|
||||
{
|
||||
displayName: 'Product Quantity',
|
||||
name: 'quantity',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The quantity ordered',
|
||||
},
|
||||
{
|
||||
displayName: 'Product External ID',
|
||||
name: 'externalid',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The ID of the product in the external service',
|
||||
},
|
||||
{
|
||||
displayName: 'Product Category',
|
||||
name: 'category',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The category of the product',
|
||||
},
|
||||
{
|
||||
displayName: 'SKU',
|
||||
name: 'sku',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The SKU for the product',
|
||||
},
|
||||
{
|
||||
displayName: 'Description',
|
||||
name: 'description',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The description of the product',
|
||||
},
|
||||
{
|
||||
displayName: 'Image URL',
|
||||
name: 'imageUrl',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'An Image URL that displays an image of the product',
|
||||
},
|
||||
{
|
||||
displayName: 'Product URL',
|
||||
name: 'productUrl',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'A URL linking to the product in your store',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Shipping Amount',
|
||||
name: 'shippingAmount',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The total shipping amount for the order in cents',
|
||||
},
|
||||
|
||||
{
|
||||
displayName: 'Tax Amount',
|
||||
name: 'taxAmount',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The total tax amount for the order in cents',
|
||||
},
|
||||
{
|
||||
displayName: 'Discount Amount',
|
||||
name: 'discountAmount',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The total discount amount for the order in cents',
|
||||
},
|
||||
{
|
||||
displayName: 'Order URL',
|
||||
name: 'orderUrl',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The URL for the order in the external service',
|
||||
},
|
||||
{
|
||||
displayName: 'External Updated Date',
|
||||
name: 'externalUpdatedDate',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'The date the order was updated',
|
||||
},
|
||||
{
|
||||
displayName: 'Shipping Method',
|
||||
name: 'shippingMethod',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The shipping method of the order',
|
||||
},
|
||||
{
|
||||
displayName: 'Order Number',
|
||||
name: 'orderNumber',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The order number. This can be different than the externalid.',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// ecommerceOrder:update
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Order ID',
|
||||
name: 'orderId',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['update'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
description: 'The ID of the e-commerce order',
|
||||
},
|
||||
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['update'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'External ID',
|
||||
name: 'externalid',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'The ID of the order in the external service. ONLY REQUIRED IF EXTERNALCHECKOUTID NOT INCLUDED.',
|
||||
},
|
||||
{
|
||||
displayName: 'External Checkout ID',
|
||||
name: 'externalcheckoutid',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'The ID of the cart in the external service. ONLY REQUIRED IF EXTERNALID IS NOT INCLUDED.',
|
||||
},
|
||||
{
|
||||
displayName: 'Order Source',
|
||||
name: 'source',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description:
|
||||
'The order source code (0 - will not trigger automations, 1 - will trigger automations)',
|
||||
},
|
||||
{
|
||||
displayName: 'Customer Email',
|
||||
name: 'email',
|
||||
type: 'string',
|
||||
placeholder: 'name@email.com',
|
||||
default: '',
|
||||
description: 'The email address of the customer who placed the order',
|
||||
},
|
||||
{
|
||||
displayName: 'Total Price',
|
||||
name: 'totalPrice',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description:
|
||||
'The total price of the order in cents, including tax and shipping charges. (i.e. $456.78 => 45678). Must be greater than or equal to zero.',
|
||||
},
|
||||
{
|
||||
displayName: 'Order Currency',
|
||||
name: 'currency',
|
||||
type: 'options',
|
||||
default: 'eur',
|
||||
options: allCurrencies,
|
||||
description: 'The currency of the order (3-digit ISO code, e.g., "USD")',
|
||||
},
|
||||
{
|
||||
displayName: 'Connection ID',
|
||||
name: 'connectionid',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The ID of the connection from which this order originated',
|
||||
},
|
||||
{
|
||||
displayName: 'Customer ID',
|
||||
name: 'customerid',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The ID of the customer associated with this order',
|
||||
},
|
||||
{
|
||||
displayName: 'Creation Date',
|
||||
name: 'externalupdatedDate',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'The date the order was placed',
|
||||
},
|
||||
{
|
||||
displayName: 'Abandoning Date',
|
||||
name: 'abandonedDate',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description:
|
||||
'The date the cart was abandoned. REQUIRED ONLY IF INCLUDING EXTERNALCHECKOUTID.',
|
||||
},
|
||||
{
|
||||
displayName: 'Shipping Amount',
|
||||
name: 'shippingAmount',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The total shipping amount for the order in cents',
|
||||
},
|
||||
|
||||
{
|
||||
displayName: 'Tax Amount',
|
||||
name: 'taxAmount',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The total tax amount for the order in cents',
|
||||
},
|
||||
{
|
||||
displayName: 'Discount Amount',
|
||||
name: 'discountAmount',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The total discount amount for the order in cents',
|
||||
},
|
||||
{
|
||||
displayName: 'Order URL',
|
||||
name: 'orderUrl',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The URL for the order in the external service',
|
||||
},
|
||||
{
|
||||
displayName: 'External Updated Date',
|
||||
name: 'externalUpdatedDate',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'The date the order was updated',
|
||||
},
|
||||
{
|
||||
displayName: 'Shipping Method',
|
||||
name: 'shippingMethod',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The shipping method of the order',
|
||||
},
|
||||
{
|
||||
displayName: 'Order Number',
|
||||
name: 'orderNumber',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The order number. This can be different than the externalid.',
|
||||
},
|
||||
|
||||
{
|
||||
displayName: 'Products',
|
||||
name: 'orderProducts',
|
||||
type: 'collection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add product',
|
||||
},
|
||||
default: {},
|
||||
description: 'All ordered products',
|
||||
placeholder: 'Add product field',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The name of the product',
|
||||
},
|
||||
{
|
||||
displayName: 'Price',
|
||||
name: 'price',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description:
|
||||
'The price of the product, in cents. (i.e. $456.78 => 45678). Must be greater than or equal to zero.',
|
||||
},
|
||||
{
|
||||
displayName: 'Product Quantity',
|
||||
name: 'quantity',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The quantity ordered',
|
||||
},
|
||||
{
|
||||
displayName: 'Product External ID',
|
||||
name: 'externalid',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The ID of the product in the external service',
|
||||
},
|
||||
{
|
||||
displayName: 'Product Category',
|
||||
name: 'category',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The category of the product',
|
||||
},
|
||||
{
|
||||
displayName: 'SKU',
|
||||
name: 'sku',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The SKU for the product',
|
||||
},
|
||||
{
|
||||
displayName: 'Description',
|
||||
name: 'description',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The description of the product',
|
||||
},
|
||||
{
|
||||
displayName: 'Image URL',
|
||||
name: 'imageUrl',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'An Image URL that displays an image of the product',
|
||||
},
|
||||
{
|
||||
displayName: 'Product URL',
|
||||
name: 'productUrl',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'A URL linking to the product in your store',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// ecommerceOrder:delete
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Order ID',
|
||||
name: 'orderId',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['delete'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
description: 'The ID of the e-commerce order',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// ecommerceOrder:get
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Order ID',
|
||||
name: 'orderId',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['get'],
|
||||
resource: ['ecommerceOrder'],
|
||||
},
|
||||
},
|
||||
description: 'The ID of the e-commerce order',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// ecommerceOrder:getAll
|
||||
// ----------------------------------
|
||||
...activeCampaignDefaultGetAllProperties('ecommerceOrder', 'getAll'),
|
||||
];
|
||||
@@ -0,0 +1,79 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { activeCampaignDefaultGetAllProperties } from './GenericFunctions';
|
||||
|
||||
export const ecomOrderProductsOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['ecommerceOrderProducts'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get data of many order products',
|
||||
action: 'Get many ecommerce orders',
|
||||
},
|
||||
{
|
||||
name: 'Get by Product ID',
|
||||
value: 'getByProductId',
|
||||
description: 'Get data of a ordered product',
|
||||
action: 'Get an e-commerce order product by product ID',
|
||||
},
|
||||
{
|
||||
name: 'Get by Order ID',
|
||||
value: 'getByOrderId',
|
||||
description: "Get data of an order's products",
|
||||
action: 'Get an e-commerce order product by order ID',
|
||||
},
|
||||
],
|
||||
default: 'getAll',
|
||||
},
|
||||
];
|
||||
|
||||
export const ecomOrderProductsFields: INodeProperties[] = [
|
||||
// ----------------------------------
|
||||
// ecommerceOrderProducts:getByOrderId
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Order ID',
|
||||
name: 'orderId',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['getByOrderId'],
|
||||
resource: ['ecommerceOrderProducts'],
|
||||
},
|
||||
},
|
||||
description: "The ID of the order whose products you'd like returned",
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// ecommerceOrderProducts:getByProductId
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Product ID',
|
||||
name: 'procuctId',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['getByProductId'],
|
||||
resource: ['ecommerceOrderProducts'],
|
||||
},
|
||||
},
|
||||
description: "The ID of the product you'd like returned",
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// ecommerceOrderProducts:getAll
|
||||
// ----------------------------------
|
||||
...activeCampaignDefaultGetAllProperties('ecommerceOrderProducts', 'getAll'),
|
||||
];
|
||||
@@ -0,0 +1,166 @@
|
||||
import type {
|
||||
IDataObject,
|
||||
IExecuteFunctions,
|
||||
IHookFunctions,
|
||||
ILoadOptionsFunctions,
|
||||
INodeProperties,
|
||||
JsonObject,
|
||||
IRequestOptions,
|
||||
IHttpRequestMethods,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeApiError } from 'n8n-workflow';
|
||||
|
||||
export interface IProduct {
|
||||
fields: {
|
||||
item?: object[];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an API request to ActiveCampaign
|
||||
*
|
||||
*/
|
||||
export async function activeCampaignApiRequest(
|
||||
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
endpoint: string,
|
||||
body: IDataObject,
|
||||
query?: IDataObject,
|
||||
dataKey?: string,
|
||||
): Promise<any> {
|
||||
const credentials = await this.getCredentials('activeCampaignApi');
|
||||
|
||||
if (query === undefined) {
|
||||
query = {};
|
||||
}
|
||||
|
||||
const options: IRequestOptions = {
|
||||
headers: {},
|
||||
method,
|
||||
qs: query,
|
||||
uri: `${credentials.apiUrl}${endpoint}`,
|
||||
json: true,
|
||||
};
|
||||
|
||||
if (Object.keys(body).length !== 0) {
|
||||
options.body = body;
|
||||
}
|
||||
|
||||
try {
|
||||
const responseData = await this.helpers.requestWithAuthentication.call(
|
||||
this,
|
||||
'activeCampaignApi',
|
||||
options,
|
||||
);
|
||||
|
||||
if (responseData.success === false) {
|
||||
throw new NodeApiError(this.getNode(), responseData as JsonObject);
|
||||
}
|
||||
|
||||
if (dataKey === undefined) {
|
||||
return responseData;
|
||||
} else {
|
||||
return responseData[dataKey] as IDataObject;
|
||||
}
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an API request to paginated ActiveCampaign endpoint
|
||||
* and return all results
|
||||
*
|
||||
* @param {(IHookFunctions | IExecuteFunctions)} this
|
||||
*/
|
||||
export async function activeCampaignApiRequestAllItems(
|
||||
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
endpoint: string,
|
||||
body: IDataObject,
|
||||
query?: IDataObject,
|
||||
dataKey?: string,
|
||||
): Promise<any> {
|
||||
if (query === undefined) {
|
||||
query = {};
|
||||
}
|
||||
query.limit = 100;
|
||||
query.offset = 0;
|
||||
|
||||
const returnData: IDataObject[] = [];
|
||||
|
||||
let responseData;
|
||||
|
||||
let itemsReceived = 0;
|
||||
do {
|
||||
responseData = await activeCampaignApiRequest.call(this, method, endpoint, body, query);
|
||||
|
||||
if (dataKey === undefined) {
|
||||
returnData.push.apply(returnData, responseData as IDataObject[]);
|
||||
if (returnData !== undefined) {
|
||||
itemsReceived += returnData.length;
|
||||
}
|
||||
} else {
|
||||
returnData.push.apply(returnData, responseData[dataKey] as IDataObject[]);
|
||||
if (responseData[dataKey] !== undefined) {
|
||||
itemsReceived += responseData[dataKey].length;
|
||||
}
|
||||
}
|
||||
|
||||
query.offset = itemsReceived;
|
||||
} while (responseData.meta?.total !== undefined && responseData.meta.total > itemsReceived);
|
||||
|
||||
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: 'Whether to return all results 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: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: [operation],
|
||||
resource: [resource],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { activeCampaignDefaultGetAllProperties } from './GenericFunctions';
|
||||
|
||||
export const listOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['list'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many lists',
|
||||
action: 'Get many lists',
|
||||
},
|
||||
],
|
||||
default: 'getAll',
|
||||
},
|
||||
];
|
||||
|
||||
export const listFields: INodeProperties[] = [
|
||||
// ----------------------------------
|
||||
// list:getAll
|
||||
// ----------------------------------
|
||||
...activeCampaignDefaultGetAllProperties('list', 'getAll'),
|
||||
];
|
||||
@@ -0,0 +1,203 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { activeCampaignDefaultGetAllProperties } from './GenericFunctions';
|
||||
|
||||
export const tagOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['tag'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a tag',
|
||||
action: 'Create a tag',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete a tag',
|
||||
action: 'Delete a tag',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get data of a tag',
|
||||
action: 'Get a tag',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get data of many tags',
|
||||
action: 'Get many tags',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update a tag',
|
||||
action: 'Update a tag',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const tagFields: INodeProperties[] = [
|
||||
// ----------------------------------
|
||||
// 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'),
|
||||
];
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"account": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"accountUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"createdTimestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedTimestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"accountContacts": {
|
||||
"type": "string"
|
||||
},
|
||||
"accountCustomFieldData": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactEmails": {
|
||||
"type": "string"
|
||||
},
|
||||
"emailActivities": {
|
||||
"type": "string"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"contactCount": {
|
||||
"type": "string"
|
||||
},
|
||||
"createdTimestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"dealCount": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"accountContacts": {
|
||||
"type": "string"
|
||||
},
|
||||
"accountCustomFieldData": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactEmails": {
|
||||
"type": "string"
|
||||
},
|
||||
"emailActivities": {
|
||||
"type": "string"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedTimestamp": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"anonymized": {
|
||||
"type": "string"
|
||||
},
|
||||
"bounced_hard": {
|
||||
"type": "string"
|
||||
},
|
||||
"bounced_soft": {
|
||||
"type": "string"
|
||||
},
|
||||
"cdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_utc_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"deleted": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"email_domain": {
|
||||
"type": "string"
|
||||
},
|
||||
"email_local": {
|
||||
"type": "string"
|
||||
},
|
||||
"fieldValues": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"firstName": {
|
||||
"type": "string"
|
||||
},
|
||||
"gravatar": {
|
||||
"type": "string"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"ip": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastName": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"automationEntryCounts": {
|
||||
"type": "string"
|
||||
},
|
||||
"bounceLogs": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactAutomations": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactData": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactDeals": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactGoals": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactLists": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactLogs": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactTags": {
|
||||
"type": "string"
|
||||
},
|
||||
"deals": {
|
||||
"type": "string"
|
||||
},
|
||||
"fieldValues": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoIps": {
|
||||
"type": "string"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"plusAppend": {
|
||||
"type": "string"
|
||||
},
|
||||
"scoreValues": {
|
||||
"type": "string"
|
||||
},
|
||||
"trackingLogs": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mpp_tracking": {
|
||||
"type": "string"
|
||||
},
|
||||
"orgid": {
|
||||
"type": "string"
|
||||
},
|
||||
"orgname": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"segmentio_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"sentcnt": {
|
||||
"type": "string"
|
||||
},
|
||||
"socialdata_lastcheck": {
|
||||
"type": "null"
|
||||
},
|
||||
"udate": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_utc_timestamp": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,660 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"accountContacts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"account": {
|
||||
"type": "string"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"createdTimestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"jobTitle": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"account": {
|
||||
"type": "string"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updatedTimestamp": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"accountContacts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"anonymized": {
|
||||
"type": "string"
|
||||
},
|
||||
"bounced_hard": {
|
||||
"type": "string"
|
||||
},
|
||||
"bounced_soft": {
|
||||
"type": "string"
|
||||
},
|
||||
"cdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactAutomations": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"contactData": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactLists": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"created_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_utc_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"deals": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"deleted": {
|
||||
"type": "string"
|
||||
},
|
||||
"deleted_at": {
|
||||
"type": "null"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"email_domain": {
|
||||
"type": "string"
|
||||
},
|
||||
"email_local": {
|
||||
"type": "string"
|
||||
},
|
||||
"fieldValues": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"firstName": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoIps": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"gravatar": {
|
||||
"type": "string"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"ip": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastName": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"accountContacts": {
|
||||
"type": "string"
|
||||
},
|
||||
"automationEntryCounts": {
|
||||
"type": "string"
|
||||
},
|
||||
"bounceLogs": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactAutomations": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactData": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactDeals": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactGoals": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactLists": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactLogs": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactTags": {
|
||||
"type": "string"
|
||||
},
|
||||
"deals": {
|
||||
"type": "string"
|
||||
},
|
||||
"fieldValues": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoIps": {
|
||||
"type": "string"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"plusAppend": {
|
||||
"type": "string"
|
||||
},
|
||||
"scoreValues": {
|
||||
"type": "string"
|
||||
},
|
||||
"trackingLogs": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mpp_tracking": {
|
||||
"type": "string"
|
||||
},
|
||||
"orgid": {
|
||||
"type": "string"
|
||||
},
|
||||
"orgname": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"segmentio_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"sentcnt": {
|
||||
"type": "string"
|
||||
},
|
||||
"socialdata_lastcheck": {
|
||||
"type": "null"
|
||||
},
|
||||
"udate": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_utc_timestamp": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"contactAutomations": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"adddate": {
|
||||
"type": "string"
|
||||
},
|
||||
"automation": {
|
||||
"type": "string"
|
||||
},
|
||||
"completed": {
|
||||
"type": "integer"
|
||||
},
|
||||
"completedElements": {
|
||||
"type": "integer"
|
||||
},
|
||||
"completeValue": {
|
||||
"type": "integer"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastblock": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastlogid": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"automation": {
|
||||
"type": "string"
|
||||
},
|
||||
"automationLogs": {
|
||||
"type": "string"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactGoals": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"seriesid": {
|
||||
"type": "string"
|
||||
},
|
||||
"startid": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"totalElements": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"contactData": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"fb_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"fb_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"ga_campaign_content": {
|
||||
"type": "string"
|
||||
},
|
||||
"ga_campaign_customsegment": {
|
||||
"type": "string"
|
||||
},
|
||||
"ga_campaign_medium": {
|
||||
"type": "string"
|
||||
},
|
||||
"ga_campaign_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"ga_campaign_source": {
|
||||
"type": "string"
|
||||
},
|
||||
"ga_campaign_term": {
|
||||
"type": "string"
|
||||
},
|
||||
"ga_first_visit": {
|
||||
"type": "null"
|
||||
},
|
||||
"ga_times_visited": {
|
||||
"type": "string"
|
||||
},
|
||||
"geo_country": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoArea": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoCity": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoCountry2": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoIp4": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoLat": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoLon": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoState": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoTz": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoTzOffset": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoZip": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"tstamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"tw_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_timestamp": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"contactLists": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"autosyncLog": {
|
||||
"type": "null"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"first_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"ip4_last": {
|
||||
"type": "string"
|
||||
},
|
||||
"ip4Sub": {
|
||||
"type": "string"
|
||||
},
|
||||
"ip4Unsub": {
|
||||
"type": "string"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"automation": {
|
||||
"type": "string"
|
||||
},
|
||||
"autosyncLog": {
|
||||
"type": "string"
|
||||
},
|
||||
"campaign": {
|
||||
"type": "string"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"form": {
|
||||
"type": "string"
|
||||
},
|
||||
"list": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"unsubscribeAutomation": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "null"
|
||||
},
|
||||
"responder": {
|
||||
"type": "string"
|
||||
},
|
||||
"sdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"seriesid": {
|
||||
"type": "string"
|
||||
},
|
||||
"sourceid": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"sync": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_timestamp": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deals": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"activitycount": {
|
||||
"type": "string"
|
||||
},
|
||||
"cdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"currency": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"isDisabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"account": {
|
||||
"type": "string"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactDeals": {
|
||||
"type": "string"
|
||||
},
|
||||
"customerAccount": {
|
||||
"type": "string"
|
||||
},
|
||||
"dealActivities": {
|
||||
"type": "string"
|
||||
},
|
||||
"dealCustomFieldData": {
|
||||
"type": "string"
|
||||
},
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"nextTask": {
|
||||
"type": "string"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"scoreValues": {
|
||||
"type": "string"
|
||||
},
|
||||
"stage": {
|
||||
"type": "string"
|
||||
},
|
||||
"tasks": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"nextdealid": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"percent": {
|
||||
"type": "string"
|
||||
},
|
||||
"stage": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
},
|
||||
"winProbability": {
|
||||
"type": "null"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fieldValues": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"field": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"udate": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"geoIps": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"campaignid": {
|
||||
"type": "string"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoAddress": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoaddrid": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"ip4": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"geoAddress": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"messageid": {
|
||||
"type": "string"
|
||||
},
|
||||
"tstamp": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"anonymized": {
|
||||
"type": "string"
|
||||
},
|
||||
"bounced_hard": {
|
||||
"type": "string"
|
||||
},
|
||||
"bounced_soft": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_utc_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"deleted": {
|
||||
"type": "string"
|
||||
},
|
||||
"deleted_at": {
|
||||
"type": "null"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"email_domain": {
|
||||
"type": "string"
|
||||
},
|
||||
"email_local": {
|
||||
"type": "string"
|
||||
},
|
||||
"firstName": {
|
||||
"type": "string"
|
||||
},
|
||||
"gravatar": {
|
||||
"type": "string"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"ip": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastName": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"accountContacts": {
|
||||
"type": "string"
|
||||
},
|
||||
"automationEntryCounts": {
|
||||
"type": "string"
|
||||
},
|
||||
"bounceLogs": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactAutomations": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactData": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactDeals": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactGoals": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactLists": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactLogs": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactTags": {
|
||||
"type": "string"
|
||||
},
|
||||
"deals": {
|
||||
"type": "string"
|
||||
},
|
||||
"fieldValues": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoIps": {
|
||||
"type": "string"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"plusAppend": {
|
||||
"type": "string"
|
||||
},
|
||||
"scoreValues": {
|
||||
"type": "string"
|
||||
},
|
||||
"trackingLogs": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mpp_tracking": {
|
||||
"type": "string"
|
||||
},
|
||||
"orgid": {
|
||||
"type": "string"
|
||||
},
|
||||
"orgname": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"segmentio_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"sentcnt": {
|
||||
"type": "string"
|
||||
},
|
||||
"socialdata_lastcheck": {
|
||||
"type": "null"
|
||||
},
|
||||
"udate": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_utc_timestamp": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"anonymized": {
|
||||
"type": "string"
|
||||
},
|
||||
"bounced_hard": {
|
||||
"type": "string"
|
||||
},
|
||||
"bounced_soft": {
|
||||
"type": "string"
|
||||
},
|
||||
"cdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_utc_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"deleted": {
|
||||
"type": "string"
|
||||
},
|
||||
"deleted_at": {
|
||||
"type": "null"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"email_domain": {
|
||||
"type": "string"
|
||||
},
|
||||
"email_local": {
|
||||
"type": "string"
|
||||
},
|
||||
"fieldValues": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"firstName": {
|
||||
"type": "string"
|
||||
},
|
||||
"gravatar": {
|
||||
"type": "string"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"ip": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastName": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"accountContacts": {
|
||||
"type": "string"
|
||||
},
|
||||
"automationEntryCounts": {
|
||||
"type": "string"
|
||||
},
|
||||
"bounceLogs": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactAutomations": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactData": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactDeals": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactGoals": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactLists": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactLogs": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactTags": {
|
||||
"type": "string"
|
||||
},
|
||||
"deals": {
|
||||
"type": "string"
|
||||
},
|
||||
"fieldValues": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoIps": {
|
||||
"type": "string"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"plusAppend": {
|
||||
"type": "string"
|
||||
},
|
||||
"scoreValues": {
|
||||
"type": "string"
|
||||
},
|
||||
"trackingLogs": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mpp_tracking": {
|
||||
"type": "string"
|
||||
},
|
||||
"orgid": {
|
||||
"type": "string"
|
||||
},
|
||||
"orgname": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"segmentio_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"sentcnt": {
|
||||
"type": "string"
|
||||
},
|
||||
"socialdata_lastcheck": {
|
||||
"type": "null"
|
||||
},
|
||||
"udate": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_utc_timestamp": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_by": {
|
||||
"type": "null"
|
||||
},
|
||||
"created_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updated_by": {
|
||||
"type": "null"
|
||||
},
|
||||
"updated_timestamp": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 2
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"contacts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"anonymized": {
|
||||
"type": "string"
|
||||
},
|
||||
"bounced_date": {
|
||||
"type": "null"
|
||||
},
|
||||
"bounced_hard": {
|
||||
"type": "string"
|
||||
},
|
||||
"bounced_soft": {
|
||||
"type": "string"
|
||||
},
|
||||
"cdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_utc_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"deleted": {
|
||||
"type": "string"
|
||||
},
|
||||
"deleted_at": {
|
||||
"type": "null"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"email_domain": {
|
||||
"type": "string"
|
||||
},
|
||||
"email_local": {
|
||||
"type": "string"
|
||||
},
|
||||
"firstName": {
|
||||
"type": "string"
|
||||
},
|
||||
"gravatar": {
|
||||
"type": "string"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"ip": {
|
||||
"type": "string"
|
||||
},
|
||||
"last_mpp_open_date": {
|
||||
"type": "null"
|
||||
},
|
||||
"lastName": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"accountContacts": {
|
||||
"type": "string"
|
||||
},
|
||||
"automationEntryCounts": {
|
||||
"type": "string"
|
||||
},
|
||||
"bounceLogs": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactAutomations": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactData": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactDeals": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactGoals": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactLists": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactLogs": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactTags": {
|
||||
"type": "string"
|
||||
},
|
||||
"deals": {
|
||||
"type": "string"
|
||||
},
|
||||
"fieldValues": {
|
||||
"type": "string"
|
||||
},
|
||||
"geoIps": {
|
||||
"type": "string"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"plusAppend": {
|
||||
"type": "string"
|
||||
},
|
||||
"scoreValues": {
|
||||
"type": "string"
|
||||
},
|
||||
"trackingLogs": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mpp_tracking": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "null"
|
||||
},
|
||||
"orgid": {
|
||||
"type": "string"
|
||||
},
|
||||
"orgname": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"segmentio_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"sentcnt": {
|
||||
"type": "string"
|
||||
},
|
||||
"socialdata_lastcheck": {
|
||||
"type": "null"
|
||||
},
|
||||
"udate": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_utc_timestamp": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deal": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"account": {
|
||||
"type": "null"
|
||||
},
|
||||
"cdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"currency": {
|
||||
"type": "string"
|
||||
},
|
||||
"customerAccount": {
|
||||
"type": "null"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"isDisabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"account": {
|
||||
"type": "string"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactDeals": {
|
||||
"type": "string"
|
||||
},
|
||||
"customerAccount": {
|
||||
"type": "string"
|
||||
},
|
||||
"dealActivities": {
|
||||
"type": "string"
|
||||
},
|
||||
"dealCustomFieldData": {
|
||||
"type": "string"
|
||||
},
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"nextTask": {
|
||||
"type": "string"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"scoreValues": {
|
||||
"type": "string"
|
||||
},
|
||||
"stage": {
|
||||
"type": "string"
|
||||
},
|
||||
"tasks": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"nextdate": {
|
||||
"type": "null"
|
||||
},
|
||||
"nextdealid": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "null"
|
||||
},
|
||||
"status": {
|
||||
"type": "integer"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"winProbability": {
|
||||
"type": "null"
|
||||
},
|
||||
"winProbabilityMdate": {
|
||||
"type": "null"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dealGroups": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"allgroups": {
|
||||
"type": "string"
|
||||
},
|
||||
"allusers": {
|
||||
"type": "string"
|
||||
},
|
||||
"autoassign": {
|
||||
"type": "string"
|
||||
},
|
||||
"cdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"currency": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dealGroupGroups": {
|
||||
"type": "string"
|
||||
},
|
||||
"dealGroupUsers": {
|
||||
"type": "string"
|
||||
},
|
||||
"stages": {
|
||||
"type": "string"
|
||||
},
|
||||
"winProbabilityFeatures": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"udate": {
|
||||
"type": "string"
|
||||
},
|
||||
"win_probability_initialize_date": {
|
||||
"type": "null"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dealStages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cardRegion1": {
|
||||
"type": "string"
|
||||
},
|
||||
"cardRegion2": {
|
||||
"type": "string"
|
||||
},
|
||||
"cardRegion3": {
|
||||
"type": "string"
|
||||
},
|
||||
"cardRegion4": {
|
||||
"type": "string"
|
||||
},
|
||||
"cardRegion5": {
|
||||
"type": "string"
|
||||
},
|
||||
"cdate": {
|
||||
"type": "null"
|
||||
},
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"dealOrder": {
|
||||
"type": "string"
|
||||
},
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"group": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"order": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"width": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"deal": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"activitycount": {
|
||||
"type": "string"
|
||||
},
|
||||
"cdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"currency": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"isDisabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"account": {
|
||||
"type": "string"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactDeals": {
|
||||
"type": "string"
|
||||
},
|
||||
"customerAccount": {
|
||||
"type": "string"
|
||||
},
|
||||
"dealActivities": {
|
||||
"type": "string"
|
||||
},
|
||||
"dealCustomFieldData": {
|
||||
"type": "string"
|
||||
},
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"nextTask": {
|
||||
"type": "string"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"scoreValues": {
|
||||
"type": "string"
|
||||
},
|
||||
"stage": {
|
||||
"type": "string"
|
||||
},
|
||||
"tasks": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"nextdealid": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"percent": {
|
||||
"type": "string"
|
||||
},
|
||||
"stage": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"activitycount": {
|
||||
"type": "string"
|
||||
},
|
||||
"cdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"currency": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"isDisabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"account": {
|
||||
"type": "string"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactDeals": {
|
||||
"type": "string"
|
||||
},
|
||||
"customerAccount": {
|
||||
"type": "string"
|
||||
},
|
||||
"dealActivities": {
|
||||
"type": "string"
|
||||
},
|
||||
"dealCustomFieldData": {
|
||||
"type": "string"
|
||||
},
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"nextTask": {
|
||||
"type": "string"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"scoreValues": {
|
||||
"type": "string"
|
||||
},
|
||||
"stage": {
|
||||
"type": "string"
|
||||
},
|
||||
"tasks": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"nextdealid": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"percent": {
|
||||
"type": "string"
|
||||
},
|
||||
"stage": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"deal": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"activitycount": {
|
||||
"type": "string"
|
||||
},
|
||||
"cdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"currency": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"isDisabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"account": {
|
||||
"type": "string"
|
||||
},
|
||||
"contact": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactDeals": {
|
||||
"type": "string"
|
||||
},
|
||||
"customerAccount": {
|
||||
"type": "string"
|
||||
},
|
||||
"dealActivities": {
|
||||
"type": "string"
|
||||
},
|
||||
"dealCustomFieldData": {
|
||||
"type": "string"
|
||||
},
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"nextTask": {
|
||||
"type": "string"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"scoreValues": {
|
||||
"type": "string"
|
||||
},
|
||||
"stage": {
|
||||
"type": "string"
|
||||
},
|
||||
"tasks": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"nextdealid": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"percent": {
|
||||
"type": "string"
|
||||
},
|
||||
"stage": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dealStages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cardRegion1": {
|
||||
"type": "string"
|
||||
},
|
||||
"cardRegion2": {
|
||||
"type": "string"
|
||||
},
|
||||
"cardRegion3": {
|
||||
"type": "string"
|
||||
},
|
||||
"cardRegion4": {
|
||||
"type": "string"
|
||||
},
|
||||
"cardRegion5": {
|
||||
"type": "string"
|
||||
},
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"dealOrder": {
|
||||
"type": "string"
|
||||
},
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"group": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"order": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"udate": {
|
||||
"type": "string"
|
||||
},
|
||||
"width": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"analytics_domains": {
|
||||
"type": "null"
|
||||
},
|
||||
"analytics_source": {
|
||||
"type": "string"
|
||||
},
|
||||
"analytics_ua": {
|
||||
"type": "string"
|
||||
},
|
||||
"cdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_by": {
|
||||
"type": "null"
|
||||
},
|
||||
"created_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"deletestamp": {
|
||||
"type": "null"
|
||||
},
|
||||
"facebook_session": {
|
||||
"type": "null"
|
||||
},
|
||||
"get_unsubscribe_reason": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"addressLists": {
|
||||
"type": "string"
|
||||
},
|
||||
"contactGoalLists": {
|
||||
"type": "string"
|
||||
},
|
||||
"user": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"optinmessageid": {
|
||||
"type": "string"
|
||||
},
|
||||
"optinoptout": {
|
||||
"type": "string"
|
||||
},
|
||||
"optoutconf": {
|
||||
"type": "string"
|
||||
},
|
||||
"p_embed_image": {
|
||||
"type": "string"
|
||||
},
|
||||
"p_use_analytics_link": {
|
||||
"type": "string"
|
||||
},
|
||||
"p_use_analytics_read": {
|
||||
"type": "string"
|
||||
},
|
||||
"p_use_captcha": {
|
||||
"type": "string"
|
||||
},
|
||||
"p_use_facebook": {
|
||||
"type": "string"
|
||||
},
|
||||
"p_use_tracking": {
|
||||
"type": "string"
|
||||
},
|
||||
"p_use_twitter": {
|
||||
"type": "string"
|
||||
},
|
||||
"private": {
|
||||
"type": "string"
|
||||
},
|
||||
"require_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"send_last_broadcast": {
|
||||
"type": "string"
|
||||
},
|
||||
"sender_addr1": {
|
||||
"type": "string"
|
||||
},
|
||||
"sender_addr2": {
|
||||
"type": "string"
|
||||
},
|
||||
"sender_city": {
|
||||
"type": "string"
|
||||
},
|
||||
"sender_country": {
|
||||
"type": "string"
|
||||
},
|
||||
"sender_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"sender_phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"sender_reminder": {
|
||||
"type": "string"
|
||||
},
|
||||
"sender_state": {
|
||||
"type": "string"
|
||||
},
|
||||
"sender_url": {
|
||||
"type": "string"
|
||||
},
|
||||
"sender_zip": {
|
||||
"type": "string"
|
||||
},
|
||||
"stringid": {
|
||||
"type": "string"
|
||||
},
|
||||
"to_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"twitter_token": {
|
||||
"type": "string"
|
||||
},
|
||||
"twitter_token_secret": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_by": {
|
||||
"type": "null"
|
||||
},
|
||||
"updated_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"user": {
|
||||
"type": "string"
|
||||
},
|
||||
"userid": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"tag": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"deleted": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"contactGoalTags": {
|
||||
"type": "string"
|
||||
},
|
||||
"templateTags": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"subscriber_count": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"type": "string"
|
||||
},
|
||||
"tagType": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_timestamp": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"deleted": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"contactGoalTags": {
|
||||
"type": "string"
|
||||
},
|
||||
"templateTags": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"subscriber_count": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"type": "string"
|
||||
},
|
||||
"tagType": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_timestamp": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.45172 33.7906L28.3389 19.9196L7.45172 5.96777C6.56472 5.40313 6 4.35496 6 3.22569V0L31.3229 16.4516C32.5325 17.258 33.1777 18.5485 33.1777 19.9196C33.1777 21.2903 32.4517 22.5809 31.3229 23.3872L6 40V36.5323C6 35.4839 6.48422 34.4357 7.45172 33.7906Z" fill="white"/>
|
||||
<path d="M19.4679 21.0485C18.3391 21.7741 16.8871 21.7741 15.7583 21.0485L12.8549 19.1936L6 14.5967V11.9354C6 10.8873 7.20961 10.3226 8.01612 10.8873L21.242 19.8388L19.4679 21.0485Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 580 B |
@@ -0,0 +1,4 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.45172 33.7906L28.3389 19.9196L7.45172 5.96777C6.56472 5.40313 6 4.35496 6 3.22569V0L31.3229 16.4516C32.5325 17.258 33.1777 18.5485 33.1777 19.9196C33.1777 21.2903 32.4517 22.5809 31.3229 23.3872L6 40V36.5323C6 35.4839 6.48422 34.4357 7.45172 33.7906Z" fill="#004CFF"/>
|
||||
<path d="M19.4679 21.0485C18.3391 21.7741 16.8871 21.7741 15.7583 21.0485L12.8549 19.1936L6 14.5967V11.9354C6 10.8873 7.20961 10.3226 8.01612 10.8873L21.242 19.8388L19.4679 21.0485Z" fill="#004CFF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 584 B |
@@ -0,0 +1,173 @@
|
||||
export const allCurrencies = [
|
||||
{ name: 'Euro', value: 'eur' },
|
||||
{ name: 'United States Dollar', value: 'usd' },
|
||||
{ name: 'British Pound Sterling', value: 'gbp' },
|
||||
{ name: 'Swiss Franc', value: 'chf' },
|
||||
{ name: 'Renminbi', value: 'cny' },
|
||||
{ name: '--------', value: '' },
|
||||
{ name: 'United Arab Emirates Dirham', value: 'aed' },
|
||||
{ name: 'Afghan Afghani', value: 'afn' },
|
||||
{ name: 'Albanian Lek', value: 'all' },
|
||||
{ name: 'Armenian Dram', value: 'amd' },
|
||||
{ name: 'Netherlands Antillean Guilder', value: 'ang' },
|
||||
{ name: 'Angolan Kwanza', value: 'aoa' },
|
||||
{ name: 'Argentine Peso', value: 'ars' },
|
||||
{ name: 'Australian Dollar', value: 'aud' },
|
||||
{ name: 'Aruban Florin', value: 'awg' },
|
||||
{ name: 'Azerbaijani Manat', value: 'azn' },
|
||||
{ name: 'Bosnia-Herzegovina Convertible Mark', value: 'bam' },
|
||||
{ name: 'Barbadian Dollar', value: 'bbd' },
|
||||
{ name: 'Bangladeshi Taka', value: 'bdt' },
|
||||
{ name: 'Bulgarian Lev', value: 'bgn' },
|
||||
{ name: 'Bahraini Dinar', value: 'bhd' },
|
||||
{ name: 'Burundian Franc', value: 'bif' },
|
||||
{ name: 'Bermudan Dollar', value: 'bmd' },
|
||||
{ name: 'Brunei Dollar', value: 'bnd' },
|
||||
{ name: 'Bolivian Boliviano', value: 'bob' },
|
||||
{ name: 'Brazilian Real', value: 'brl' },
|
||||
{ name: 'Bahamian Dollar', value: 'bsd' },
|
||||
{ name: 'Bitcoin', value: 'btc' },
|
||||
{ name: 'Bhutanese Ngultrum', value: 'btn' },
|
||||
{ name: 'Botswanan Pula', value: 'bwp' },
|
||||
{ name: 'Belarusian Ruble', value: 'byn' },
|
||||
{ name: 'Belize Dollar', value: 'bzd' },
|
||||
{ name: 'Canadian Dollar', value: 'cad' },
|
||||
{ name: 'Congolese Franc', value: 'cdf' },
|
||||
{ name: 'Chilean Unit of Account (UF)', value: 'clf' },
|
||||
{ name: 'Chilean Peso', value: 'clp' },
|
||||
{ name: 'Chinese Yuan (Offshore)', value: 'cnh' },
|
||||
{ name: 'Colombian Peso', value: 'cop' },
|
||||
{ name: 'Costa Rican Colón', value: 'crc' },
|
||||
{ name: 'Cuban Convertible Peso', value: 'cuc' },
|
||||
{ name: 'Cuban Peso', value: 'cup' },
|
||||
{ name: 'Cape Verdean Escudo', value: 'cve' },
|
||||
{ name: 'Czech Republic Koruna', value: 'czk' },
|
||||
{ name: 'Djiboutian Franc', value: 'djf' },
|
||||
{ name: 'Danish Krone', value: 'dkk' },
|
||||
{ name: 'Dominican Peso', value: 'dop' },
|
||||
{ name: 'Algerian Dinar', value: 'dzd' },
|
||||
{ name: 'Egyptian Pound', value: 'egp' },
|
||||
{ name: 'Eritrean Nakfa', value: 'ern' },
|
||||
{ name: 'Ethiopian Birr', value: 'etb' },
|
||||
{ name: 'Fijian Dollar', value: 'fjd' },
|
||||
{ name: 'Falkland Islands Pound', value: 'fkp' },
|
||||
{ name: 'Georgian Lari', value: 'gel' },
|
||||
{ name: 'Guernsey Pound', value: 'ggp' },
|
||||
{ name: 'Ghanaian Cedi', value: 'ghs' },
|
||||
{ name: 'Gibraltar Pound', value: 'gip' },
|
||||
{ name: 'Gambian Dalasi', value: 'gmd' },
|
||||
{ name: 'Guinean Franc', value: 'gnf' },
|
||||
{ name: 'Guatemalan Quetzal', value: 'gtq' },
|
||||
{ name: 'Guyanaese Dollar', value: 'gyd' },
|
||||
{ name: 'Hong Kong Dollar', value: 'hkd' },
|
||||
{ name: 'Honduran Lempira', value: 'hnl' },
|
||||
{ name: 'Croatian Kuna', value: 'hrk' },
|
||||
{ name: 'Haitian Gourde', value: 'htg' },
|
||||
{ name: 'Hungarian Forint', value: 'huf' },
|
||||
{ name: 'Indonesian Rupiah', value: 'idr' },
|
||||
{ name: 'Israeli New Sheqel', value: 'ils' },
|
||||
{ name: 'Manx Pound', value: 'imp' },
|
||||
{ name: 'Indian Rupee', value: 'inr' },
|
||||
{ name: 'Iraqi Dinar', value: 'iqd' },
|
||||
{ name: 'Iranian Rial', value: 'irr' },
|
||||
{ name: 'Icelandic Króna', value: 'isk' },
|
||||
{ name: 'Jersey Pound', value: 'jep' },
|
||||
{ name: 'Jamaican Dollar', value: 'jmd' },
|
||||
{ name: 'Jordanian Dinar', value: 'jod' },
|
||||
{ name: 'Japanese Yen', value: 'jpy' },
|
||||
{ name: 'Kenyan Shilling', value: 'kes' },
|
||||
{ name: 'Kyrgystani Som', value: 'kgs' },
|
||||
{ name: 'Cambodian Riel', value: 'khr' },
|
||||
{ name: 'Comorian Franc', value: 'kmf' },
|
||||
{ name: 'North Korean Won', value: 'kpw' },
|
||||
{ name: 'South Korean Won', value: 'krw' },
|
||||
{ name: 'Kuwaiti Dinar', value: 'kwd' },
|
||||
{ name: 'Cayman Islands Dollar', value: 'kyd' },
|
||||
{ name: 'Kazakhstani Tenge', value: 'kzt' },
|
||||
{ name: 'Laotian Kip', value: 'lak' },
|
||||
{ name: 'Lebanese Pound', value: 'lbp' },
|
||||
{ name: 'Sri Lankan Rupee', value: 'lkr' },
|
||||
{ name: 'Liberian Dollar', value: 'lrd' },
|
||||
{ name: 'Lesotho Loti', value: 'lsl' },
|
||||
{ name: 'Libyan Dinar', value: 'lyd' },
|
||||
{ name: 'Moroccan Dirham', value: 'mad' },
|
||||
{ name: 'Moldovan Leu', value: 'mdl' },
|
||||
{ name: 'Malagasy Ariary', value: 'mga' },
|
||||
{ name: 'Macedonian Denar', value: 'mkd' },
|
||||
{ name: 'Myanma Kyat', value: 'mmk' },
|
||||
{ name: 'Mongolian Tugrik', value: 'mnt' },
|
||||
{ name: 'Macanese Pataca', value: 'mop' },
|
||||
{ name: 'Mauritanian Ouguiya (Pre-2018)', value: 'mro' },
|
||||
{ name: 'Mauritanian Ouguiya', value: 'mru' },
|
||||
{ name: 'Mauritian Rupee', value: 'mur' },
|
||||
{ name: 'Maldivian Rufiyaa', value: 'mvr' },
|
||||
{ name: 'Malawian Kwacha', value: 'mwk' },
|
||||
{ name: 'Mexican Peso', value: 'mxn' },
|
||||
{ name: 'Malaysian Ringgit', value: 'myr' },
|
||||
{ name: 'Mozambican Metical', value: 'mzn' },
|
||||
{ name: 'Namibian Dollar', value: 'nad' },
|
||||
{ name: 'Nigerian Naira', value: 'ngn' },
|
||||
{ name: 'Nicaraguan Córdoba', value: 'nio' },
|
||||
{ name: 'Norwegian Krone', value: 'nok' },
|
||||
{ name: 'Nepalese Rupee', value: 'npr' },
|
||||
{ name: 'New Zealand Dollar', value: 'nzd' },
|
||||
{ name: 'Omani Rial', value: 'omr' },
|
||||
{ name: 'Panamanian Balboa', value: 'pab' },
|
||||
{ name: 'Peruvian Nuevo Sol', value: 'pen' },
|
||||
{ name: 'Papua New Guinean Kina', value: 'pgk' },
|
||||
{ name: 'Philippine Peso', value: 'php' },
|
||||
{ name: 'Pakistani Rupee', value: 'pkr' },
|
||||
{ name: 'Polish Zloty', value: 'pln' },
|
||||
{ name: 'Paraguayan Guarani', value: 'pyg' },
|
||||
{ name: 'Qatari Rial', value: 'qar' },
|
||||
{ name: 'Romanian Leu', value: 'ron' },
|
||||
{ name: 'Serbian Dinar', value: 'rsd' },
|
||||
{ name: 'Russian Ruble', value: 'rub' },
|
||||
{ name: 'Rwandan Franc', value: 'rwf' },
|
||||
{ name: 'Saudi Riyal', value: 'sar' },
|
||||
{ name: 'Solomon Islands Dollar', value: 'sbd' },
|
||||
{ name: 'Seychellois Rupee', value: 'scr' },
|
||||
{ name: 'Sudanese Pound', value: 'sdg' },
|
||||
{ name: 'Swedish Krona', value: 'sek' },
|
||||
{ name: 'Singapore Dollar', value: 'sgd' },
|
||||
{ name: 'Saint Helena Pound', value: 'shp' },
|
||||
{ name: 'Sierra Leonean Leone', value: 'sll' },
|
||||
{ name: 'Somali Shilling', value: 'sos' },
|
||||
{ name: 'Surinamese Dollar', value: 'srd' },
|
||||
{ name: 'South Sudanese Pound', value: 'ssp' },
|
||||
{ name: 'São Tomé and Príncipe Dobra (Pre-2018)', value: 'std' },
|
||||
{ name: 'São Tomé and Príncipe Dobra', value: 'stn' },
|
||||
{ name: 'Salvadoran Colón', value: 'svc' },
|
||||
{ name: 'Syrian Pound', value: 'syp' },
|
||||
{ name: 'Swazi Lilangeni', value: 'szl' },
|
||||
{ name: 'Thai Baht', value: 'thb' },
|
||||
{ name: 'Tajikistani Somoni', value: 'tjs' },
|
||||
{ name: 'Turkmenistani Manat', value: 'tmt' },
|
||||
{ name: 'Tunisian Dinar', value: 'tnd' },
|
||||
{ name: "Tongan Pa'anga", value: 'top' },
|
||||
{ name: 'Turkish Lira', value: 'try' },
|
||||
{ name: 'Trinidad and Tobago Dollar', value: 'ttd' },
|
||||
{ name: 'New Taiwan Dollar', value: 'twd' },
|
||||
{ name: 'Tanzanian Shilling', value: 'tzs' },
|
||||
{ name: 'Ukrainian Hryvnia', value: 'uah' },
|
||||
{ name: 'Ugandan Shilling', value: 'ugx' },
|
||||
{ name: 'Uruguayan Peso', value: 'uyu' },
|
||||
{ name: 'Uzbekistan Som', value: 'uzs' },
|
||||
{ name: 'Venezuelan Bolívar Fuerte', value: 'vef' },
|
||||
{ name: 'Vietnamese Dong', value: 'vnd' },
|
||||
{ name: 'Vanuatu Vatu', value: 'vuv' },
|
||||
{ name: 'Samoan Tala', value: 'wst' },
|
||||
{ name: 'CFA Franc BEAC', value: 'xaf' },
|
||||
{ name: 'Silver Ounce', value: 'xag' },
|
||||
{ name: 'Gold Ounce', value: 'xau' },
|
||||
{ name: 'East Caribbean Dollar', value: 'xcd' },
|
||||
{ name: 'Special Drawing Rights', value: 'xdr' },
|
||||
{ name: 'CFA Franc BCEAO', value: 'xof' },
|
||||
{ name: 'Palladium Ounce', value: 'xpd' },
|
||||
{ name: 'CFP Franc', value: 'xpf' },
|
||||
{ name: 'Platinum Ounce', value: 'xpt' },
|
||||
{ name: 'Yemeni Rial', value: 'yer' },
|
||||
{ name: 'South African Rand', value: 'zar' },
|
||||
{ name: 'Zambian Kwacha', value: 'zmw' },
|
||||
{ name: 'Zimbabwean Dollar', value: 'zwl' },
|
||||
];
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.acuitySchedulingTrigger",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Productivity"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/acuityscheduling/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.acuityschedulingtrigger/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
import type {
|
||||
IHookFunctions,
|
||||
IWebhookFunctions,
|
||||
IDataObject,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
IWebhookResponseData,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionTypes } from 'n8n-workflow';
|
||||
|
||||
import { acuitySchedulingApiRequest } from './GenericFunctions';
|
||||
|
||||
export class AcuitySchedulingTrigger implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Acuity Scheduling Trigger',
|
||||
name: 'acuitySchedulingTrigger',
|
||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-icon-not-svg
|
||||
icon: 'file:acuityScheduling.png',
|
||||
group: ['trigger'],
|
||||
version: 1,
|
||||
description: 'Handle Acuity Scheduling events via webhooks',
|
||||
defaults: {
|
||||
name: 'Acuity Scheduling Trigger',
|
||||
},
|
||||
inputs: [],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'acuitySchedulingApi',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authentication: ['apiKey'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'acuitySchedulingOAuth2Api',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authentication: ['oAuth2'],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
webhooks: [
|
||||
{
|
||||
name: 'default',
|
||||
httpMethod: 'POST',
|
||||
responseMode: 'onReceived',
|
||||
path: 'webhook',
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Authentication',
|
||||
name: 'authentication',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'API Key',
|
||||
value: 'apiKey',
|
||||
},
|
||||
{
|
||||
name: 'OAuth2',
|
||||
value: 'oAuth2',
|
||||
},
|
||||
],
|
||||
default: 'apiKey',
|
||||
},
|
||||
{
|
||||
displayName: 'Event',
|
||||
name: 'event',
|
||||
type: 'options',
|
||||
required: true,
|
||||
default: '',
|
||||
options: [
|
||||
{
|
||||
name: 'appointment.canceled',
|
||||
value: 'appointment.canceled',
|
||||
description: 'Is called whenever an appointment is canceled',
|
||||
},
|
||||
{
|
||||
name: 'appointment.changed',
|
||||
value: 'appointment.changed',
|
||||
description: 'Is called when the appointment is changed in any way',
|
||||
},
|
||||
{
|
||||
name: 'appointment.rescheduled',
|
||||
value: 'appointment.rescheduled',
|
||||
description: 'Is called when the appointment is rescheduled to a new time',
|
||||
},
|
||||
{
|
||||
name: 'appointment.scheduled',
|
||||
value: 'appointment.scheduled',
|
||||
description: 'Is called once when an appointment is initially booked',
|
||||
},
|
||||
{
|
||||
name: 'order.completed',
|
||||
value: 'order.completed',
|
||||
description: 'Is called when an order is completed',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Resolve Data',
|
||||
name: 'resolveData',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
// eslint-disable-next-line n8n-nodes-base/node-param-description-boolean-without-whether
|
||||
description:
|
||||
'By default does the webhook-data only contain the ID of the object. If this option gets activated, it will resolve the data automatically.',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
webhookMethods = {
|
||||
default: {
|
||||
async checkExists(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
if (webhookData.webhookId === undefined) {
|
||||
return false;
|
||||
}
|
||||
const endpoint = '/webhooks';
|
||||
const webhooks = await acuitySchedulingApiRequest.call(this, 'GET', endpoint);
|
||||
if (Array.isArray(webhooks)) {
|
||||
for (const webhook of webhooks) {
|
||||
if (webhook.id === webhookData.webhookId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
async create(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookUrl = this.getNodeWebhookUrl('default');
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
const event = this.getNodeParameter('event') as string;
|
||||
const endpoint = '/webhooks';
|
||||
const body: IDataObject = {
|
||||
target: webhookUrl,
|
||||
event,
|
||||
};
|
||||
const { id } = await acuitySchedulingApiRequest.call(this, 'POST', endpoint, body);
|
||||
webhookData.webhookId = id;
|
||||
return true;
|
||||
},
|
||||
async delete(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
const endpoint = `/webhooks/${webhookData.webhookId}`;
|
||||
try {
|
||||
await acuitySchedulingApiRequest.call(this, 'DELETE', endpoint);
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
delete webhookData.webhookId;
|
||||
return true;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
|
||||
const req = this.getRequestObject();
|
||||
|
||||
const resolveData = this.getNodeParameter('resolveData', false) as boolean;
|
||||
|
||||
if (!resolveData) {
|
||||
// Return the data as it got received
|
||||
return {
|
||||
workflowData: [this.helpers.returnJsonArray(req.body as IDataObject[])],
|
||||
};
|
||||
}
|
||||
|
||||
// Resolve the data by requesting the information via API
|
||||
const event = this.getNodeParameter('event', false) as string;
|
||||
const eventType = event.split('.').shift();
|
||||
const endpoint = `/${eventType}s/${req.body.id}`;
|
||||
const responseData = await acuitySchedulingApiRequest.call(this, 'GET', endpoint, {});
|
||||
|
||||
return {
|
||||
workflowData: [this.helpers.returnJsonArray(responseData as IDataObject)],
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import type {
|
||||
IDataObject,
|
||||
IExecuteFunctions,
|
||||
IHookFunctions,
|
||||
IHttpRequestMethods,
|
||||
ILoadOptionsFunctions,
|
||||
IRequestOptions,
|
||||
IWebhookFunctions,
|
||||
JsonObject,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeApiError } from 'n8n-workflow';
|
||||
|
||||
export async function acuitySchedulingApiRequest(
|
||||
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
resource: string,
|
||||
body: any = {},
|
||||
qs: IDataObject = {},
|
||||
uri?: string,
|
||||
_option: IDataObject = {},
|
||||
): Promise<any> {
|
||||
const authenticationMethod = this.getNodeParameter('authentication', 0);
|
||||
|
||||
const options: IRequestOptions = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
auth: {},
|
||||
method,
|
||||
qs,
|
||||
body,
|
||||
uri: uri || `https://acuityscheduling.com/api/v1${resource}`,
|
||||
json: true,
|
||||
};
|
||||
|
||||
try {
|
||||
if (authenticationMethod === 'apiKey') {
|
||||
const credentials = await this.getCredentials('acuitySchedulingApi');
|
||||
|
||||
options.auth = {
|
||||
user: credentials.userId as string,
|
||||
password: credentials.apiKey as string,
|
||||
};
|
||||
|
||||
return await this.helpers.request(options);
|
||||
} else {
|
||||
delete options.auth;
|
||||
return await this.helpers.requestOAuth2.call(
|
||||
this,
|
||||
'acuitySchedulingOAuth2Api',
|
||||
options,
|
||||
//@ts-ignore
|
||||
true,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 132 KiB |
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.adalo",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Data & Storage"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/adalo/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.adalo/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
import {
|
||||
NodeConnectionTypes,
|
||||
type IDataObject,
|
||||
type IExecuteSingleFunctions,
|
||||
type IHttpRequestOptions,
|
||||
type INodeType,
|
||||
type INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { collectionFields } from './CollectionDescription';
|
||||
import type { FieldsUiValues } from './types';
|
||||
|
||||
export class Adalo implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Adalo',
|
||||
name: 'adalo',
|
||||
icon: 'file:adalo.svg',
|
||||
group: ['transform'],
|
||||
version: 1,
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["collectionId"]}}',
|
||||
description: 'Consume Adalo API',
|
||||
defaults: {
|
||||
name: 'Adalo',
|
||||
},
|
||||
usableAsTool: true,
|
||||
inputs: [NodeConnectionTypes.Main],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'adaloApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
requestDefaults: {
|
||||
baseURL: '=https://api.adalo.com/v0/apps/{{$credentials.appId}}',
|
||||
},
|
||||
requestOperations: {
|
||||
pagination: {
|
||||
type: 'offset',
|
||||
properties: {
|
||||
limitParameter: 'limit',
|
||||
offsetParameter: 'offset',
|
||||
pageSize: 100,
|
||||
type: 'query',
|
||||
},
|
||||
},
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
default: 'collection',
|
||||
options: [
|
||||
{
|
||||
name: 'Collection',
|
||||
value: 'collection',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a row',
|
||||
routing: {
|
||||
send: {
|
||||
preSend: [this.presendCreateUpdate],
|
||||
},
|
||||
request: {
|
||||
method: 'POST',
|
||||
url: '=/collections/{{$parameter["collectionId"]}}',
|
||||
},
|
||||
},
|
||||
action: 'Create a row',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete a row',
|
||||
routing: {
|
||||
request: {
|
||||
method: 'DELETE',
|
||||
url: '=/collections/{{$parameter["collectionId"]}}/{{$parameter["rowId"]}}',
|
||||
},
|
||||
output: {
|
||||
postReceive: [
|
||||
{
|
||||
type: 'set',
|
||||
properties: {
|
||||
value: '={{ { "success": true } }}',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
action: 'Delete a row',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Retrieve a row',
|
||||
routing: {
|
||||
request: {
|
||||
method: 'GET',
|
||||
url: '=/collections/{{$parameter["collectionId"]}}/{{$parameter["rowId"]}}',
|
||||
},
|
||||
},
|
||||
action: 'Retrieve a row',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Retrieve many rows',
|
||||
routing: {
|
||||
request: {
|
||||
method: 'GET',
|
||||
url: '=/collections/{{$parameter["collectionId"]}}',
|
||||
qs: {
|
||||
limit: '={{$parameter["limit"]}}',
|
||||
},
|
||||
},
|
||||
send: {
|
||||
paginate: '={{$parameter["returnAll"]}}',
|
||||
},
|
||||
output: {
|
||||
postReceive: [
|
||||
{
|
||||
type: 'rootProperty',
|
||||
properties: {
|
||||
property: 'records',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
action: 'Retrieve all rows',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update a row',
|
||||
routing: {
|
||||
send: {
|
||||
preSend: [this.presendCreateUpdate],
|
||||
},
|
||||
request: {
|
||||
method: 'PUT',
|
||||
url: '=/collections/{{$parameter["collectionId"]}}/{{$parameter["rowId"]}}',
|
||||
},
|
||||
},
|
||||
action: 'Update a row',
|
||||
},
|
||||
],
|
||||
default: 'getAll',
|
||||
},
|
||||
{
|
||||
displayName: 'Collection ID',
|
||||
name: 'collectionId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
description:
|
||||
'Open your Adalo application and click on the three buttons beside the collection name, then select API Documentation',
|
||||
hint: "You can find information about app's collections on https://app.adalo.com/apps/<strong>your-app-id</strong>/api-docs",
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['collection'],
|
||||
},
|
||||
},
|
||||
},
|
||||
...collectionFields,
|
||||
],
|
||||
};
|
||||
|
||||
async presendCreateUpdate(
|
||||
this: IExecuteSingleFunctions,
|
||||
requestOptions: IHttpRequestOptions,
|
||||
): Promise<IHttpRequestOptions> {
|
||||
const dataToSend = this.getNodeParameter('dataToSend', 0) as 'defineBelow' | 'autoMapInputData';
|
||||
|
||||
requestOptions.body = {};
|
||||
|
||||
if (dataToSend === 'autoMapInputData') {
|
||||
const inputData = this.getInputData();
|
||||
const rawInputsToIgnore = this.getNodeParameter('inputsToIgnore') as string;
|
||||
|
||||
const inputKeysToIgnore = rawInputsToIgnore.split(',').map((c) => c.trim());
|
||||
const inputKeys = Object.keys(inputData.json).filter(
|
||||
(key) => !inputKeysToIgnore.includes(key),
|
||||
);
|
||||
|
||||
for (const key of inputKeys) {
|
||||
(requestOptions.body as IDataObject)[key] = inputData.json[key];
|
||||
}
|
||||
} else {
|
||||
const fields = this.getNodeParameter('fieldsUi.fieldValues') as FieldsUiValues;
|
||||
|
||||
for (const field of fields) {
|
||||
(requestOptions.body as IDataObject)[field.fieldId] = field.fieldValue;
|
||||
}
|
||||
}
|
||||
|
||||
return requestOptions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const collectionFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Row ID',
|
||||
name: 'rowId',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['get', 'delete', 'update'],
|
||||
resource: ['collection'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
},
|
||||
|
||||
/**
|
||||
* create / update
|
||||
*/
|
||||
|
||||
{
|
||||
displayName: 'Data to Send',
|
||||
name: 'dataToSend',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Auto-Map Input Data to Columns',
|
||||
value: 'autoMapInputData',
|
||||
description: 'Use when node input properties match destination column names',
|
||||
},
|
||||
{
|
||||
name: 'Define Below for Each Column',
|
||||
value: 'defineBelow',
|
||||
description: 'Set the value for each destination column',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create', 'update'],
|
||||
resource: ['collection'],
|
||||
},
|
||||
},
|
||||
default: 'defineBelow',
|
||||
description: 'Whether to insert the input data this node receives in the new row',
|
||||
},
|
||||
{
|
||||
displayName: 'Inputs to Ignore',
|
||||
name: 'inputsToIgnore',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create', 'update'],
|
||||
dataToSend: ['autoMapInputData'],
|
||||
resource: ['collection'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'List of input properties to avoid sending, separated by commas. Leave empty to send all properties.',
|
||||
placeholder: 'Enter properties...',
|
||||
},
|
||||
{
|
||||
displayName: 'Fields to Send',
|
||||
name: 'fieldsUi',
|
||||
placeholder: 'Add Field',
|
||||
type: 'fixedCollection',
|
||||
description:
|
||||
'Field must be defined in the collection, otherwise it will be ignored. If field defined in the collection is not set here, it will be set to null.',
|
||||
typeOptions: {
|
||||
multipleValueButtonText: 'Add Field to Send',
|
||||
multipleValues: true,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create', 'update'],
|
||||
dataToSend: ['defineBelow'],
|
||||
resource: ['collection'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Field',
|
||||
name: 'fieldValues',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Field ID',
|
||||
name: 'fieldId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Field Value',
|
||||
name: 'fieldValue',
|
||||
type: 'string',
|
||||
default: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/**
|
||||
* getAll
|
||||
*/
|
||||
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['getAll'],
|
||||
resource: ['collection'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
default: 100,
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 100,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['getAll'],
|
||||
resource: ['collection'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"deleted_TS": {
|
||||
"type": "null"
|
||||
},
|
||||
"dropbox_thumbnailURL": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="438" height="438" style="shape-rendering:geometricPrecision;text-rendering:geometricPrecision;image-rendering:optimizeQuality;fill-rule:evenodd;clip-rule:evenodd"><path fill="#09a595" d="M199.5-.5h19v22Q92.504 27.319 38 140.5q-35.76 91.255 11.5 177a145.6 145.6 0 0 0-20 11q-25.522-42.567-30-92v-36Q13.954 78.293 122.5 21q36.926-17.101 77-21.5" style="opacity:.999"/><path fill="#ea4c2e" d="M218.5-.5h18q130.095 15.852 184.5 135 14.124 35.394 16.5 73v21q-2.68 52.038-29 97a198 198 0 0 1-20-12q37.113-71.613 17.5-150Q372.673 61.674 270.5 29q-25.88-6.236-52-7.5z" style="opacity:.999"/><path fill="#fefefe" d="M218.5 21.5q26.12 1.264 52 7.5Q372.673 61.674 406 163.5q19.613 78.387-17.5 150-59.03 96.298-173 99-107.855-4.904-166-95-47.26-85.745-11.5-177 54.503-113.181 180.5-119" style="opacity:1"/><path fill="#343434" d="M321.5 72.5q2.588.514 1.5 3A547 547 0 0 0 312.5 95a602 602 0 0 0 11 20.5q-1.834 1.671-4 .5a233 233 0 0 0-18-9.5 725 725 0 0 0-19 9.5q-1.702 1.124-3-.5a578 578 0 0 0 10-20.5 577 577 0 0 0-10-20.5q1.298-1.625 3-.5a161 161 0 0 0 18.5 9.5q10.916-4.578 20.5-11" style="opacity:1"/><path fill="#3b3b3b" d="M226.5 80.5q4.338 3.346 7 8.5 6.556.258 13 1.5l-9 6-2 13a154 154 0 0 0-7-9.5l-12-1a86 86 0 0 1 9-6.5 36.9 36.9 0 0 0 1-12" style="opacity:1"/><path fill="#323232" d="M215.5 188.5a577 577 0 0 1-16.5-28 32.5 32.5 0 0 1-.5-8q5.79-16.4 23-12.5a32 32 0 0 1 7.5 5.5l103 170q2.281 23.718-21.5 21.5-5.103-2.1-8.5-6.5a20572 20572 0 0 0-86.5-142" style="opacity:1"/><path fill="#373737" d="M295.5 149.5q4.662 4.243 8 10 6.947 1.242 14 1.5a184 184 0 0 0-10.5 7.5 86.6 86.6 0 0 1-1.5 13l-7-10a86.6 86.6 0 0 0-13-1.5 86 86 0 0 1 9-6.5 49.9 49.9 0 0 0 1-14" style="opacity:1"/><path fill="#bbb" d="M198.5 152.5a32.5 32.5 0 0 0 .5 8 577 577 0 0 0 16.5 28 22390 22390 0 0 0-86.5 142q-10.027 11.031-23.5 4.5-9.877-8.036-6.5-20.5a19243 19243 0 0 1 99.5-162" style="opacity:1"/><path fill="#333" d="M210.5 257.5q24.901-2.333 29 22-3.077 26.814-30 22.5-19.836-9.978-13.5-31.5 5.677-8.437 14.5-13" style="opacity:1"/><path fill="#f5b915" d="M388.5 313.5a198 198 0 0 0 20 12q-35.346 63.587-102 93.5-39.96 17.038-83 18.5h-11q-110.685-6.214-175.5-96a63.5 63.5 0 0 1-7.5-13 145.6 145.6 0 0 1 20-11q58.145 90.096 166 95 113.97-2.702 173-99" style="opacity:.999"/></svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,11 @@
|
||||
export type AdaloCredentials = {
|
||||
apiKey: string;
|
||||
appId: string;
|
||||
};
|
||||
|
||||
export type FieldsUiValues = Array<{
|
||||
fieldId: string;
|
||||
fieldValue: string;
|
||||
}>;
|
||||
|
||||
export type Operation = 'create' | 'delete' | 'update' | 'get' | 'getAll';
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.affinity",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Sales"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/affinity/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.affinity/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,432 @@
|
||||
import type {
|
||||
IExecuteFunctions,
|
||||
IDataObject,
|
||||
ILoadOptionsFunctions,
|
||||
INodeExecutionData,
|
||||
INodePropertyOptions,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionTypes } from 'n8n-workflow';
|
||||
|
||||
import { affinityApiRequest, affinityApiRequestAllItems } from './GenericFunctions';
|
||||
import { listFields, listOperations } from './ListDescription';
|
||||
import { listEntryFields, listEntryOperations } from './ListEntryDescription';
|
||||
import { organizationFields, organizationOperations } from './OrganizationDescription';
|
||||
import type { IOrganization } from './OrganizationInterface';
|
||||
import { personFields, personOperations } from './PersonDescription';
|
||||
import type { IPerson } from './PersonInterface';
|
||||
|
||||
export class Affinity implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Affinity',
|
||||
name: 'affinity',
|
||||
icon: { light: 'file:affinity.svg', dark: 'file:affinity.dark.svg' },
|
||||
group: ['output'],
|
||||
version: 1,
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
description: 'Consume Affinity API',
|
||||
defaults: {
|
||||
name: 'Affinity',
|
||||
},
|
||||
usableAsTool: true,
|
||||
inputs: [NodeConnectionTypes.Main],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'affinityApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
options: [
|
||||
{
|
||||
name: 'List',
|
||||
value: 'list',
|
||||
},
|
||||
{
|
||||
name: 'List Entry',
|
||||
value: 'listEntry',
|
||||
},
|
||||
{
|
||||
name: 'Organization',
|
||||
value: 'organization',
|
||||
},
|
||||
{
|
||||
name: 'Person',
|
||||
value: 'person',
|
||||
},
|
||||
],
|
||||
default: 'organization',
|
||||
},
|
||||
...listOperations,
|
||||
...listFields,
|
||||
...listEntryOperations,
|
||||
...listEntryFields,
|
||||
...organizationOperations,
|
||||
...organizationFields,
|
||||
...personOperations,
|
||||
...personFields,
|
||||
],
|
||||
};
|
||||
|
||||
methods = {
|
||||
loadOptions: {
|
||||
// Get all the available organizations to display them to user so that they can
|
||||
// select them easily
|
||||
async getOrganizations(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const organizations = await affinityApiRequestAllItems.call(
|
||||
this,
|
||||
'organizations',
|
||||
'GET',
|
||||
'/organizations',
|
||||
{},
|
||||
);
|
||||
for (const organization of organizations) {
|
||||
const organizationName = organization.name;
|
||||
const organizationId = organization.id;
|
||||
returnData.push({
|
||||
name: organizationName,
|
||||
value: organizationId,
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
// Get all the available persons to display them to user so that they can
|
||||
// select them easily
|
||||
async getPersons(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const persons = await affinityApiRequestAllItems.call(
|
||||
this,
|
||||
'persons',
|
||||
'GET',
|
||||
'/persons',
|
||||
{},
|
||||
);
|
||||
for (const person of persons) {
|
||||
let personName = `${person.first_name} ${person.last_name}`;
|
||||
if (person.primary_email !== null) {
|
||||
personName += ` (${person.primary_email})`;
|
||||
}
|
||||
const personId = person.id;
|
||||
returnData.push({
|
||||
name: personName,
|
||||
value: personId,
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
// Get all the available lists to display them to user so that they can
|
||||
// select them easily
|
||||
async getLists(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const lists = await affinityApiRequest.call(this, 'GET', '/lists');
|
||||
for (const list of lists) {
|
||||
returnData.push({
|
||||
name: list.name,
|
||||
value: list.id,
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
const length = items.length;
|
||||
let responseData;
|
||||
const qs: IDataObject = {};
|
||||
const resource = this.getNodeParameter('resource', 0);
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
for (let i = 0; i < length; i++) {
|
||||
try {
|
||||
if (resource === 'list') {
|
||||
//https://api-docs.affinity.co/#get-a-specific-list
|
||||
if (operation === 'get') {
|
||||
const listId = this.getNodeParameter('listId', i) as string;
|
||||
responseData = await affinityApiRequest.call(this, 'GET', `/lists/${listId}`, {}, qs);
|
||||
}
|
||||
//https://api-docs.affinity.co/#get-all-lists
|
||||
if (operation === 'getAll') {
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
responseData = await affinityApiRequest.call(this, 'GET', '/lists', {}, qs);
|
||||
if (!returnAll) {
|
||||
const limit = this.getNodeParameter('limit', i);
|
||||
responseData = responseData.splice(0, limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (resource === 'listEntry') {
|
||||
//https://api-docs.affinity.co/#create-a-new-list-entry
|
||||
if (operation === 'create') {
|
||||
const listId = this.getNodeParameter('listId', i) as string;
|
||||
const entityId = this.getNodeParameter('entityId', i) as string;
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
const body: IDataObject = {
|
||||
entity_id: parseInt(entityId, 10),
|
||||
};
|
||||
Object.assign(body, additionalFields);
|
||||
responseData = await affinityApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
`/lists/${listId}/list-entries`,
|
||||
body,
|
||||
);
|
||||
}
|
||||
//https://api-docs.affinity.co/#get-a-specific-list-entry
|
||||
if (operation === 'get') {
|
||||
const listId = this.getNodeParameter('listId', i) as string;
|
||||
const listEntryId = this.getNodeParameter('listEntryId', i) as string;
|
||||
responseData = await affinityApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/lists/${listId}/list-entries/${listEntryId}`,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
}
|
||||
//https://api-docs.affinity.co/#get-all-list-entries
|
||||
if (operation === 'getAll') {
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
const listId = this.getNodeParameter('listId', i) as string;
|
||||
if (returnAll) {
|
||||
responseData = await affinityApiRequestAllItems.call(
|
||||
this,
|
||||
'list_entries',
|
||||
'GET',
|
||||
`/lists/${listId}/list-entries`,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
} else {
|
||||
qs.page_size = this.getNodeParameter('limit', i);
|
||||
responseData = await affinityApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/lists/${listId}/list-entries`,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
responseData = responseData.list_entries;
|
||||
}
|
||||
}
|
||||
//https://api-docs.affinity.co/#delete-a-specific-list-entry
|
||||
if (operation === 'delete') {
|
||||
const listId = this.getNodeParameter('listId', i) as string;
|
||||
const listEntryId = this.getNodeParameter('listEntryId', i) as string;
|
||||
responseData = await affinityApiRequest.call(
|
||||
this,
|
||||
'DELETE',
|
||||
`/lists/${listId}/list-entries/${listEntryId}`,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (resource === 'person') {
|
||||
//https://api-docs.affinity.co/#create-a-new-person
|
||||
if (operation === 'create') {
|
||||
const firstName = this.getNodeParameter('firstName', i) as string;
|
||||
const lastName = this.getNodeParameter('lastName', i) as string;
|
||||
const emails = this.getNodeParameter('emails', i) as string[];
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
const body: IPerson = {
|
||||
first_name: firstName,
|
||||
last_name: lastName,
|
||||
emails,
|
||||
};
|
||||
if (additionalFields.organizations) {
|
||||
body.organization_ids = additionalFields.organizations as number[];
|
||||
}
|
||||
responseData = await affinityApiRequest.call(this, 'POST', '/persons', body);
|
||||
}
|
||||
//https://api-docs.affinity.co/#update-a-person
|
||||
if (operation === 'update') {
|
||||
const personId = this.getNodeParameter('personId', i) as number;
|
||||
const updateFields = this.getNodeParameter('updateFields', i);
|
||||
const emails = this.getNodeParameter('emails', i) as string[];
|
||||
const body: IPerson = {
|
||||
emails,
|
||||
};
|
||||
if (updateFields.firstName) {
|
||||
body.first_name = updateFields.firstName as string;
|
||||
}
|
||||
if (updateFields.lastName) {
|
||||
body.last_name = updateFields.lastName as string;
|
||||
}
|
||||
if (updateFields.organizations) {
|
||||
body.organization_ids = updateFields.organizations as number[];
|
||||
}
|
||||
responseData = await affinityApiRequest.call(this, 'PUT', `/persons/${personId}`, body);
|
||||
}
|
||||
//https://api-docs.affinity.co/#get-a-specific-person
|
||||
if (operation === 'get') {
|
||||
const personId = this.getNodeParameter('personId', i) as number;
|
||||
const options = this.getNodeParameter('options', i);
|
||||
if (options.withInteractionDates) {
|
||||
qs.with_interaction_dates = options.withInteractionDates as boolean;
|
||||
}
|
||||
responseData = await affinityApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/persons/${personId}`,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
}
|
||||
//https://api-docs.affinity.co/#search-for-persons
|
||||
if (operation === 'getAll') {
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
const options = this.getNodeParameter('options', i);
|
||||
if (options.term) {
|
||||
qs.term = options.term as string;
|
||||
}
|
||||
if (options.withInteractionDates) {
|
||||
qs.with_interaction_dates = options.withInteractionDates as boolean;
|
||||
}
|
||||
if (returnAll) {
|
||||
responseData = await affinityApiRequestAllItems.call(
|
||||
this,
|
||||
'persons',
|
||||
'GET',
|
||||
'/persons',
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
} else {
|
||||
qs.page_size = this.getNodeParameter('limit', i);
|
||||
responseData = await affinityApiRequest.call(this, 'GET', '/persons', {}, qs);
|
||||
responseData = responseData.persons;
|
||||
}
|
||||
}
|
||||
//https://api-docs.affinity.co/#delete-a-person
|
||||
if (operation === 'delete') {
|
||||
const personId = this.getNodeParameter('personId', i) as number;
|
||||
responseData = await affinityApiRequest.call(
|
||||
this,
|
||||
'DELETE',
|
||||
`/persons/${personId}`,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (resource === 'organization') {
|
||||
//https://api-docs.affinity.co/#create-a-new-organization
|
||||
if (operation === 'create') {
|
||||
const name = this.getNodeParameter('name', i) as string;
|
||||
const domain = this.getNodeParameter('domain', i) as string;
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
const body: IOrganization = {
|
||||
name,
|
||||
domain,
|
||||
};
|
||||
if (additionalFields.persons) {
|
||||
body.person_ids = additionalFields.persons as number[];
|
||||
}
|
||||
responseData = await affinityApiRequest.call(this, 'POST', '/organizations', body);
|
||||
}
|
||||
//https://api-docs.affinity.co/#update-an-organization
|
||||
if (operation === 'update') {
|
||||
const organizationId = this.getNodeParameter('organizationId', i) as number;
|
||||
const updateFields = this.getNodeParameter('updateFields', i);
|
||||
const body: IOrganization = {};
|
||||
if (updateFields.name) {
|
||||
body.name = updateFields.name as string;
|
||||
}
|
||||
if (updateFields.domain) {
|
||||
body.domain = updateFields.domain as string;
|
||||
}
|
||||
if (updateFields.persons) {
|
||||
body.person_ids = updateFields.persons as number[];
|
||||
}
|
||||
responseData = await affinityApiRequest.call(
|
||||
this,
|
||||
'PUT',
|
||||
`/organizations/${organizationId}`,
|
||||
body,
|
||||
);
|
||||
}
|
||||
//https://api-docs.affinity.co/#get-a-specific-organization
|
||||
if (operation === 'get') {
|
||||
const organizationId = this.getNodeParameter('organizationId', i) as number;
|
||||
const options = this.getNodeParameter('options', i);
|
||||
if (options.withInteractionDates) {
|
||||
qs.with_interaction_dates = options.withInteractionDates as boolean;
|
||||
}
|
||||
responseData = await affinityApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/organizations/${organizationId}`,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
}
|
||||
//https://api-docs.affinity.co/#search-for-organizations
|
||||
if (operation === 'getAll') {
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
const options = this.getNodeParameter('options', i);
|
||||
if (options.term) {
|
||||
qs.term = options.term as string;
|
||||
}
|
||||
if (options.withInteractionDates) {
|
||||
qs.with_interaction_dates = options.withInteractionDates as boolean;
|
||||
}
|
||||
if (returnAll) {
|
||||
responseData = await affinityApiRequestAllItems.call(
|
||||
this,
|
||||
'organizations',
|
||||
'GET',
|
||||
'/organizations',
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
} else {
|
||||
qs.page_size = this.getNodeParameter('limit', i);
|
||||
responseData = await affinityApiRequest.call(this, 'GET', '/organizations', {}, qs);
|
||||
responseData = responseData.organizations;
|
||||
}
|
||||
}
|
||||
//https://api-docs.affinity.co/#delete-an-organization
|
||||
if (operation === 'delete') {
|
||||
const organizationId = this.getNodeParameter('organizationId', i) as number;
|
||||
responseData = await affinityApiRequest.call(
|
||||
this,
|
||||
'DELETE',
|
||||
`/organizations/${organizationId}`,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
const executionErrorData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray({ error: error.message }),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionErrorData);
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
return [returnData];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.affinityTrigger",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Sales"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/affinity/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.affinitytrigger/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
import type {
|
||||
IHookFunctions,
|
||||
IWebhookFunctions,
|
||||
IDataObject,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
IWebhookResponseData,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';
|
||||
|
||||
import { affinityApiRequest, eventsExist, mapResource } from './GenericFunctions';
|
||||
|
||||
export class AffinityTrigger implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Affinity Trigger',
|
||||
name: 'affinityTrigger',
|
||||
icon: { light: 'file:affinity.svg', dark: 'file:affinity.dark.svg' },
|
||||
group: ['trigger'],
|
||||
version: 1,
|
||||
description: 'Handle Affinity events via webhooks',
|
||||
defaults: {
|
||||
name: 'Affinity Trigger',
|
||||
},
|
||||
inputs: [],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'affinityApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
webhooks: [
|
||||
{
|
||||
name: 'default',
|
||||
httpMethod: 'POST',
|
||||
responseMode: 'onReceived',
|
||||
path: 'webhook',
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Events',
|
||||
name: 'events',
|
||||
type: 'multiOptions',
|
||||
options: [
|
||||
{
|
||||
name: 'field_value.created',
|
||||
value: 'field_value.created',
|
||||
},
|
||||
{
|
||||
name: 'field_value.deleted',
|
||||
value: 'field_value.deleted',
|
||||
},
|
||||
{
|
||||
name: 'field_value.updated',
|
||||
value: 'field_value.updated',
|
||||
},
|
||||
{
|
||||
name: 'field.created',
|
||||
value: 'field.created',
|
||||
},
|
||||
{
|
||||
name: 'field.deleted',
|
||||
value: 'field.deleted',
|
||||
},
|
||||
{
|
||||
name: 'field.updated',
|
||||
value: 'field.updated',
|
||||
},
|
||||
{
|
||||
name: 'file.created',
|
||||
value: 'file.created',
|
||||
},
|
||||
{
|
||||
name: 'file.deleted',
|
||||
value: 'file.deleted',
|
||||
},
|
||||
{
|
||||
name: 'list_entry.created',
|
||||
value: 'list_entry.created',
|
||||
},
|
||||
{
|
||||
name: 'list_entry.deleted',
|
||||
value: 'list_entry.deleted',
|
||||
},
|
||||
{
|
||||
name: 'list.created',
|
||||
value: 'list.created',
|
||||
},
|
||||
{
|
||||
name: 'list.deleted',
|
||||
value: 'list.deleted',
|
||||
},
|
||||
{
|
||||
name: 'list.updated',
|
||||
value: 'list.updated',
|
||||
},
|
||||
{
|
||||
name: 'note.created',
|
||||
value: 'note.created',
|
||||
},
|
||||
{
|
||||
name: 'note.deleted',
|
||||
value: 'note.deleted',
|
||||
},
|
||||
{
|
||||
name: 'note.updated',
|
||||
value: 'note.updated',
|
||||
},
|
||||
{
|
||||
name: 'opportunity.created',
|
||||
value: 'opportunity.created',
|
||||
},
|
||||
{
|
||||
name: 'opportunity.deleted',
|
||||
value: 'opportunity.deleted',
|
||||
},
|
||||
{
|
||||
name: 'opportunity.updated',
|
||||
value: 'opportunity.updated',
|
||||
},
|
||||
{
|
||||
name: 'organization.created',
|
||||
value: 'organization.created',
|
||||
},
|
||||
{
|
||||
name: 'organization.deleted',
|
||||
value: 'organization.deleted',
|
||||
},
|
||||
{
|
||||
name: 'organization.updated',
|
||||
value: 'organization.updated',
|
||||
},
|
||||
{
|
||||
name: 'person.created',
|
||||
value: 'person.created',
|
||||
},
|
||||
{
|
||||
name: 'person.deleted',
|
||||
value: 'person.deleted',
|
||||
},
|
||||
{
|
||||
name: 'person.updated',
|
||||
value: 'person.updated',
|
||||
},
|
||||
],
|
||||
default: [],
|
||||
required: true,
|
||||
description: 'Webhook events that will be enabled for that endpoint',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
webhookMethods = {
|
||||
default: {
|
||||
async checkExists(this: IHookFunctions): Promise<boolean> {
|
||||
// Check all the webhooks which exist already if it is identical to the
|
||||
// one that is supposed to get created.
|
||||
const endpoint = '/webhook';
|
||||
|
||||
const responseData = await affinityApiRequest.call(this, 'GET', endpoint, {});
|
||||
|
||||
const webhookUrl = this.getNodeWebhookUrl('default');
|
||||
|
||||
const events = this.getNodeParameter('events') as string[];
|
||||
|
||||
for (const webhook of responseData) {
|
||||
if (
|
||||
eventsExist(webhook.subscriptions as string[], events) &&
|
||||
webhook.webhook_url === webhookUrl
|
||||
) {
|
||||
// Set webhook-id to be sure that it can be deleted
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
webhookData.webhookId = webhook.id as string;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
async create(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookUrl = this.getNodeWebhookUrl('default') as string;
|
||||
|
||||
if (webhookUrl.includes('%20')) {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
'The name of the Affinity Trigger Node is not allowed to contain any spaces!',
|
||||
);
|
||||
}
|
||||
|
||||
const events = this.getNodeParameter('events') as string[];
|
||||
|
||||
const endpoint = '/webhook/subscribe';
|
||||
|
||||
const body = {
|
||||
webhook_url: webhookUrl,
|
||||
subscriptions: events,
|
||||
};
|
||||
|
||||
const responseData = await affinityApiRequest.call(this, 'POST', endpoint, body);
|
||||
|
||||
if (responseData.id === undefined) {
|
||||
// Required data is missing so was not successful
|
||||
return false;
|
||||
}
|
||||
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
webhookData.webhookId = responseData.id as string;
|
||||
return true;
|
||||
},
|
||||
async delete(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
if (webhookData.webhookId !== undefined) {
|
||||
const endpoint = `/webhook/${webhookData.webhookId}`;
|
||||
|
||||
const responseData = await affinityApiRequest.call(this, 'DELETE', endpoint);
|
||||
|
||||
if (!responseData.success) {
|
||||
return false;
|
||||
}
|
||||
// Remove from the static workflow data so that it is clear
|
||||
// that no webhooks are registered anymore
|
||||
delete webhookData.webhookId;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
|
||||
const bodyData = this.getBodyData();
|
||||
|
||||
if (bodyData.type === 'sample.webhook') {
|
||||
return {};
|
||||
}
|
||||
|
||||
let responseData: IDataObject = {};
|
||||
|
||||
if (bodyData.type && bodyData.body) {
|
||||
const resource = (bodyData.type as string).split('.')[0];
|
||||
//@ts-ignore
|
||||
const id = bodyData.body.id;
|
||||
responseData = await affinityApiRequest.call(this, 'GET', `/${mapResource(resource)}/${id}`);
|
||||
responseData.type = bodyData.type;
|
||||
}
|
||||
|
||||
return {
|
||||
workflowData: [this.helpers.returnJsonArray(responseData)],
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import type {
|
||||
IDataObject,
|
||||
IExecuteFunctions,
|
||||
ILoadOptionsFunctions,
|
||||
IHookFunctions,
|
||||
IWebhookFunctions,
|
||||
JsonObject,
|
||||
IRequestOptions,
|
||||
IHttpRequestMethods,
|
||||
} from 'n8n-workflow';
|
||||
import { BINARY_ENCODING, NodeApiError } from 'n8n-workflow';
|
||||
|
||||
export async function affinityApiRequest(
|
||||
this: IExecuteFunctions | IWebhookFunctions | IHookFunctions | ILoadOptionsFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
resource: string,
|
||||
body: any = {},
|
||||
query: IDataObject = {},
|
||||
uri?: string,
|
||||
option: IDataObject = {},
|
||||
): Promise<any> {
|
||||
const credentials = await this.getCredentials('affinityApi');
|
||||
|
||||
const apiKey = `:${credentials.apiKey}`;
|
||||
|
||||
const endpoint = 'https://api.affinity.co';
|
||||
|
||||
let options: IRequestOptions = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Basic ${Buffer.from(apiKey).toString(BINARY_ENCODING)}`,
|
||||
},
|
||||
method,
|
||||
body,
|
||||
qs: query,
|
||||
uri: uri || `${endpoint}${resource}`,
|
||||
json: true,
|
||||
};
|
||||
if (!Object.keys(body as IDataObject).length) {
|
||||
delete options.body;
|
||||
}
|
||||
if (!Object.keys(query).length) {
|
||||
delete options.qs;
|
||||
}
|
||||
options = Object.assign({}, options, option);
|
||||
try {
|
||||
return await this.helpers.request(options);
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
}
|
||||
|
||||
export async function affinityApiRequestAllItems(
|
||||
this: IHookFunctions | ILoadOptionsFunctions | IExecuteFunctions,
|
||||
propertyName: string,
|
||||
method: IHttpRequestMethods,
|
||||
resource: string,
|
||||
body: any = {},
|
||||
query: IDataObject = {},
|
||||
): Promise<any> {
|
||||
const returnData: IDataObject[] = [];
|
||||
|
||||
let responseData;
|
||||
|
||||
query.page_size = 500;
|
||||
|
||||
do {
|
||||
responseData = await affinityApiRequest.call(this, method, resource, body, query);
|
||||
query.page_token = responseData.page_token;
|
||||
returnData.push.apply(returnData, responseData[propertyName] as IDataObject[]);
|
||||
} while (responseData.page_token !== undefined && responseData.page_token !== null);
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
||||
export function eventsExist(subscriptions: string[], currentSubsriptions: string[]) {
|
||||
for (const subscription of currentSubsriptions) {
|
||||
if (!subscriptions.includes(subscription)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function mapResource(key: string) {
|
||||
return {
|
||||
person: 'persons',
|
||||
list: 'lists',
|
||||
note: 'notes',
|
||||
organization: 'organizatitons',
|
||||
list_entry: 'list-entries',
|
||||
field: 'fields',
|
||||
file: 'files',
|
||||
}[key];
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const listOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['list'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a list',
|
||||
action: 'Get a list',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many lists',
|
||||
action: 'Get many lists',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
export const listFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* list:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'List ID',
|
||||
name: 'listId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['list'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
description: 'The unique ID of the list object to be retrieved',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* list:getAll */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['list'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['list'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 10,
|
||||
},
|
||||
default: 5,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,225 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const listEntryOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['listEntry'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a list entry',
|
||||
action: 'Create a list entry',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete a list entry',
|
||||
action: 'Delete a list entry',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a list entry',
|
||||
action: 'Get a list entry',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many list entries',
|
||||
action: 'Get many list entries',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const listEntryFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* listEntry:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'List Name or ID',
|
||||
name: 'listId',
|
||||
type: 'options',
|
||||
required: true,
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getLists',
|
||||
},
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['listEntry'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The unique ID of the list whose list entries are to be retrieved. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Entity ID',
|
||||
name: 'entityId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['listEntry'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The unique ID of the entity (person, organization, or opportunity) to add to this list',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['listEntry'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Creator ID',
|
||||
name: 'creator_id',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'The ID of a Person resource who should be recorded as adding the entry to the list. Must be a person who can access Affinity. If not provided the creator defaults to the owner of the API key.',
|
||||
},
|
||||
],
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* listEntry:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'List Name or ID',
|
||||
name: 'listId',
|
||||
type: 'options',
|
||||
required: true,
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getLists',
|
||||
},
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['listEntry'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The unique ID of the list that contains the specified list_entry_id. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'List Entry ID',
|
||||
name: 'listEntryId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['listEntry'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
description: 'The unique ID of the list entry object to be retrieved',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* listEntry:getAll */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'List Name or ID',
|
||||
name: 'listId',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getLists',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['listEntry'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'The unique ID of the list whose list entries are to be retrieved. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['listEntry'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['listEntry'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 10,
|
||||
},
|
||||
default: 5,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* listEntry:delete */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'List Name or ID',
|
||||
name: 'listId',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getLists',
|
||||
},
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['listEntry'],
|
||||
operation: ['delete'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The unique ID of the list that contains the specified list_entry_id. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'List Entry ID',
|
||||
name: 'listEntryId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['listEntry'],
|
||||
operation: ['delete'],
|
||||
},
|
||||
},
|
||||
description: 'The unique ID of the list entry object to be deleted',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,285 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const organizationOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['organization'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create an organization',
|
||||
action: 'Create an organization',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete an organization',
|
||||
action: 'Delete an organization',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get an organization',
|
||||
action: 'Get an organization',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many organizations',
|
||||
action: 'Get many organizations',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update an organization',
|
||||
action: 'Update an organization',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const organizationFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* organization:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['organization'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
description: 'The name of the organization',
|
||||
},
|
||||
{
|
||||
displayName: 'Domain',
|
||||
name: 'domain',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['organization'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
description: 'The domain name of the organization',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['organization'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Person Names or IDs',
|
||||
name: 'persons',
|
||||
type: 'multiOptions',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getPersons',
|
||||
},
|
||||
default: [],
|
||||
description:
|
||||
'Persons that the new organization will be associated with. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
],
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* organization:update */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Organization ID',
|
||||
name: 'organizationId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['organization'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
description: 'Unique identifier for the organization',
|
||||
},
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['organization'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Domain',
|
||||
name: 'domain',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The domain name of the organization',
|
||||
},
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The name of the organization',
|
||||
},
|
||||
{
|
||||
displayName: 'Person Names or IDs',
|
||||
name: 'persons',
|
||||
type: 'multiOptions',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getPersons',
|
||||
},
|
||||
default: [],
|
||||
description:
|
||||
'Persons that the new organization will be associated with. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
],
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* organization:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Organization ID',
|
||||
name: 'organizationId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['organization'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
description: 'Unique identifier for the organization',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add option',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['organization'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'With Interaction Dates',
|
||||
name: 'withInteractionDates',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether interaction dates will be present on the returned resources',
|
||||
},
|
||||
],
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* organization:getAll */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['organization'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['organization'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 10,
|
||||
},
|
||||
default: 5,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add option',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['organization'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Term',
|
||||
name: 'term',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'A string used to search all the organizations in your team’s address book. This could be an email address, a first name or a last name.',
|
||||
},
|
||||
{
|
||||
displayName: 'With Interaction Dates',
|
||||
name: 'withInteractionDates',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether interaction dates will be present on the returned resources',
|
||||
},
|
||||
],
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* organization:delete */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Organization ID',
|
||||
name: 'organizationId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['organization'],
|
||||
operation: ['delete'],
|
||||
},
|
||||
},
|
||||
description: 'Unique identifier for the organization',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
export interface IOrganization {
|
||||
name?: string;
|
||||
domain?: string;
|
||||
person_ids?: number[];
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const personOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a person',
|
||||
action: 'Create a person',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete a person',
|
||||
action: 'Delete a person',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a person',
|
||||
action: 'Get a person',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many persons',
|
||||
action: 'Get many people',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update a person',
|
||||
action: 'Update a person',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const personFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* person:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'First Name',
|
||||
name: 'firstName',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
description: 'The first name of the person',
|
||||
},
|
||||
{
|
||||
displayName: 'Last Name',
|
||||
name: 'lastName',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
description: 'The last name of the person',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Organization Names or IDs',
|
||||
name: 'organizations',
|
||||
type: 'multiOptions',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getOrganizations',
|
||||
},
|
||||
default: [],
|
||||
description:
|
||||
'Organizations that the person is associated with. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Emails',
|
||||
name: 'emails',
|
||||
type: 'string',
|
||||
description: 'The email addresses of the person',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add To Email',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
placeholder: 'info@example.com',
|
||||
default: [],
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* person:update */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Person ID',
|
||||
name: 'personId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
description: 'Unique identifier for the person',
|
||||
},
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'First Name',
|
||||
name: 'firstName',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The first name of the person',
|
||||
},
|
||||
{
|
||||
displayName: 'Last Name',
|
||||
name: 'lastName',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The last name of the person',
|
||||
},
|
||||
{
|
||||
displayName: 'Organization Names or IDs',
|
||||
name: 'organizations',
|
||||
type: 'multiOptions',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getOrganizations',
|
||||
},
|
||||
default: [],
|
||||
description:
|
||||
'Organizations that the person is associated with. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Emails',
|
||||
name: 'emails',
|
||||
type: 'string',
|
||||
description: 'The email addresses of the person',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add To Email',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
placeholder: 'info@example.com',
|
||||
default: [],
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* person:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Person ID',
|
||||
name: 'personId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
description: 'Unique identifier for the person',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add option',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'With Interaction Dates',
|
||||
name: 'withInteractionDates',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether interaction dates will be present on the returned resources',
|
||||
},
|
||||
],
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* person:getAll */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 10,
|
||||
},
|
||||
default: 5,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add option',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Term',
|
||||
name: 'term',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'A string used to search all the persons in your team’s address book. This could be an email address, a first name or a last name.',
|
||||
},
|
||||
{
|
||||
displayName: 'With Interaction Dates',
|
||||
name: 'withInteractionDates',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether interaction dates will be present on the returned resources',
|
||||
},
|
||||
],
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* person:delete */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Person ID',
|
||||
name: 'personId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['person'],
|
||||
operation: ['delete'],
|
||||
},
|
||||
},
|
||||
description: 'Unique identifier for the person',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,6 @@
|
||||
export interface IPerson {
|
||||
first_name?: string;
|
||||
last_name?: string;
|
||||
emails?: string[];
|
||||
organization_ids?: number[];
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"creator_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"list_size": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"public": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"creator_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"entity": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"crunchbase_uuid": {
|
||||
"type": "null"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string"
|
||||
},
|
||||
"domains": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"global": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"entity_type": {
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"list_id": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"creator_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"entity": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"crunchbase_uuid": {
|
||||
"type": "null"
|
||||
},
|
||||
"domains": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"global": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"entity_type": {
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"list_id": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"version": 3
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"crunchbase_uuid": {
|
||||
"type": "null"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string"
|
||||
},
|
||||
"domains": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"global": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"person_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"crunchbase_uuid": {
|
||||
"type": "null"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string"
|
||||
},
|
||||
"domains": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"global": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"list_entries": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"creator_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"entity_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"entity_type": {
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"list_id": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"person_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": 3
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"crunchbase_uuid": {
|
||||
"type": "null"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string"
|
||||
},
|
||||
"domains": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"global": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 2
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"emails": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"first_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"list_entries": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"creator_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"entity_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"entity_type": {
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"list_id": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"organization_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"emails": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"first_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0_1002_8324" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="40" height="40">
|
||||
<path d="M32.4632 23.7334L34.3904 25.6595C35.5228 26.8199 36.152 28.3799 36.1418 30.0012C36.1315 31.6225 35.4825 33.1744 34.3356 34.3204C33.1887 35.4664 31.6362 36.1141 30.0149 36.1231C28.3936 36.132 26.8341 35.5015 25.6746 34.3682L23.7308 32.4226C23.8337 32.0677 23.8864 31.7001 23.8875 31.3306C23.8873 31.005 23.8452 30.6807 23.7621 30.3658L30.3478 23.7813C31.043 23.9627 31.7751 23.9461 32.4614 23.7334M5.70165 34.296C4.55763 33.1545 3.90875 31.6086 3.89524 29.9925C3.88174 28.3765 4.5047 26.82 5.62949 25.6595L7.63246 23.6689C8.30009 23.9123 9.02155 23.9686 9.71884 23.8316L16.2128 30.322C16.124 30.6499 16.0791 30.988 16.0791 31.3277C16.0785 31.712 16.1347 32.0943 16.246 32.4622L14.3435 34.3658C13.1809 35.4886 11.6239 36.1101 10.0077 36.0965C8.3915 36.0828 6.84523 35.4353 5.70165 34.2931M20.8783 12.1628L27.5853 18.8656C27.3587 19.6074 27.3587 20.4 27.5853 21.1418V21.1377L21.1161 27.6009C20.3906 27.3803 19.6165 27.3758 18.8884 27.5879L12.6292 21.3341C12.944 20.4731 12.944 19.5284 12.6292 18.6674L19.1321 12.1734C19.7073 12.3038 20.3048 12.3002 20.8783 12.1628ZM16.2826 9.60611V9.60256V9.60848V9.60611ZM23.6971 9.56056C23.8241 9.17437 23.889 8.77043 23.8893 8.36387C23.8882 8.07789 23.856 7.79287 23.7935 7.51381L25.6705 5.63743C26.8335 4.52383 28.3862 3.90983 29.9963 3.92691C31.6064 3.94399 33.1458 4.59079 34.2849 5.72882C35.424 6.86685 36.0723 8.40564 36.0909 10.0157C36.1095 11.6258 35.497 13.1792 34.3845 14.3432L32.459 16.2699C32.0911 16.159 31.7088 16.1027 31.3244 16.1031C31.0019 16.1025 30.6807 16.1433 30.3685 16.2243L23.6971 9.56056ZM5.62949 14.3414C4.50287 13.1801 3.87837 11.6222 3.89091 10.0042C3.90346 8.38625 4.55204 6.83818 5.69654 5.69447C6.84103 4.55075 8.38954 3.90322 10.0075 3.89177C11.6255 3.88033 13.183 4.50588 14.3435 5.63329L16.1856 7.47655C16.0168 8.18138 16.0505 8.91955 16.2826 9.60611L9.72062 16.1723C9.0221 16.0358 8.29948 16.095 7.63246 16.3432L5.62949 14.3414ZM9.98859 2.34538e-06C8.01364 -0.0013512 6.08268 0.583186 4.44006 1.67964C2.79744 2.7761 1.51699 4.33519 0.760763 6.15962C0.00453271 7.98404 -0.193492 9.9918 0.191747 11.9288C0.576986 13.8658 1.52817 15.645 2.92494 17.0412L5.13022 19.2483C5.03143 19.7437 5.03143 20.2537 5.13022 20.7491L2.92257 22.9555C1.05059 24.8291 -0.000455671 27.3695 0.000653692 30.018C0.00176306 32.6665 1.05494 35.2061 2.92849 37.0781C4.80204 38.9501 7.3425 40.0011 9.99099 40C12.6395 39.9989 15.1791 38.9457 17.051 37.0722L19.0138 35.1082C19.6625 35.2804 20.345 35.2804 20.9937 35.1082L22.9689 37.0828C24.3351 38.4256 26.0587 39.3472 27.9342 39.7377C29.8096 40.1283 31.7578 39.9713 33.5465 39.2855C35.3352 38.5997 36.889 37.414 38.0227 35.8697C39.1563 34.3255 39.822 32.4878 39.9403 30.5758V29.3484C39.7956 26.9469 38.7846 24.6794 37.095 22.9668L35.1027 20.9638C35.1813 20.6508 35.221 20.3294 35.221 20.0067C35.221 19.6802 35.1789 19.3551 35.0956 19.0395L37.0944 17.0424C38.7765 15.3375 39.7863 13.0824 39.9379 10.6922V9.39552C39.813 7.48725 39.1429 5.65496 38.0072 4.11633C36.8716 2.5777 35.3181 1.3974 33.5314 0.715656C31.7447 0.033914 29.7999 -0.120614 27.9279 0.270429C26.056 0.661473 24.3356 1.58165 22.9712 2.92165L21.225 4.66671C20.4336 4.39806 19.5765 4.39287 18.7819 4.65192L17.0528 2.9252C15.1791 1.052 12.6381 -0.000209017 9.98859 2.34538e-06Z" fill="white"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_1002_8324)">
|
||||
<rect x="-0.479492" y="-0.450134" width="40.8575" height="40.8575" fill="white"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 29 KiB |
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.agileCrm",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Marketing", "Sales"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/agilecrm/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.agilecrm/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,642 @@
|
||||
import type {
|
||||
IExecuteFunctions,
|
||||
IDataObject,
|
||||
INodeExecutionData,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionTypes, jsonParse, NodeOperationError } from 'n8n-workflow';
|
||||
|
||||
import { companyFields, companyOperations } from './CompanyDescription';
|
||||
import { contactFields, contactOperations } from './ContactDescription';
|
||||
import type { IContact, IContactUpdate } from './ContactInterface';
|
||||
import { dealFields, dealOperations } from './DealDescription';
|
||||
import type { IDeal } from './DealInterface';
|
||||
import type { IFilter, ISearchConditions } from './FilterInterface';
|
||||
import {
|
||||
agileCrmApiRequest,
|
||||
agileCrmApiRequestAllItems,
|
||||
agileCrmApiRequestUpdate,
|
||||
getFilterRules,
|
||||
simplifyResponse,
|
||||
validateJSON,
|
||||
} from './GenericFunctions';
|
||||
|
||||
export class AgileCrm implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Agile CRM',
|
||||
name: 'agileCrm',
|
||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-icon-not-svg
|
||||
icon: 'file:agilecrm.png',
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
group: ['transform'],
|
||||
version: 1,
|
||||
description: 'Consume Agile CRM API',
|
||||
defaults: {
|
||||
name: 'Agile CRM',
|
||||
},
|
||||
usableAsTool: true,
|
||||
inputs: [NodeConnectionTypes.Main],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'agileCrmApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
// Node properties which the user gets displayed and
|
||||
// can change on the node.
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
options: [
|
||||
{
|
||||
name: 'Company',
|
||||
value: 'company',
|
||||
},
|
||||
{
|
||||
name: 'Contact',
|
||||
value: 'contact',
|
||||
},
|
||||
{
|
||||
name: 'Deal',
|
||||
value: 'deal',
|
||||
},
|
||||
],
|
||||
default: 'contact',
|
||||
},
|
||||
// CONTACT
|
||||
...contactOperations,
|
||||
...contactFields,
|
||||
|
||||
// COMPANY
|
||||
...companyOperations,
|
||||
...companyFields,
|
||||
|
||||
// DEAL
|
||||
...dealOperations,
|
||||
...dealFields,
|
||||
],
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const returnData: IDataObject[] = [];
|
||||
let responseData;
|
||||
const resource = this.getNodeParameter('resource', 0);
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (resource === 'contact' || resource === 'company') {
|
||||
const idGetter = resource === 'contact' ? 'contactId' : 'companyId';
|
||||
|
||||
if (operation === 'get') {
|
||||
const contactId = this.getNodeParameter(idGetter, i) as string;
|
||||
|
||||
const endpoint = `api/contacts/${contactId}`;
|
||||
responseData = await agileCrmApiRequest.call(this, 'GET', endpoint, {});
|
||||
} else if (operation === 'delete') {
|
||||
const contactId = this.getNodeParameter(idGetter, i) as string;
|
||||
|
||||
const endpoint = `api/contacts/${contactId}`;
|
||||
responseData = await agileCrmApiRequest.call(this, 'DELETE', endpoint, {});
|
||||
} else if (operation === 'getAll') {
|
||||
const simple = this.getNodeParameter('simple', 0) as boolean;
|
||||
const returnAll = this.getNodeParameter('returnAll', 0);
|
||||
const filterType = this.getNodeParameter('filterType', i) as string;
|
||||
const sort = this.getNodeParameter('options.sort.sort', i, {}) as {
|
||||
direction: string;
|
||||
field: string;
|
||||
};
|
||||
const body: IDataObject = {};
|
||||
const filterJson: IFilter = {};
|
||||
|
||||
let contactType = '';
|
||||
if (resource === 'contact') {
|
||||
contactType = 'PERSON';
|
||||
} else {
|
||||
contactType = 'COMPANY';
|
||||
}
|
||||
filterJson.contact_type = contactType;
|
||||
|
||||
if (filterType === 'manual') {
|
||||
const conditions = this.getNodeParameter(
|
||||
'filters.conditions',
|
||||
i,
|
||||
[],
|
||||
) as ISearchConditions[];
|
||||
const matchType = this.getNodeParameter('matchType', i) as string;
|
||||
let rules;
|
||||
if (conditions.length !== 0) {
|
||||
rules = getFilterRules(conditions, matchType);
|
||||
Object.assign(filterJson, rules);
|
||||
} else {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
'At least one condition must be added.',
|
||||
{ itemIndex: i },
|
||||
);
|
||||
}
|
||||
} else if (filterType === 'json') {
|
||||
const filterJsonRules = this.getNodeParameter('filterJson', i) as string;
|
||||
if (validateJSON(filterJsonRules) !== undefined) {
|
||||
Object.assign(filterJson, jsonParse(filterJsonRules));
|
||||
} else {
|
||||
throw new NodeOperationError(this.getNode(), 'Filter (JSON) must be a valid json', {
|
||||
itemIndex: i,
|
||||
});
|
||||
}
|
||||
}
|
||||
body.filterJson = JSON.stringify(filterJson);
|
||||
|
||||
if (sort) {
|
||||
if (sort.direction === 'ASC') {
|
||||
body.global_sort_key = sort.field;
|
||||
} else if (sort.direction === 'DESC') {
|
||||
body.global_sort_key = `-${sort.field}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (returnAll) {
|
||||
body.page_size = 100;
|
||||
responseData = await agileCrmApiRequestAllItems.call(
|
||||
this,
|
||||
'POST',
|
||||
'api/filters/filter/dynamic-filter',
|
||||
body,
|
||||
undefined,
|
||||
undefined,
|
||||
true,
|
||||
);
|
||||
} else {
|
||||
body.page_size = this.getNodeParameter('limit', 0);
|
||||
responseData = await agileCrmApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
'api/filters/filter/dynamic-filter',
|
||||
body,
|
||||
undefined,
|
||||
undefined,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
if (simple) {
|
||||
responseData = simplifyResponse(responseData);
|
||||
}
|
||||
} else if (operation === 'create') {
|
||||
const jsonParameters = this.getNodeParameter('jsonParameters', i);
|
||||
const body: IContact = {};
|
||||
const properties: IDataObject[] = [];
|
||||
|
||||
if (jsonParameters) {
|
||||
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
|
||||
|
||||
if (additionalFieldsJson !== '') {
|
||||
if (validateJSON(additionalFieldsJson) !== undefined) {
|
||||
Object.assign(body, jsonParse(additionalFieldsJson));
|
||||
} else {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
'Additional fields must be a valid JSON',
|
||||
{ itemIndex: i },
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
|
||||
// if company, add 'company' as type. default is person
|
||||
if (resource === 'company') {
|
||||
body.type = 'COMPANY';
|
||||
}
|
||||
if (additionalFields.starValue) {
|
||||
body.star_value = additionalFields.starValue as string;
|
||||
}
|
||||
if (additionalFields.tags) {
|
||||
body.tags = additionalFields.tags as string[];
|
||||
}
|
||||
|
||||
// Contact specific properties
|
||||
if (resource === 'contact') {
|
||||
if (additionalFields.firstName) {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
name: 'first_name',
|
||||
value: additionalFields.firstName as string,
|
||||
} as IDataObject);
|
||||
}
|
||||
if (additionalFields.lastName) {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
name: 'last_name',
|
||||
value: additionalFields.lastName as string,
|
||||
} as IDataObject);
|
||||
}
|
||||
if (additionalFields.company) {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
name: 'company',
|
||||
value: additionalFields.company as string,
|
||||
} as IDataObject);
|
||||
}
|
||||
if (additionalFields.title) {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
name: 'title',
|
||||
value: additionalFields.title as string,
|
||||
} as IDataObject);
|
||||
}
|
||||
if (additionalFields.emailOptions) {
|
||||
//@ts-ignore
|
||||
additionalFields.emailOptions.emailProperties.map((property) => {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
subtype: property.subtype as string,
|
||||
name: 'email',
|
||||
value: property.email as string,
|
||||
} as IDataObject);
|
||||
});
|
||||
}
|
||||
if (additionalFields.addressOptions) {
|
||||
//@ts-ignore
|
||||
additionalFields.addressOptions.addressProperties.map((property) => {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
subtype: property.subtype as string,
|
||||
name: 'address',
|
||||
value: property.address as string,
|
||||
} as IDataObject);
|
||||
});
|
||||
}
|
||||
|
||||
if (additionalFields.phoneOptions) {
|
||||
//@ts-ignore
|
||||
additionalFields.phoneOptions.phoneProperties.map((property) => {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
subtype: property.subtype as string,
|
||||
name: 'phone',
|
||||
value: property.number as string,
|
||||
} as IDataObject);
|
||||
});
|
||||
}
|
||||
} else if (resource === 'company') {
|
||||
if (additionalFields.email) {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
name: 'email',
|
||||
value: additionalFields.email as string,
|
||||
} as IDataObject);
|
||||
}
|
||||
|
||||
if (additionalFields.addressOptions) {
|
||||
//@ts-ignore
|
||||
additionalFields.addressOptions.addressProperties.map((property) => {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
subtype: property.subtype as string,
|
||||
name: 'address',
|
||||
value: property.address as string,
|
||||
} as IDataObject);
|
||||
});
|
||||
}
|
||||
|
||||
if (additionalFields.phone) {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
name: 'phone',
|
||||
value: additionalFields.phone as string,
|
||||
} as IDataObject);
|
||||
}
|
||||
|
||||
if (additionalFields.name) {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
name: 'name',
|
||||
value: additionalFields.name as string,
|
||||
} as IDataObject);
|
||||
}
|
||||
}
|
||||
|
||||
if (additionalFields.websiteOptions) {
|
||||
//@ts-ignore
|
||||
additionalFields.websiteOptions.websiteProperties.map((property) => {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
subtype: property.subtype as string,
|
||||
name: 'website',
|
||||
value: property.url as string,
|
||||
} as IDataObject);
|
||||
});
|
||||
}
|
||||
|
||||
if (additionalFields.customProperties) {
|
||||
//@ts-ignore
|
||||
additionalFields.customProperties.customProperty.map((property) => {
|
||||
properties.push({
|
||||
type: 'CUSTOM',
|
||||
subtype: property.subtype as string,
|
||||
name: property.name,
|
||||
value: property.value as string,
|
||||
} as IDataObject);
|
||||
});
|
||||
}
|
||||
body.properties = properties;
|
||||
}
|
||||
const endpoint = 'api/contacts';
|
||||
responseData = await agileCrmApiRequest.call(this, 'POST', endpoint, body);
|
||||
} else if (operation === 'update') {
|
||||
const contactId = this.getNodeParameter(idGetter, i) as string;
|
||||
const contactUpdatePayload: IContactUpdate = { id: contactId };
|
||||
const jsonParameters = this.getNodeParameter('jsonParameters', i);
|
||||
const body: IContact = {};
|
||||
const properties: IDataObject[] = [];
|
||||
|
||||
if (jsonParameters) {
|
||||
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
|
||||
|
||||
if (additionalFieldsJson !== '') {
|
||||
if (validateJSON(additionalFieldsJson) !== undefined) {
|
||||
Object.assign(body, jsonParse(additionalFieldsJson));
|
||||
} else {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
'Additional fields must be a valid JSON',
|
||||
{ itemIndex: i },
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
|
||||
if (additionalFields.starValue) {
|
||||
body.star_value = additionalFields.starValue as string;
|
||||
}
|
||||
if (additionalFields.tags) {
|
||||
body.tags = additionalFields.tags as string[];
|
||||
}
|
||||
|
||||
// Contact specific properties
|
||||
if (resource === 'contact') {
|
||||
if (additionalFields.leadScore) {
|
||||
body.lead_score = additionalFields.leadScore as string;
|
||||
}
|
||||
|
||||
if (additionalFields.firstName) {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
name: 'first_name',
|
||||
value: additionalFields.firstName as string,
|
||||
} as IDataObject);
|
||||
}
|
||||
if (additionalFields.lastName) {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
name: 'last_name',
|
||||
value: additionalFields.lastName as string,
|
||||
} as IDataObject);
|
||||
}
|
||||
if (additionalFields.company) {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
name: 'company',
|
||||
value: additionalFields.company as string,
|
||||
} as IDataObject);
|
||||
}
|
||||
if (additionalFields.title) {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
name: 'title',
|
||||
value: additionalFields.title as string,
|
||||
} as IDataObject);
|
||||
}
|
||||
if (additionalFields.emailOptions) {
|
||||
//@ts-ignore
|
||||
additionalFields.emailOptions.emailProperties.map((property) => {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
subtype: property.subtype as string,
|
||||
name: 'email',
|
||||
value: property.email as string,
|
||||
} as IDataObject);
|
||||
});
|
||||
}
|
||||
if (additionalFields.addressOptions) {
|
||||
//@ts-ignore
|
||||
additionalFields.addressOptions.addressProperties.map((property) => {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
subtype: property.subtype as string,
|
||||
name: 'address',
|
||||
value: property.address as string,
|
||||
} as IDataObject);
|
||||
});
|
||||
}
|
||||
|
||||
if (additionalFields.phoneOptions) {
|
||||
//@ts-ignore
|
||||
additionalFields.phoneOptions.phoneProperties.map((property) => {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
subtype: property.subtype as string,
|
||||
name: 'phone',
|
||||
value: property.number as string,
|
||||
} as IDataObject);
|
||||
});
|
||||
}
|
||||
} else if (resource === 'company') {
|
||||
if (additionalFields.email) {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
name: 'email',
|
||||
value: additionalFields.email as string,
|
||||
} as IDataObject);
|
||||
}
|
||||
|
||||
if (additionalFields.addressOptions) {
|
||||
//@ts-ignore
|
||||
additionalFields.addressOptions.addressProperties.map((property) => {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
subtype: property.subtype as string,
|
||||
name: 'address',
|
||||
value: property.address as string,
|
||||
} as IDataObject);
|
||||
});
|
||||
}
|
||||
|
||||
if (additionalFields.phone) {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
name: 'phone',
|
||||
value: additionalFields.phone as string,
|
||||
} as IDataObject);
|
||||
}
|
||||
}
|
||||
|
||||
if (additionalFields.websiteOptions) {
|
||||
//@ts-ignore
|
||||
additionalFields.websiteOptions.websiteProperties.map((property) => {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
subtype: property.subtype as string,
|
||||
name: 'website',
|
||||
value: property.url as string,
|
||||
} as IDataObject);
|
||||
});
|
||||
}
|
||||
if (additionalFields.name) {
|
||||
properties.push({
|
||||
type: 'SYSTEM',
|
||||
name: 'name',
|
||||
value: additionalFields.name as string,
|
||||
} as IDataObject);
|
||||
}
|
||||
if (additionalFields.customProperties) {
|
||||
//@ts-ignore
|
||||
additionalFields.customProperties.customProperty.map((property) => {
|
||||
properties.push({
|
||||
type: 'CUSTOM',
|
||||
subtype: property.subtype as string,
|
||||
name: property.name,
|
||||
value: property.value as string,
|
||||
} as IDataObject);
|
||||
});
|
||||
}
|
||||
body.properties = properties;
|
||||
}
|
||||
|
||||
Object.assign(contactUpdatePayload, body);
|
||||
|
||||
responseData = await agileCrmApiRequestUpdate.call(this, 'PUT', '', contactUpdatePayload);
|
||||
}
|
||||
} else if (resource === 'deal') {
|
||||
if (operation === 'get') {
|
||||
const dealId = this.getNodeParameter('dealId', i) as string;
|
||||
|
||||
const endpoint = `api/opportunity/${dealId}`;
|
||||
responseData = await agileCrmApiRequest.call(this, 'GET', endpoint, {});
|
||||
} else if (operation === 'delete') {
|
||||
const contactId = this.getNodeParameter('dealId', i) as string;
|
||||
|
||||
const endpoint = `api/opportunity/${contactId}`;
|
||||
responseData = await agileCrmApiRequest.call(this, 'DELETE', endpoint, {});
|
||||
} else if (operation === 'getAll') {
|
||||
const returnAll = this.getNodeParameter('returnAll', 0);
|
||||
const endpoint = 'api/opportunity';
|
||||
|
||||
if (returnAll) {
|
||||
const limit = 100;
|
||||
responseData = await agileCrmApiRequestAllItems.call(this, 'GET', endpoint, undefined, {
|
||||
page_size: limit,
|
||||
});
|
||||
} else {
|
||||
const limit = this.getNodeParameter('limit', 0);
|
||||
responseData = await agileCrmApiRequest.call(this, 'GET', endpoint, undefined, {
|
||||
page_size: limit,
|
||||
});
|
||||
}
|
||||
} else if (operation === 'create') {
|
||||
const jsonParameters = this.getNodeParameter('jsonParameters', i);
|
||||
|
||||
const body: IDeal = {};
|
||||
|
||||
if (jsonParameters) {
|
||||
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
|
||||
|
||||
if (additionalFieldsJson !== '') {
|
||||
if (validateJSON(additionalFieldsJson) !== undefined) {
|
||||
Object.assign(body, jsonParse(additionalFieldsJson));
|
||||
} else {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
'Additional fields must be a valid JSON',
|
||||
{ itemIndex: i },
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
|
||||
body.close_date = new Date(this.getNodeParameter('closeDate', i) as string).getTime();
|
||||
body.expected_value = this.getNodeParameter('expectedValue', i) as number;
|
||||
body.milestone = this.getNodeParameter('milestone', i) as string;
|
||||
body.probability = this.getNodeParameter('probability', i) as number;
|
||||
body.name = this.getNodeParameter('name', i) as string;
|
||||
|
||||
if (additionalFields.contactIds) {
|
||||
body.contactIds = additionalFields.contactIds as string[];
|
||||
}
|
||||
|
||||
if (additionalFields.customData) {
|
||||
// @ts-ignore
|
||||
body.customData = additionalFields.customData.customProperty as IDealCustomProperty[];
|
||||
}
|
||||
}
|
||||
|
||||
const endpoint = 'api/opportunity';
|
||||
responseData = await agileCrmApiRequest.call(this, 'POST', endpoint, body);
|
||||
} else if (operation === 'update') {
|
||||
const jsonParameters = this.getNodeParameter('jsonParameters', i);
|
||||
|
||||
const body: IDeal = {};
|
||||
|
||||
if (jsonParameters) {
|
||||
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
|
||||
|
||||
if (additionalFieldsJson !== '') {
|
||||
if (validateJSON(additionalFieldsJson) !== undefined) {
|
||||
Object.assign(body, jsonParse(additionalFieldsJson));
|
||||
} else {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
'Additional fields must be valid JSON',
|
||||
{ itemIndex: i },
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
body.id = this.getNodeParameter('dealId', i) as number;
|
||||
|
||||
if (additionalFields.expectedValue) {
|
||||
body.expected_value = additionalFields.expectedValue as number;
|
||||
}
|
||||
|
||||
if (additionalFields.name) {
|
||||
body.name = additionalFields.name as string;
|
||||
}
|
||||
|
||||
if (additionalFields.probability) {
|
||||
body.probability = additionalFields.probability as number;
|
||||
}
|
||||
|
||||
if (additionalFields.contactIds) {
|
||||
body.contactIds = additionalFields.contactIds as string[];
|
||||
}
|
||||
|
||||
if (additionalFields.customData) {
|
||||
// @ts-ignore
|
||||
body.customData = additionalFields.customData.customProperty as IDealCustomProperty[];
|
||||
}
|
||||
}
|
||||
|
||||
const endpoint = 'api/opportunity/partial-update';
|
||||
responseData = await agileCrmApiRequest.call(this, 'PUT', endpoint, body);
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(responseData)) {
|
||||
returnData.push.apply(returnData, responseData as IDataObject[]);
|
||||
} else {
|
||||
returnData.push(responseData as IDataObject);
|
||||
}
|
||||
}
|
||||
|
||||
return [this.helpers.returnJsonArray(returnData)];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,924 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const companyOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a new company',
|
||||
action: 'Create a company',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete a company',
|
||||
action: 'Delete a company',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a company',
|
||||
action: 'Get a company',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many companies',
|
||||
action: 'Get many companies',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update company properties',
|
||||
action: 'Update a company',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
export const companyFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* company:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Company ID',
|
||||
name: 'companyId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Unique identifier for a particular company',
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* company:get all */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
default: 20,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
|
||||
{
|
||||
displayName: 'Filter',
|
||||
name: 'filterType',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'None',
|
||||
value: 'none',
|
||||
},
|
||||
{
|
||||
name: 'Build Manually',
|
||||
value: 'manual',
|
||||
},
|
||||
{
|
||||
name: 'JSON',
|
||||
value: 'json',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: 'none',
|
||||
},
|
||||
{
|
||||
displayName: 'Must Match',
|
||||
name: 'matchType',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Any Filter',
|
||||
value: 'anyFilter',
|
||||
},
|
||||
{
|
||||
name: 'All Filters',
|
||||
value: 'allFilters',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['getAll'],
|
||||
filterType: ['manual'],
|
||||
},
|
||||
},
|
||||
default: 'anyFilter',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
// eslint-disable-next-line n8n-nodes-base/node-param-default-wrong-for-simplify
|
||||
default: false,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['getAll'],
|
||||
filterType: ['manual'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Condition',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Conditions',
|
||||
name: 'conditions',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Field',
|
||||
name: 'field',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Any searchable field',
|
||||
},
|
||||
{
|
||||
displayName: 'Condition Type',
|
||||
name: 'condition_type',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'After',
|
||||
value: 'AFTER',
|
||||
},
|
||||
{
|
||||
name: 'Before',
|
||||
value: 'BEFORE',
|
||||
},
|
||||
{
|
||||
name: 'Between',
|
||||
value: 'BETWEEN',
|
||||
},
|
||||
{
|
||||
name: 'Equals',
|
||||
value: 'EQUALS',
|
||||
},
|
||||
{
|
||||
name: 'Last',
|
||||
value: 'LAST',
|
||||
},
|
||||
{
|
||||
name: 'Not Equal',
|
||||
value: 'NOTEQUALS',
|
||||
},
|
||||
{
|
||||
name: 'On',
|
||||
value: 'ON',
|
||||
},
|
||||
],
|
||||
default: 'EQUALS',
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'value',
|
||||
type: 'string',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Value 2',
|
||||
name: 'value2',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
condition_type: ['BETWEEN'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName:
|
||||
'See <a href="https://github.com/agilecrm/rest-api#121-get-contacts-by-dynamic-filter" target="_blank">Agile CRM guide</a> to creating filters',
|
||||
name: 'jsonNotice',
|
||||
type: 'notice',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['getAll'],
|
||||
filterType: ['json'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Filters (JSON)',
|
||||
name: 'filterJson',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['getAll'],
|
||||
filterType: ['json'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add option',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Sort',
|
||||
name: 'sort',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Sort',
|
||||
default: [],
|
||||
options: [
|
||||
{
|
||||
displayName: 'Sort',
|
||||
name: 'sort',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Direction',
|
||||
name: 'direction',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Ascending',
|
||||
value: 'ASC',
|
||||
},
|
||||
{
|
||||
name: 'Descending',
|
||||
value: 'DESC',
|
||||
},
|
||||
],
|
||||
default: 'ASC',
|
||||
description: 'The sorting direction',
|
||||
},
|
||||
{
|
||||
displayName: 'Field',
|
||||
name: 'field',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The sorting field',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* company:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'JSON Parameters',
|
||||
name: 'jsonParameters',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFieldsJson',
|
||||
type: 'json',
|
||||
typeOptions: {
|
||||
alwaysOpenEditWindow: true,
|
||||
},
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['create'],
|
||||
jsonParameters: [true],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'Object of values to set as described <a href="https://github.com/agilecrm/rest-api#1-companys---companies-api">here</a>',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['create'],
|
||||
jsonParameters: [false],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Address',
|
||||
name: 'addressOptions',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
description: 'Company address',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Address Properties',
|
||||
name: 'addressProperties',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Type',
|
||||
name: 'subtype',
|
||||
type: 'options',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Type of address',
|
||||
options: [
|
||||
{
|
||||
name: 'Postal',
|
||||
value: 'postal',
|
||||
},
|
||||
{
|
||||
name: 'Office',
|
||||
value: 'office',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Address',
|
||||
name: 'address',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Full address',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Email',
|
||||
name: 'email',
|
||||
type: 'string',
|
||||
placeholder: 'name@email.com',
|
||||
default: '',
|
||||
description: 'Company email',
|
||||
},
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Company name',
|
||||
},
|
||||
{
|
||||
displayName: 'Phone',
|
||||
name: 'phone',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Company phone',
|
||||
},
|
||||
{
|
||||
displayName: 'Star Value',
|
||||
name: 'starValue',
|
||||
type: 'options',
|
||||
default: '',
|
||||
description: 'Rating of company (Max value 5). This is not applicable for companies.',
|
||||
options: [
|
||||
{
|
||||
name: '0',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: '1',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: '2',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
name: '3',
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
name: '4',
|
||||
value: 4,
|
||||
},
|
||||
{
|
||||
name: '5',
|
||||
value: 5,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Tags',
|
||||
name: 'tags',
|
||||
type: 'string',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add Tag',
|
||||
},
|
||||
default: [],
|
||||
description:
|
||||
'Unique identifiers added to company, for easy management of companys. This is not applicable for companies.',
|
||||
},
|
||||
{
|
||||
displayName: 'Website',
|
||||
name: 'websiteOptions',
|
||||
type: 'fixedCollection',
|
||||
description: 'Companies websites',
|
||||
default: {},
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Website Properties.',
|
||||
name: 'websiteProperties',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Type',
|
||||
name: 'subtype',
|
||||
type: 'options',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Type of website',
|
||||
options: [
|
||||
{
|
||||
name: 'Facebook',
|
||||
value: 'facebook',
|
||||
},
|
||||
{
|
||||
name: 'Feed',
|
||||
value: 'feed',
|
||||
},
|
||||
{
|
||||
name: 'Flickr',
|
||||
value: 'flickr',
|
||||
},
|
||||
{
|
||||
name: 'Github',
|
||||
value: 'github',
|
||||
},
|
||||
{
|
||||
name: 'Google Plus',
|
||||
value: 'googlePlus',
|
||||
},
|
||||
{
|
||||
name: 'LinkedIn',
|
||||
value: 'linkedin',
|
||||
},
|
||||
{
|
||||
name: 'Skype',
|
||||
value: 'skype',
|
||||
},
|
||||
{
|
||||
name: 'Twitter',
|
||||
value: 'twitter',
|
||||
},
|
||||
{
|
||||
name: 'URL',
|
||||
value: 'url',
|
||||
},
|
||||
{
|
||||
name: 'Xing',
|
||||
value: 'xing',
|
||||
},
|
||||
{
|
||||
name: 'YouTube',
|
||||
value: 'youtube',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'URL',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Website URL',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Custom Properties',
|
||||
name: 'customProperties',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Property',
|
||||
name: 'customProperty',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Property name',
|
||||
},
|
||||
{
|
||||
displayName: 'Sub Type',
|
||||
name: 'subtype',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Property sub type',
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'value',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Property value',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* company:delete */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Company ID',
|
||||
name: 'companyId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['delete'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'ID of company to delete',
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* company:update */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Company ID',
|
||||
name: 'companyId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Unique identifier for a particular company',
|
||||
},
|
||||
{
|
||||
displayName: 'JSON Parameters',
|
||||
name: 'jsonParameters',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFieldsJson',
|
||||
type: 'json',
|
||||
typeOptions: {
|
||||
alwaysOpenEditWindow: true,
|
||||
},
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['update'],
|
||||
jsonParameters: [true],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'Object of values to set as described <a href="https://github.com/agilecrm/rest-api#1-companys---companies-api">here</a>',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['company'],
|
||||
operation: ['update'],
|
||||
jsonParameters: [false],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Address',
|
||||
name: 'addressOptions',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
description: 'Company address',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Address Properties',
|
||||
name: 'addressProperties',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Type',
|
||||
name: 'subtype',
|
||||
type: 'options',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Type of address',
|
||||
options: [
|
||||
{
|
||||
name: 'Postal',
|
||||
value: 'postal',
|
||||
},
|
||||
{
|
||||
name: 'Office',
|
||||
value: 'office',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Address',
|
||||
name: 'address',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Full address',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Email',
|
||||
name: 'email',
|
||||
type: 'string',
|
||||
placeholder: 'name@email.com',
|
||||
default: '',
|
||||
description: 'Company email',
|
||||
},
|
||||
{
|
||||
displayName: 'Star Value',
|
||||
name: 'starValue',
|
||||
type: 'options',
|
||||
default: '',
|
||||
description: 'Rating of company (Max value 5). This is not applicable for companies.',
|
||||
options: [
|
||||
{
|
||||
name: '0',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: '1',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: '2',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
name: '3',
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
name: '4',
|
||||
value: 4,
|
||||
},
|
||||
{
|
||||
name: '5',
|
||||
value: 5,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Tags',
|
||||
name: 'tags',
|
||||
type: 'string',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add Tag',
|
||||
},
|
||||
default: [],
|
||||
description:
|
||||
'Unique identifiers added to company, for easy management of companys. This is not applicable for companies.',
|
||||
},
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Company name',
|
||||
},
|
||||
{
|
||||
displayName: 'Phone',
|
||||
name: 'phone',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Company phone',
|
||||
},
|
||||
{
|
||||
displayName: 'Website',
|
||||
name: 'websiteOptions',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
description: 'Companys websites',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Website Properties.',
|
||||
name: 'websiteProperties',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Type',
|
||||
name: 'subtype',
|
||||
type: 'options',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Type of website',
|
||||
options: [
|
||||
{
|
||||
name: 'Facebook',
|
||||
value: 'facebook',
|
||||
},
|
||||
{
|
||||
name: 'Feed',
|
||||
value: 'feed',
|
||||
},
|
||||
{
|
||||
name: 'Flickr',
|
||||
value: 'flickr',
|
||||
},
|
||||
{
|
||||
name: 'Github',
|
||||
value: 'github',
|
||||
},
|
||||
{
|
||||
name: 'Google Plus',
|
||||
value: 'googlePlus',
|
||||
},
|
||||
{
|
||||
name: 'LinkedIn',
|
||||
value: 'linkedin',
|
||||
},
|
||||
{
|
||||
name: 'Skype',
|
||||
value: 'skype',
|
||||
},
|
||||
{
|
||||
name: 'Twitter',
|
||||
value: 'twitter',
|
||||
},
|
||||
{
|
||||
name: 'URL',
|
||||
value: 'url',
|
||||
},
|
||||
{
|
||||
name: 'Xing',
|
||||
value: 'xing',
|
||||
},
|
||||
{
|
||||
name: 'YouTube',
|
||||
value: 'youtube',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'URL',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Website URL',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Custom Properties',
|
||||
name: 'customProperties',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Property',
|
||||
name: 'customProperty',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Property name',
|
||||
},
|
||||
{
|
||||
displayName: 'Sub Type',
|
||||
name: 'subtype',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Property sub type',
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'value',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Property value',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { IDataObject } from 'n8n-workflow';
|
||||
|
||||
export interface IProperty {
|
||||
type: string;
|
||||
name: string;
|
||||
subtype?: string;
|
||||
value?: string;
|
||||
}
|
||||
|
||||
export interface IContact {
|
||||
type?: string;
|
||||
star_value?: string;
|
||||
lead_score?: string;
|
||||
tags?: string[];
|
||||
properties?: IDataObject[];
|
||||
}
|
||||
|
||||
export interface IContactUpdate {
|
||||
id: string;
|
||||
properties?: IDataObject[];
|
||||
star_value?: string;
|
||||
lead_score?: string;
|
||||
tags?: string[];
|
||||
}
|
||||
@@ -0,0 +1,432 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const dealOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a new deal',
|
||||
action: 'Create a deal',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete a deal',
|
||||
action: 'Delete a deal',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a deal',
|
||||
action: 'Get a deal',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many deals',
|
||||
action: 'Get many deals',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update deal properties',
|
||||
action: 'Update a deal',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
export const dealFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* deal:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Deal ID',
|
||||
name: 'dealId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Unique identifier for a particular deal',
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* deal:get all */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
},
|
||||
description: 'Max number of results to return',
|
||||
default: 20,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* deal:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Close Date',
|
||||
name: 'closeDate',
|
||||
type: 'dateTime',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['create'],
|
||||
jsonParameters: [false],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Closing date of deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Expected Value',
|
||||
name: 'expectedValue',
|
||||
type: 'number',
|
||||
required: true,
|
||||
typeOptions: {
|
||||
minValue: 0,
|
||||
maxValue: 1000000000000,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['create'],
|
||||
jsonParameters: [false],
|
||||
},
|
||||
},
|
||||
default: 1,
|
||||
description: 'Expected Value of deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Milestone',
|
||||
name: 'milestone',
|
||||
type: 'string',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['create'],
|
||||
jsonParameters: [false],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Milestone of deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['create'],
|
||||
jsonParameters: [false],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Name of deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Probability',
|
||||
name: 'probability',
|
||||
type: 'number',
|
||||
required: true,
|
||||
typeOptions: {
|
||||
minValue: 0,
|
||||
maxValue: 100,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['create'],
|
||||
jsonParameters: [false],
|
||||
},
|
||||
},
|
||||
default: 50,
|
||||
description: 'Expected probability',
|
||||
},
|
||||
{
|
||||
displayName: 'JSON Parameters',
|
||||
name: 'jsonParameters',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFieldsJson',
|
||||
type: 'json',
|
||||
typeOptions: {
|
||||
alwaysOpenEditWindow: true,
|
||||
},
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['create'],
|
||||
jsonParameters: [true],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'Object of values to set as described <a href="https://github.com/agilecrm/rest-api#1-deals---companies-api">here</a>',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['create'],
|
||||
jsonParameters: [false],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Contact IDs',
|
||||
name: 'contactIds',
|
||||
type: 'string',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add ID',
|
||||
},
|
||||
default: [],
|
||||
description: 'Unique contact identifiers',
|
||||
},
|
||||
{
|
||||
displayName: 'Custom Data',
|
||||
name: 'customData',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Property',
|
||||
name: 'customProperty',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Property name',
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'value',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Property value',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* deal:delete */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Deal ID',
|
||||
name: 'dealId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['delete'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'ID of deal to delete',
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* deal:update */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Deal ID',
|
||||
name: 'dealId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'ID of deal to update',
|
||||
},
|
||||
{
|
||||
displayName: 'JSON Parameters',
|
||||
name: 'jsonParameters',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFieldsJson',
|
||||
type: 'json',
|
||||
typeOptions: {
|
||||
alwaysOpenEditWindow: true,
|
||||
},
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['update'],
|
||||
jsonParameters: [true],
|
||||
},
|
||||
},
|
||||
|
||||
description:
|
||||
'Object of values to set as described <a href="https://github.com/agilecrm/rest-api#1-deals---companies-api">here</a>',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['deal'],
|
||||
operation: ['update'],
|
||||
jsonParameters: [false],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Expected Value',
|
||||
name: 'expectedValue',
|
||||
type: 'number',
|
||||
typeOptions: {
|
||||
minValue: 0,
|
||||
maxValue: 10000,
|
||||
},
|
||||
default: '',
|
||||
description: 'Expected Value of deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Name of deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Probability',
|
||||
name: 'probability',
|
||||
type: 'number',
|
||||
typeOptions: {
|
||||
minValue: 0,
|
||||
maxValue: 100,
|
||||
},
|
||||
default: 50,
|
||||
description: 'Expected Value of deal',
|
||||
},
|
||||
{
|
||||
displayName: 'Contact IDs',
|
||||
name: 'contactIds',
|
||||
type: 'string',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add ID',
|
||||
},
|
||||
default: [],
|
||||
description: 'Unique contact identifiers',
|
||||
},
|
||||
{
|
||||
displayName: 'Custom Data',
|
||||
name: 'customData',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Property',
|
||||
name: 'customProperty',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Property name',
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'value',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Property value',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,15 @@
|
||||
export interface IDealCustomProperty {
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface IDeal {
|
||||
id?: number;
|
||||
expected_value?: number;
|
||||
probability?: number;
|
||||
name?: string;
|
||||
close_date?: number;
|
||||
milestone?: string;
|
||||
contactIds?: string[];
|
||||
customData?: IDealCustomProperty[];
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
export interface ISearchConditions {
|
||||
field?: string;
|
||||
condition_type?: string;
|
||||
value?: string;
|
||||
value2?: string;
|
||||
}
|
||||
|
||||
export interface IFilterRules {
|
||||
LHS?: string;
|
||||
CONDITION?: string;
|
||||
RHS?: string;
|
||||
RHS_NEW?: string;
|
||||
}
|
||||
|
||||
export interface IFilter {
|
||||
or_rules?: IFilterRules;
|
||||
rules?: IFilterRules;
|
||||
contact_type?: string;
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
import type {
|
||||
IDataObject,
|
||||
IExecuteFunctions,
|
||||
IHookFunctions,
|
||||
ILoadOptionsFunctions,
|
||||
JsonObject,
|
||||
IRequestOptions,
|
||||
IHttpRequestMethods,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeApiError } from 'n8n-workflow';
|
||||
|
||||
import type { IContactUpdate } from './ContactInterface';
|
||||
import type { IFilterRules, ISearchConditions } from './FilterInterface';
|
||||
|
||||
export async function agileCrmApiRequest(
|
||||
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
endpoint: string,
|
||||
body: any = {},
|
||||
query: IDataObject = {},
|
||||
uri?: string,
|
||||
sendAsForm?: boolean,
|
||||
): Promise<any> {
|
||||
const credentials = await this.getCredentials('agileCrmApi');
|
||||
const options: IRequestOptions = {
|
||||
method,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
},
|
||||
auth: {
|
||||
username: credentials.email as string,
|
||||
password: credentials.apiKey as string,
|
||||
},
|
||||
qs: query,
|
||||
uri: uri || `https://${credentials.subdomain}.agilecrm.com/dev/${endpoint}`,
|
||||
json: true,
|
||||
};
|
||||
|
||||
// To send the request as 'content-type': 'application/x-www-form-urlencoded' add form to options instead of body
|
||||
if (sendAsForm) {
|
||||
options.form = body;
|
||||
}
|
||||
// Only add Body property if method not GET or DELETE to avoid 400 response
|
||||
// And when not sending a form
|
||||
else if (method !== 'GET' && method !== 'DELETE') {
|
||||
options.body = body;
|
||||
}
|
||||
|
||||
try {
|
||||
return await this.helpers.request(options);
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
}
|
||||
|
||||
export async function agileCrmApiRequestAllItems(
|
||||
this: IHookFunctions | ILoadOptionsFunctions | IExecuteFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
resource: string,
|
||||
body: any = {},
|
||||
query: IDataObject = {},
|
||||
uri?: string,
|
||||
sendAsForm?: boolean,
|
||||
): Promise<any> {
|
||||
// https://github.com/agilecrm/rest-api#11-listing-contacts-
|
||||
|
||||
const returnData: IDataObject[] = [];
|
||||
let responseData;
|
||||
do {
|
||||
responseData = await agileCrmApiRequest.call(
|
||||
this,
|
||||
method,
|
||||
resource,
|
||||
body,
|
||||
query,
|
||||
uri,
|
||||
sendAsForm,
|
||||
);
|
||||
if (responseData.length !== 0) {
|
||||
returnData.push.apply(returnData, responseData as IDataObject[]);
|
||||
if (sendAsForm) {
|
||||
body.cursor = responseData[responseData.length - 1].cursor;
|
||||
} else {
|
||||
query.cursor = responseData[responseData.length - 1].cursor;
|
||||
}
|
||||
}
|
||||
} while (
|
||||
responseData.length !== 0 &&
|
||||
responseData[responseData.length - 1].hasOwnProperty('cursor')
|
||||
);
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
||||
export async function agileCrmApiRequestUpdate(
|
||||
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions,
|
||||
method: IHttpRequestMethods = 'PUT',
|
||||
_endpoint?: string,
|
||||
body: any = {},
|
||||
_query: IDataObject = {},
|
||||
uri?: string,
|
||||
): Promise<any> {
|
||||
const credentials = await this.getCredentials('agileCrmApi');
|
||||
const baseUri = `https://${credentials.subdomain}.agilecrm.com/dev/`;
|
||||
const options: IRequestOptions = {
|
||||
method,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
},
|
||||
body: { id: body.id },
|
||||
auth: {
|
||||
username: credentials.email as string,
|
||||
password: credentials.apiKey as string,
|
||||
},
|
||||
uri: uri || baseUri,
|
||||
json: true,
|
||||
};
|
||||
|
||||
const successfulUpdates = [];
|
||||
let lastSuccesfulUpdateReturn: any;
|
||||
const payload: IContactUpdate = body;
|
||||
|
||||
try {
|
||||
// Due to API, we must update each property separately. For user it looks like one seamless update
|
||||
if (payload.properties) {
|
||||
options.body.properties = payload.properties;
|
||||
options.uri = baseUri + 'api/contacts/edit-properties';
|
||||
lastSuccesfulUpdateReturn = await this.helpers.request(options);
|
||||
|
||||
// Iterate trough properties and show them as individial updates instead of only vague "properties"
|
||||
payload.properties?.map((property: any) => {
|
||||
successfulUpdates.push(`${property.name}`);
|
||||
});
|
||||
|
||||
delete options.body.properties;
|
||||
}
|
||||
if (payload.lead_score) {
|
||||
options.body.lead_score = payload.lead_score;
|
||||
options.uri = baseUri + 'api/contacts/edit/lead-score';
|
||||
lastSuccesfulUpdateReturn = await this.helpers.request(options);
|
||||
|
||||
successfulUpdates.push('lead_score');
|
||||
|
||||
delete options.body.lead_score;
|
||||
}
|
||||
if (body.tags) {
|
||||
options.body.tags = payload.tags;
|
||||
options.uri = baseUri + 'api/contacts/edit/tags';
|
||||
lastSuccesfulUpdateReturn = await this.helpers.request(options);
|
||||
|
||||
payload.tags?.map((tag: string) => {
|
||||
successfulUpdates.push(`(Tag) ${tag}`);
|
||||
});
|
||||
|
||||
delete options.body.tags;
|
||||
}
|
||||
if (body.star_value) {
|
||||
options.body.star_value = payload.star_value;
|
||||
options.uri = baseUri + 'api/contacts/edit/add-star';
|
||||
lastSuccesfulUpdateReturn = await this.helpers.request(options);
|
||||
|
||||
successfulUpdates.push('star_value');
|
||||
|
||||
delete options.body.star_value;
|
||||
}
|
||||
|
||||
return lastSuccesfulUpdateReturn;
|
||||
} catch (error) {
|
||||
if (successfulUpdates.length === 0) {
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
} else {
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject, {
|
||||
message: `Not all properties updated. Updated properties: ${successfulUpdates.join(', ')}`,
|
||||
description: error.message,
|
||||
httpCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function validateJSON(json: string | undefined): any {
|
||||
let result;
|
||||
try {
|
||||
result = JSON.parse(json!);
|
||||
} catch (exception) {
|
||||
result = undefined;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getFilterRules(conditions: ISearchConditions[], matchType: string): IDataObject {
|
||||
const rules = [];
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-for-in-array
|
||||
for (const key in conditions) {
|
||||
if (conditions.hasOwnProperty(key)) {
|
||||
const searchConditions: ISearchConditions = conditions[key];
|
||||
const rule: IFilterRules = {
|
||||
LHS: searchConditions.field,
|
||||
CONDITION: searchConditions.condition_type,
|
||||
RHS: searchConditions.value as string,
|
||||
RHS_NEW: searchConditions.value2 as string,
|
||||
};
|
||||
rules.push(rule);
|
||||
}
|
||||
}
|
||||
|
||||
if (matchType === 'anyFilter') {
|
||||
return {
|
||||
or_rules: rules,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
rules,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function simplifyResponse(
|
||||
records: [{ id: string; properties: [{ name: string; value: string }] }],
|
||||
) {
|
||||
const results = [];
|
||||
for (const record of records) {
|
||||
results.push(
|
||||
record.properties.reduce(
|
||||
(obj, value) => Object.assign(obj, { [`${value.name}`]: value.value }),
|
||||
{ id: record.id },
|
||||
),
|
||||
);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.aiTransform",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"details": "Modify data by writing a prompt",
|
||||
"categories": ["Development", "Core Nodes"],
|
||||
"resources": {
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.aitransform/"
|
||||
}
|
||||
]
|
||||
},
|
||||
"alias": ["code", "Javascript", "JS", "Script", "Custom Code", "Function", "AI", "LLM"],
|
||||
"subcategories": {
|
||||
"Core Nodes": ["Data Transformation"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
import {
|
||||
NodeOperationError,
|
||||
NodeConnectionTypes,
|
||||
type IExecuteFunctions,
|
||||
type INodeType,
|
||||
type INodeTypeDescription,
|
||||
type INode,
|
||||
AI_TRANSFORM_CODE_GENERATED_FOR_PROMPT,
|
||||
AI_TRANSFORM_JS_CODE,
|
||||
ensureError,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { JsTaskRunnerSandbox } from '../Code/JsTaskRunnerSandbox';
|
||||
|
||||
export class AiTransform implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'AI Transform',
|
||||
name: 'aiTransform',
|
||||
icon: 'file:aitransform.svg',
|
||||
group: ['transform'],
|
||||
version: 1,
|
||||
description: 'Modify data based on instructions written in plain english',
|
||||
defaults: {
|
||||
name: 'AI Transform',
|
||||
},
|
||||
inputs: [NodeConnectionTypes.Main],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
parameterPane: 'wide',
|
||||
hints: [
|
||||
{
|
||||
message:
|
||||
"This node doesn't have access to the contents of binary files. To use those contents here, use the 'Extract from File' node first.",
|
||||
displayCondition: '={{ $input.all().some(i => i.binary) }}',
|
||||
location: 'outputPane',
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Instructions',
|
||||
name: 'instructions',
|
||||
type: 'button',
|
||||
default: '',
|
||||
description:
|
||||
"Provide instructions on how you want to transform the data, then click 'Generate code'. Use dot notation to refer to nested fields (e.g. address.street).",
|
||||
placeholder:
|
||||
"Example: Merge 'firstname' and 'lastname' into a field 'details.name' and sort by 'email'",
|
||||
typeOptions: {
|
||||
buttonConfig: {
|
||||
label: 'Generate code',
|
||||
hasInputField: true,
|
||||
inputFieldMaxLength: 500,
|
||||
action: {
|
||||
type: 'askAiCodeGeneration',
|
||||
target: AI_TRANSFORM_JS_CODE,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Code Generated For Prompt',
|
||||
name: AI_TRANSFORM_CODE_GENERATED_FOR_PROMPT,
|
||||
type: 'hidden',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Generated JavaScript',
|
||||
name: AI_TRANSFORM_JS_CODE,
|
||||
type: 'string',
|
||||
typeOptions: {
|
||||
editor: 'jsEditor',
|
||||
editorIsReadOnly: true,
|
||||
},
|
||||
default: '',
|
||||
hint: 'Read-only. To edit this code, adjust the instructions or copy and paste it into a Code node.',
|
||||
noDataExpression: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions) {
|
||||
const workflowMode = this.getMode();
|
||||
const node = this.getNode();
|
||||
const code = getValidatedCode(this, node);
|
||||
|
||||
const sandbox = new JsTaskRunnerSandbox(workflowMode, this);
|
||||
return [await sandbox.runCodeAllItems(code)];
|
||||
}
|
||||
}
|
||||
|
||||
function getValidatedCode(executeFunctions: IExecuteFunctions, node: INode): string {
|
||||
try {
|
||||
const code = executeFunctions.getNodeParameter(AI_TRANSFORM_JS_CODE, 0) as string;
|
||||
if (code) {
|
||||
return code;
|
||||
}
|
||||
|
||||
const instructions = executeFunctions.getNodeParameter('instructions', 0) as string;
|
||||
if (!instructions) {
|
||||
throw new NodeOperationError(node, 'Missing instructions to generate code', {
|
||||
description: "Enter your prompt in the 'Instructions' parameter and click 'Generate code'",
|
||||
});
|
||||
}
|
||||
throw new NodeOperationError(node, 'Missing code for data transformation', {
|
||||
description: "Click the 'Generate code' button to create the code",
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof NodeOperationError) throw error;
|
||||
|
||||
throw new NodeOperationError(node, ensureError(error));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M39.4956 19.5195L34.8 18.006C31.7965 17.015 30.0369 14.5846 29.2111 11.5306L27.1447 1.46518C27.0908 1.2663 26.9593 1 26.5548 1C26.2144 1 26.0188 1.2663 25.9649 1.46518L23.8986 11.534C23.0693 14.588 21.3131 17.0184 18.3097 18.0094L13.6141 19.5229C12.95 19.7386 12.9399 20.6757 13.6006 20.9016L18.3299 22.5297C21.3232 23.5241 23.0693 25.9512 23.8986 28.9917L25.9683 38.9458C26.0222 39.1447 26.1335 39.502 26.5582 39.502C26.9977 39.502 27.0906 39.1585 27.1449 38.9577L27.1481 38.9458L29.2178 28.9917C30.047 25.9478 31.7931 23.5208 34.7865 22.5297L39.5158 20.9016C40.1697 20.6724 40.1596 19.7353 39.4956 19.5195ZM12.6028 28.277C9.82036 27.3584 9.54358 26.324 9.07959 24.5899L9.06681 24.5421L7.89038 20.4162C7.81959 20.1499 7.12519 20.1499 7.05103 20.4162L6.25214 24.2286C5.77684 25.9848 4.76558 27.3804 3.0397 27.9501L0.289074 29.1433C-0.0918337 29.2681 -0.0985755 29.8074 0.282332 29.9355L3.05318 30.9164C4.77233 31.4861 5.77684 32.8816 6.25551 34.6311L7.0544 38.2784C7.12856 38.5447 7.81959 38.5447 7.89038 38.2784L8.82748 34.648C9.30277 32.8884 10.0309 31.4895 12.3669 30.9164L14.9692 29.9355C15.3501 29.804 15.3467 29.2647 14.9625 29.14L12.6028 28.277ZM13.3255 2.03231C13.4169 1.65456 13.954 1.64852 14.0473 2.02833L14.0475 2.02889L15.0714 6.25591C15.2111 6.74054 15.5906 7.11618 16.0783 7.2487L18.6822 7.95026C19.0346 8.04918 19.0457 8.54279 18.7009 8.65979L18.7004 8.65996L15.97 9.57684C15.531 9.72415 15.1905 10.0756 15.0538 10.5179L14.0473 14.4327L14.0471 14.4337C13.9524 14.8153 13.4207 14.7996 13.3291 14.4333L12.3559 10.5303C12.2222 10.0878 11.8845 9.73333 11.4489 9.58314L8.72013 8.63869C8.37299 8.51471 8.40082 8.02141 8.75078 7.92932L8.75135 7.92917L11.3368 7.25837C11.8372 7.12876 12.2283 6.74382 12.3616 6.24505L13.3255 2.03231Z" fill="url(#paint0_linear_1373_20357)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_1373_20357" x1="0" y1="1" x2="47.0035" y2="13.8158" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#5B60E8"/>
|
||||
<stop offset="0.5" stop-color="#AA7BEC"/>
|
||||
<stop offset="1" stop-color="#EC7B8E"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.airtable",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Data & Storage"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/airtable/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.airtable/"
|
||||
}
|
||||
],
|
||||
"generic": [
|
||||
{
|
||||
"label": "2021 Goals: Level Up Your Vocabulary With Vonage and n8n",
|
||||
"icon": "🎯",
|
||||
"url": "https://n8n.io/blog/2021-goals-level-up-your-vocabulary-with-vonage-and-n8n/"
|
||||
},
|
||||
{
|
||||
"label": "2021: The Year to Automate the New You with n8n",
|
||||
"icon": "☀️",
|
||||
"url": "https://n8n.io/blog/2021-the-year-to-automate-the-new-you-with-n8n/"
|
||||
},
|
||||
{
|
||||
"label": "How to build a low-code, self-hosted URL shortener in 3 steps",
|
||||
"icon": "🔗",
|
||||
"url": "https://n8n.io/blog/how-to-build-a-low-code-self-hosted-url-shortener/"
|
||||
},
|
||||
{
|
||||
"label": "How to get started with CRM automation (with 3 no-code workflow ideas",
|
||||
"icon": "👥",
|
||||
"url": "https://n8n.io/blog/how-to-get-started-with-crm-automation-and-no-code-workflow-ideas/"
|
||||
},
|
||||
{
|
||||
"label": "15 Google apps you can combine and automate to increase productivity",
|
||||
"icon": "💡",
|
||||
"url": "https://n8n.io/blog/automate-google-apps-for-productivity/"
|
||||
},
|
||||
{
|
||||
"label": "Building an expense tracking app in 10 minutes",
|
||||
"icon": "📱",
|
||||
"url": "https://n8n.io/blog/building-an-expense-tracking-app-in-10-minutes/"
|
||||
},
|
||||
{
|
||||
"label": "Why this Product Manager loves workflow automation with n8n",
|
||||
"icon": "🧠",
|
||||
"url": "https://n8n.io/blog/why-this-product-manager-loves-workflow-automation-with-n8n/"
|
||||
},
|
||||
{
|
||||
"label": "Learn to Build Powerful API Endpoints Using Webhooks",
|
||||
"icon": "🧰",
|
||||
"url": "https://n8n.io/blog/learn-to-build-powerful-api-endpoints-using-webhooks/"
|
||||
},
|
||||
{
|
||||
"label": "Sending SMS the Low-Code Way with Airtable, Twilio Programmable SMS, and n8n",
|
||||
"icon": "📱",
|
||||
"url": "https://n8n.io/blog/sending-sms-the-low-code-way-with-airtable-twilio-programmable-sms-and-n8n/"
|
||||
},
|
||||
{
|
||||
"label": "Automating Conference Organization Processes with n8n",
|
||||
"icon": "🙋♀️",
|
||||
"url": "https://n8n.io/blog/automating-conference-organization-processes-with-n8n/"
|
||||
},
|
||||
{
|
||||
"label": "Benefits of automation and n8n: An interview with HubSpot's Hugh Durkin",
|
||||
"icon": "🎖",
|
||||
"url": "https://n8n.io/blog/benefits-of-automation-and-n8n-an-interview-with-hubspots-hugh-durkin/"
|
||||
},
|
||||
{
|
||||
"label": "How Goomer automated their operations with over 200 n8n workflows",
|
||||
"icon": "🛵",
|
||||
"url": "https://n8n.io/blog/how-goomer-automated-their-operations-with-over-200-n8n-workflows/"
|
||||
},
|
||||
{
|
||||
"label": "7 no-code workflow automations for Amazon Web Services",
|
||||
"url": "https://n8n.io/blog/aws-workflow-automation/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import type { INodeTypeBaseDescription, IVersionedNodeType } from 'n8n-workflow';
|
||||
import { VersionedNodeType } from 'n8n-workflow';
|
||||
|
||||
import { AirtableV1 } from './v1/AirtableV1.node';
|
||||
import { AirtableV2 } from './v2/AirtableV2.node';
|
||||
|
||||
export class Airtable extends VersionedNodeType {
|
||||
constructor() {
|
||||
const baseDescription: INodeTypeBaseDescription = {
|
||||
displayName: 'Airtable',
|
||||
name: 'airtable',
|
||||
icon: 'file:airtable.svg',
|
||||
group: ['input'],
|
||||
description: 'Read, update, write and delete data from Airtable',
|
||||
defaultVersion: 2.1,
|
||||
};
|
||||
|
||||
const nodeVersions: IVersionedNodeType['nodeVersions'] = {
|
||||
1: new AirtableV1(baseDescription),
|
||||
2: new AirtableV2(baseDescription),
|
||||
2.1: new AirtableV2(baseDescription),
|
||||
};
|
||||
|
||||
super(nodeVersions, baseDescription);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.airtableTrigger",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Data & Storage"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/airtable/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.airtabletrigger/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
import moment from 'moment-timezone';
|
||||
import type {
|
||||
IPollFunctions,
|
||||
IDataObject,
|
||||
INodeExecutionData,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';
|
||||
|
||||
import type { IRecord } from './v1/GenericFunctions';
|
||||
import { apiRequestAllItems, downloadRecordAttachments } from './v1/GenericFunctions';
|
||||
|
||||
export class AirtableTrigger implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Airtable Trigger',
|
||||
name: 'airtableTrigger',
|
||||
icon: 'file:airtable.svg',
|
||||
group: ['trigger'],
|
||||
version: 1,
|
||||
description: 'Starts the workflow when Airtable events occur',
|
||||
subtitle: '={{$parameter["event"]}}',
|
||||
defaults: {
|
||||
name: 'Airtable Trigger',
|
||||
},
|
||||
credentials: [
|
||||
{
|
||||
name: 'airtableApi',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authentication: ['airtableApi'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'airtableTokenApi',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authentication: ['airtableTokenApi'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'airtableOAuth2Api',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authentication: ['airtableOAuth2Api'],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
polling: true,
|
||||
inputs: [],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Authentication',
|
||||
name: 'authentication',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'API Key',
|
||||
value: 'airtableApi',
|
||||
},
|
||||
{
|
||||
name: 'Access Token',
|
||||
value: 'airtableTokenApi',
|
||||
},
|
||||
{
|
||||
name: 'OAuth2',
|
||||
value: 'airtableOAuth2Api',
|
||||
},
|
||||
],
|
||||
default: 'airtableApi',
|
||||
},
|
||||
{
|
||||
displayName: 'Base',
|
||||
name: 'baseId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'url', value: '' },
|
||||
required: true,
|
||||
description: 'The Airtable Base in which to operate on',
|
||||
modes: [
|
||||
{
|
||||
displayName: 'By URL',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder: 'https://airtable.com/app12DiScdfes/tblAAAAAAAAAAAAA/viwHdfasdfeieg5p',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: 'https://airtable.com/([a-zA-Z0-9]{2,})/.*',
|
||||
errorMessage: 'Not a valid Airtable Base URL',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: 'https://airtable.com/([a-zA-Z0-9]{2,})',
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: '[a-zA-Z0-9]{2,}',
|
||||
errorMessage: 'Not a valid Airtable Base ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
placeholder: 'appD3dfaeidke',
|
||||
url: '=https://airtable.com/{{$value}}',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Table',
|
||||
name: 'tableId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'url', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'By URL',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder: 'https://airtable.com/app12DiScdfes/tblAAAAAAAAAAAAA/viwHdfasdfeieg5p',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: 'https://airtable.com/[a-zA-Z0-9]{2,}/([a-zA-Z0-9]{2,})/.*',
|
||||
errorMessage: 'Not a valid Airtable Table URL',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: 'https://airtable.com/[a-zA-Z0-9]{2,}/([a-zA-Z0-9]{2,})',
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: '[a-zA-Z0-9]{2,}',
|
||||
errorMessage: 'Not a valid Airtable Table ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
placeholder: 'tbl3dirwqeidke',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Trigger Field',
|
||||
name: 'triggerField',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'A Created Time or Last Modified Time field that will be used to sort records. If you do not have a Created Time or Last Modified Time field in your schema, please create one, because without this field trigger will not work correctly.',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Download Attachments',
|
||||
name: 'downloadAttachments',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: "Whether the attachment fields define in 'Download Fields' will be downloaded",
|
||||
},
|
||||
{
|
||||
displayName: 'Download Fields',
|
||||
name: 'downloadFieldNames',
|
||||
type: 'string',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
downloadAttachments: [true],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
"Name of the fields of type 'attachment' that should be downloaded. Multiple ones can be defined separated by comma. Case sensitive.",
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Fields',
|
||||
name: 'fields',
|
||||
type: 'string',
|
||||
requiresDataPath: 'multiple',
|
||||
default: '',
|
||||
// eslint-disable-next-line n8n-nodes-base/node-param-description-miscased-id
|
||||
description:
|
||||
'Fields to be included in the response. Multiple ones can be set separated by comma. Example: <code>name, id</code>. By default just the trigger field will be included.',
|
||||
},
|
||||
{
|
||||
displayName: 'Formula',
|
||||
name: 'formula',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'Formulas may involve functions, numeric operations, logical operations, and text operations that operate on fields. More info <a href="https://support.airtable.com/hc/en-us/articles/203255215-Formula-Field-Reference">here</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'View ID',
|
||||
name: 'viewId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'The name or ID of a view in the table. If set, only the records in that view will be returned.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
async poll(this: IPollFunctions): Promise<INodeExecutionData[][] | null> {
|
||||
const downloadAttachments = this.getNodeParameter('downloadAttachments', 0) as boolean;
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
const additionalFields = this.getNodeParameter('additionalFields') as IDataObject;
|
||||
const base = this.getNodeParameter('baseId', '', { extractValue: true }) as string;
|
||||
const table = this.getNodeParameter('tableId', '', { extractValue: true }) as string;
|
||||
const triggerField = this.getNodeParameter('triggerField') as string;
|
||||
|
||||
const qs: IDataObject = {};
|
||||
|
||||
const endpoint = `${base}/${table}`;
|
||||
|
||||
const now = moment().utc().format();
|
||||
|
||||
const startDate = (webhookData.lastTimeChecked as string) || now;
|
||||
|
||||
const endDate = now;
|
||||
|
||||
if (additionalFields.viewId) {
|
||||
qs.view = additionalFields.viewId;
|
||||
}
|
||||
|
||||
if (additionalFields.fields) {
|
||||
qs['fields[]'] = (additionalFields.fields as string).split(',');
|
||||
}
|
||||
|
||||
qs.filterByFormula = `IS_AFTER({${triggerField}}, DATETIME_PARSE("${startDate}", "YYYY-MM-DD HH:mm:ss"))`;
|
||||
|
||||
if (additionalFields.formula) {
|
||||
qs.filterByFormula = `AND(${qs.filterByFormula}, ${additionalFields.formula})`;
|
||||
}
|
||||
|
||||
if (this.getMode() === 'manual') {
|
||||
delete qs.filterByFormula;
|
||||
qs.maxRecords = 1;
|
||||
}
|
||||
|
||||
const { records } = await apiRequestAllItems.call(this, 'GET', endpoint, {}, qs);
|
||||
|
||||
webhookData.lastTimeChecked = endDate;
|
||||
|
||||
if (Array.isArray(records) && records.length) {
|
||||
if (this.getMode() === 'manual' && records[0].fields[triggerField] === undefined) {
|
||||
throw new NodeOperationError(this.getNode(), `The Field "${triggerField}" does not exist.`);
|
||||
}
|
||||
|
||||
if (downloadAttachments) {
|
||||
const downloadFieldNames = (this.getNodeParameter('downloadFieldNames', 0) as string).split(
|
||||
',',
|
||||
);
|
||||
const data = await downloadRecordAttachments.call(
|
||||
this,
|
||||
records as IRecord[],
|
||||
downloadFieldNames,
|
||||
);
|
||||
return [data];
|
||||
}
|
||||
|
||||
return [this.helpers.returnJsonArray(records)];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 170"><path fill="#fcb400" d="M89 4.8 16.2 34.9c-4.1 1.7-4 7.4.1 9.1l73.2 29c6.4 2.6 13.6 2.6 20 0l73.2-29c4.1-1.6 4.1-7.4.1-9.1l-73-30.1C103.2 2 95.7 2 89 4.8"/><path fill="#18bfff" d="M105.9 88.9v72.5c0 3.4 3.5 5.8 6.7 4.5l81.6-31.7c1.9-.7 3.1-2.5 3.1-4.5V57.2c0-3.4-3.5-5.8-6.7-4.5L109 84.3c-1.9.8-3.1 2.6-3.1 4.6"/><path fill="#f82b60" d="m86.9 92.6-24.2 11.7-2.5 1.2L9.1 130c-3.2 1.6-7.4-.8-7.4-4.4V57.5c0-1.3.7-2.4 1.6-3.3q.6-.6 1.2-.9c1.2-.7 3-.9 4.4-.3l77.5 30.7c4 1.5 4.3 7.1.5 8.9"/><path fill="#ba1e45" d="m86.9 92.6-24.2 11.7-59.4-50q.6-.6 1.2-.9c1.2-.7 3-.9 4.4-.3l77.5 30.7c4 1.4 4.3 7 .5 8.8"/></svg>
|
||||
|
After Width: | Height: | Size: 671 B |
@@ -0,0 +1,34 @@
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
import type { WorkflowTestData } from 'n8n-workflow';
|
||||
import nock from 'nock';
|
||||
|
||||
const record = {
|
||||
id: 'rec2BWBoyS5QsS7pT',
|
||||
name: 'Tim',
|
||||
email: 'tim@email.com',
|
||||
createdTime: '2022-08-25T08:22:34.000Z',
|
||||
};
|
||||
|
||||
describe('Execute Airtable Node', () => {
|
||||
const testHarness = new NodeTestHarness();
|
||||
|
||||
beforeEach(() => {
|
||||
nock('https://api.airtable.com/v0')
|
||||
.get('/appIaXXdDqS5ORr4V/tbljyBEdYzCPF0NDh/rec2BWBoyS5QsS7pT')
|
||||
.reply(200, record);
|
||||
});
|
||||
|
||||
const testData: WorkflowTestData = {
|
||||
description: 'List Airtable Records',
|
||||
input: {
|
||||
workflowData: testHarness.readWorkflowJSON('workflow.json'),
|
||||
},
|
||||
output: {
|
||||
nodeData: {
|
||||
Airtable: [[{ json: record }]],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
testHarness.setupTest(testData, { credentials: { airtableTokenApi: {} } });
|
||||
});
|
||||