🔀 Merge branch 'feature/affinity' of https://github.com/RicardoE105/n8n into RicardoE105-feature/affinity

This commit is contained in:
Jan Oberhauser 2020-03-03 15:15:16 +01:00
commit 34d6d001d3
10 changed files with 1365 additions and 1 deletions

View file

@ -0,0 +1,17 @@
import {
ICredentialType,
NodePropertyTypes,
} from 'n8n-workflow';
export class AffinityApi implements ICredentialType {
name = 'affinityApi';
displayName = 'Affinity API';
properties = [
{
displayName: 'API Key',
name: 'apiKey',
type: 'string' as NodePropertyTypes,
default: '',
},
];
}

View file

@ -0,0 +1,267 @@
import {
IExecuteFunctions,
} from 'n8n-core';
import {
IDataObject,
ILoadOptionsFunctions,
INodeTypeDescription,
INodeExecutionData,
INodeType,
INodePropertyOptions,
} from 'n8n-workflow';
import {
affinityApiRequest,
affinityApiRequestAllItems,
} from './GenericFunctions';
import {
organizationFields,
organizationOperations,
} from './OrganizationDescription';
import {
personFields,
personOperations,
} from './PersonDescription';
import {
IOrganization,
} from './OrganizationInterface';
import {
IPerson,
} from './PersonInterface';
import { snakeCase } from 'change-case';
export class Affinity implements INodeType {
description: INodeTypeDescription = {
displayName: 'Affinity',
name: 'affinity',
icon: 'file:affinity.png',
group: ['output'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Consume Affinity API',
defaults: {
name: 'Affinity',
color: '#3343df',
},
inputs: ['main'],
outputs: ['main'],
credentials: [
{
name: 'affinityApi',
required: true,
}
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
options: [
{
name: 'Organization',
value: 'organization',
},
{
name: 'Person',
value: 'person',
},
],
default: 'organization',
description: 'Resource to consume.',
},
...organizationOperations,
...organizationFields,
...personOperations,
...personFields,
],
};
methods = {
loadOptions: {
// Get all the available organizations to display them to user so that he 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 he 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;
},
},
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
const returnData: IDataObject[] = [];
const length = items.length as unknown as number;
let responseData;
const qs: IDataObject = {};
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
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) as IDataObject;
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) as IDataObject;
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) as IDataObject;
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) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.term) {
qs.term = options.term as string;
}
if (options.withInteractionDates) {
qs.with_interaction_dates = options.withInteractionDates as boolean;
}
if (returnAll === true) {
responseData = await affinityApiRequestAllItems.call(this, 'persons', 'GET', '/persons', {}, qs);
} else {
qs.page_size = this.getNodeParameter('limit', i) as number;
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) as IDataObject;
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) as IDataObject;
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) as IDataObject;
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) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.term) {
qs.term = options.term as string;
}
if (options.withInteractionDates) {
qs.with_interaction_dates = options.withInteractionDates as boolean;
}
if (returnAll === true) {
responseData = await affinityApiRequestAllItems.call(this, 'organizations', 'GET', '/organizations', {}, qs);
} else {
qs.page_size = this.getNodeParameter('limit', i) as number;
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);
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
}
return [this.helpers.returnJsonArray(returnData)];
}
}

View file

@ -0,0 +1,273 @@
import {
IHookFunctions,
IWebhookFunctions,
} from 'n8n-core';
import {
INodeTypeDescription,
INodeType,
IWebhookResponseData,
IDataObject,
} from 'n8n-workflow';
import {
affinityApiRequest,
eventsExist,
mapResource,
} from './GenericFunctions';
export class AffinityTrigger implements INodeType {
description: INodeTypeDescription = {
displayName: 'Affinity Trigger',
name: 'affinityTrigger',
icon: 'file:affinity.png',
group: ['trigger'],
version: 1,
description: 'Handle Affinity events via webhooks',
defaults: {
name: 'Affinity Trigger',
color: '#3343df',
},
inputs: [],
outputs: ['main'],
credentials: [
{
name: 'affinityApi',
required: true,
},
],
webhooks: [
{
name: 'default',
httpMethod: 'POST',
responseMode: 'onReceived',
path: 'webhook',
},
],
properties: [
{
displayName: 'Events',
name: 'events',
type: 'multiOptions',
options: [
{
name: 'file.created',
value: 'file.deleted',
},
{
name: 'file.created',
value: 'file.deleted',
},
{
name: 'field_value.created',
value: 'field_value.created',
},
{
name: 'field_value.updated',
value: 'field_value.updated',
},
{
name: 'field_value.deleted',
value: 'field_value.deleted',
},
{
name: 'field.created',
value: 'field.created',
},
{
name: 'field.updated',
value: 'field.updated',
},
{
name: 'field.deleted',
value: 'field.deleted',
},
{
name: 'list.created',
value: 'list.created',
},
{
name: 'list.updated',
value: 'list.updated',
},
{
name: 'list.deleted',
value: 'list.deleted',
},
{
name: 'list_entry.created',
value: 'list_entry.created',
},
{
name: 'list_entry.updated',
value: 'list_entry.updated',
},
{
name: 'list_entry.deleted',
value: 'list_entry.deleted',
},
{
name: 'note.created',
value: 'note.created',
},
{
name: 'note.updated',
value: 'note.updated',
},
{
name: 'note.deleted',
value: 'note.deleted',
},
{
name: 'organization.created',
value: 'organization.created',
},
{
name: 'organization.updated',
value: 'organization.updated',
},
{
name: 'organization.deleted',
value: 'organization.deleted',
},
{
name: 'opportunity.created',
value: 'opportunity.created',
},
{
name: 'opportunity.updated',
value: 'opportunity.updated',
},
{
name: 'opportunity.deleted',
value: 'organization.deleted',
},
{
name: 'person.created',
value: 'person.created',
},
{
name: 'person.updated',
value: 'person.updated',
},
{
name: 'person.deleted',
value: 'person.deleted',
},
],
default: [],
required: true,
description: 'Webhook events that will be enabled for that endpoint.',
},
{
displayName: 'Resolve Data',
name: 'resolveData',
type: 'boolean',
default: true,
description: 'By default does the webhook-data only contain the ID of the object.<br />If this option gets activated it will resolve the data automatically.',
},
],
};
// @ts-ignore (because of request)
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, 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');
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 registred anymore
delete webhookData.webhookId;
}
return true;
},
},
};
async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
const bodyData = this.getBodyData();
const resolveData = this.getNodeParameter('resolveData', false) as boolean;
if (bodyData.type === 'sample.webhook') {
return {}
}
if (resolveData === false) {
// Return the data as it got received
return {
workflowData: [
this.helpers.returnJsonArray(bodyData),
],
};
}
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),
],
};
}
}

View file

@ -0,0 +1,95 @@
import { OptionsWithUri } from 'request';
import {
IExecuteFunctions,
ILoadOptionsFunctions,
BINARY_ENCODING
} from 'n8n-core';
import { IDataObject, IHookFunctions, IWebhookFunctions } from 'n8n-workflow';
export async function affinityApiRequest(this: IExecuteFunctions | IWebhookFunctions | IHookFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, query: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
const credentials = this.getCredentials('affinityApi');
if (credentials === undefined) {
throw new Error('No credentials got returned!');
}
const apiKey = `:${credentials.apiKey}`;
const endpoint = 'https://api.affinity.co';
let options: OptionsWithUri = {
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).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) {
if (error.response) {
let errorMessage = error.response.body.message || error.response.body.description || error.message;
throw new Error(`Affinity error response [${error.statusCode}]: ${errorMessage}`);
}
throw error;
}
}
export async function affinityApiRequestAllItems(this: IHookFunctions | ILoadOptionsFunctions | IExecuteFunctions, propertyName: string, method: string, resource: string, body: any = {}, query: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
const returnData: IDataObject[] = [];
let responseData;
query.page_size = 500;
let uri: string | undefined;
do {
responseData = await affinityApiRequest.call(this, method, resource, body, query, uri);
// @ts-ignore
query.page_token = responseData.page_token;
returnData.push.apply(returnData, responseData[propertyName]);
} 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) {
//@ts-ignore
return {
person: 'persons',
list: 'lists',
note: 'notes',
organization: 'organizatitons',
list_entry: 'list-entries',
field: 'fields',
file: 'files',
}[key]
}

View file

@ -0,0 +1,326 @@
import { INodeProperties } from 'n8n-workflow';
export const organizationOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'organization',
],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a organization',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a organization',
},
{
name: 'Get',
value: 'get',
description: 'Get a organization',
},
{
name: 'Get All',
value: 'getAll',
description: 'Get all organizations',
},
{
name: 'Update',
value: 'update',
description: 'Update a organization',
},
],
default: 'create',
description: 'The operation to perform.',
},
] as INodeProperties[];
export const organizationFields = [
/* -------------------------------------------------------------------------- */
/* 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: 'Persons',
name: 'persons',
type: 'multiOptions',
typeOptions: {
loadOptionsMethod: 'getPersons',
},
default: [],
description: 'Persons that the new organization will be associated with.',
},
],
},
/* -------------------------------------------------------------------------- */
/* 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: 'Persons',
name: 'persons',
type: 'multiOptions',
typeOptions: {
loadOptionsMethod: 'getPersons',
},
default: [],
description: 'Persons that the new organization will be associated with.',
},
]
},
/* -------------------------------------------------------------------------- */
/* 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: 'When true, 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: 'If all results should be returned 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: 'How many 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 teams 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: 'When true, 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.',
},
] as INodeProperties[];

View file

@ -0,0 +1,6 @@
export interface IOrganization {
name?: string;
domain?: string;
person_ids?: number[];
}

View file

@ -0,0 +1,370 @@
import { INodeProperties } from 'n8n-workflow';
export const personOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'person',
],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a person',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a person',
},
{
name: 'Get',
value: 'get',
description: 'Get a person',
},
{
name: 'Get All',
value: 'getAll',
description: 'Get all persons',
},
{
name: 'Update',
value: 'update',
description: 'Update a person',
},
],
default: 'create',
description: 'The operation to perform.',
},
] as INodeProperties[];
export const personFields = [
/* -------------------------------------------------------------------------- */
/* person:create */
/* -------------------------------------------------------------------------- */
{
displayName: 'Fist 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: 'Organizations',
name: 'organizations',
type: 'multiOptions',
typeOptions: {
loadOptionsMethod: 'getOrganizations',
},
default: [],
description: 'Organizations that the person is associated with.',
},
],
},
{
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: 'Fist 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: 'Organizations',
name: 'organizations',
type: 'multiOptions',
typeOptions: {
loadOptionsMethod: 'getOrganizations',
},
default: [],
description: 'Organizations that the person is associated with.',
},
]
},
{
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: 'When true, 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: 'If all results should be returned 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: 'How many 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 teams 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: 'When true, 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.',
},
] as INodeProperties[];

View file

@ -0,0 +1,7 @@
export interface IPerson {
first_name?: string;
last_name?: string;
emails?: string[];
organization_ids?: number[];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View file

@ -32,6 +32,7 @@
"dist/credentials/Amqp.credentials.js",
"dist/credentials/AsanaApi.credentials.js",
"dist/credentials/Aws.credentials.js",
"dist/credentials/AffinityApi.credentials.js",
"dist/credentials/BitbucketApi.credentials.js",
"dist/credentials/BitlyApi.credentials.js",
"dist/credentials/ChargebeeApi.credentials.js",
@ -110,6 +111,8 @@
"dist/nodes/Amqp/AmqpTrigger.node.js",
"dist/nodes/Asana/Asana.node.js",
"dist/nodes/Asana/AsanaTrigger.node.js",
"dist/nodes/Affinity/Affinity.node.js",
"dist/nodes/Affinity/AffinityTrigger.node.js",
"dist/nodes/Aws/AwsLambda.node.js",
"dist/nodes/Aws/AwsSes.node.js",
"dist/nodes/Aws/AwsSns.node.js",
@ -241,7 +244,7 @@
"@types/moment-timezone": "^0.5.12",
"@types/mongodb": "^3.3.6",
"@types/node": "^10.10.1",
"@types/nodemailer": "^4.6.5",
"@types/nodemailer": "^4.6.5",
"@types/redis": "^2.8.11",
"@types/request-promise-native": "~1.0.15",
"@types/uuid": "^3.4.6",