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
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
This commit is contained in:
@@ -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 };
|
||||
Reference in New Issue
Block a user