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,129 @@
|
||||
import moment from 'moment-timezone';
|
||||
import type {
|
||||
IDataObject,
|
||||
IExecuteFunctions,
|
||||
IHookFunctions,
|
||||
IHttpRequestMethods,
|
||||
ILoadOptionsFunctions,
|
||||
INodePropertyOptions,
|
||||
IRequestOptions,
|
||||
IWebhookFunctions,
|
||||
JsonObject,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeApiError } from 'n8n-workflow';
|
||||
|
||||
export async function onfleetApiRequest(
|
||||
this: IWebhookFunctions | IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
resource: string,
|
||||
|
||||
body: any = {},
|
||||
|
||||
qs?: any,
|
||||
uri?: string,
|
||||
): Promise<any> {
|
||||
const credentials = await this.getCredentials('onfleetApi');
|
||||
|
||||
const options: IRequestOptions = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': 'n8n-onfleet',
|
||||
},
|
||||
auth: {
|
||||
user: credentials.apiKey as string,
|
||||
pass: '',
|
||||
},
|
||||
method,
|
||||
body,
|
||||
qs,
|
||||
uri: uri || `https://onfleet.com/api/v2/${resource}`,
|
||||
json: true,
|
||||
};
|
||||
try {
|
||||
return await this.helpers.request(options);
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
}
|
||||
|
||||
export async function onfleetApiRequestAllItems(
|
||||
this: IWebhookFunctions | IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions,
|
||||
propertyName: string,
|
||||
method: IHttpRequestMethods,
|
||||
endpoint: string,
|
||||
|
||||
body: any = {},
|
||||
query: IDataObject = {},
|
||||
): Promise<any> {
|
||||
const returnData: IDataObject[] = [];
|
||||
|
||||
let responseData;
|
||||
|
||||
do {
|
||||
responseData = await onfleetApiRequest.call(this, method, endpoint, body, query);
|
||||
query.lastId = responseData.lastId;
|
||||
returnData.push.apply(returnData, responseData[propertyName] as IDataObject[]);
|
||||
} while (responseData.lastId !== undefined);
|
||||
|
||||
return returnData;
|
||||
}
|
||||
export const resourceLoaders = {
|
||||
async getTeams(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
try {
|
||||
const teams = (await onfleetApiRequest.call(this, 'GET', 'teams')) as IDataObject[];
|
||||
return teams.map(({ name = '', id: value = '' }) => ({
|
||||
name,
|
||||
value,
|
||||
})) as INodePropertyOptions[];
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
async getWorkers(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
try {
|
||||
const workers = (await onfleetApiRequest.call(this, 'GET', 'workers')) as IDataObject[];
|
||||
return workers.map(({ name = '', id: value = '' }) => ({
|
||||
name,
|
||||
value,
|
||||
})) as INodePropertyOptions[];
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
async getAdmins(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
try {
|
||||
const admins = (await onfleetApiRequest.call(this, 'GET', 'admins')) as IDataObject[];
|
||||
return admins.map(({ name = '', id: value = '' }) => ({
|
||||
name,
|
||||
value,
|
||||
})) as INodePropertyOptions[];
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
async getHubs(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
try {
|
||||
const hubs = (await onfleetApiRequest.call(this, 'GET', 'hubs')) as IDataObject[];
|
||||
return hubs.map(({ name = '', id: value = '' }) => ({
|
||||
name,
|
||||
value,
|
||||
})) as INodePropertyOptions[];
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
async getTimezones(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData = [] as INodePropertyOptions[];
|
||||
for (const timezone of moment.tz.names()) {
|
||||
returnData.push({
|
||||
name: timezone,
|
||||
value: timezone,
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.onfleet",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Miscellaneous"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/onfleet/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.onfleet/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
import {
|
||||
type IExecuteFunctions,
|
||||
type ICredentialsDecrypted,
|
||||
type ICredentialTestFunctions,
|
||||
type IDataObject,
|
||||
type INodeCredentialTestResult,
|
||||
type INodeExecutionData,
|
||||
type INodeType,
|
||||
type INodeTypeDescription,
|
||||
type IRequestOptions,
|
||||
NodeConnectionTypes,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { adminFields, adminOperations } from './descriptions/AdministratorDescription';
|
||||
import { containerFields, containerOperations } from './descriptions/ContainerDescription';
|
||||
import { destinationFields, destinationOperations } from './descriptions/DestinationDescription';
|
||||
import { hubFields, hubOperations } from './descriptions/HubDescription';
|
||||
import { organizationFields, organizationOperations } from './descriptions/OrganizationDescription';
|
||||
import { recipientFields, recipientOperations } from './descriptions/RecipientDescription';
|
||||
import { taskFields, taskOperations } from './descriptions/TaskDescription';
|
||||
import { teamFields, teamOperations } from './descriptions/TeamDescription';
|
||||
import { workerFields, workerOperations } from './descriptions/WorkerDescription';
|
||||
import { resourceLoaders } from './GenericFunctions';
|
||||
import { Onfleet as OnfleetMethods } from './Onfleet';
|
||||
export class Onfleet implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Onfleet',
|
||||
name: 'onfleet',
|
||||
icon: 'file:Onfleet.svg',
|
||||
group: ['input'],
|
||||
version: 1,
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
description: 'Consume Onfleet API',
|
||||
defaults: {
|
||||
name: 'Onfleet',
|
||||
},
|
||||
usableAsTool: true,
|
||||
inputs: [NodeConnectionTypes.Main],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'onfleetApi',
|
||||
required: true,
|
||||
testedBy: 'onfleetApiTest',
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
// List of option resources
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
options: [
|
||||
{
|
||||
name: 'Admin',
|
||||
value: 'admin',
|
||||
},
|
||||
{
|
||||
name: 'Container',
|
||||
value: 'container',
|
||||
},
|
||||
{
|
||||
name: 'Destination',
|
||||
value: 'destination',
|
||||
},
|
||||
{
|
||||
name: 'Hub',
|
||||
value: 'hub',
|
||||
},
|
||||
{
|
||||
name: 'Organization',
|
||||
value: 'organization',
|
||||
},
|
||||
{
|
||||
name: 'Recipient',
|
||||
value: 'recipient',
|
||||
},
|
||||
{
|
||||
name: 'Task',
|
||||
value: 'task',
|
||||
},
|
||||
{
|
||||
name: 'Team',
|
||||
value: 'team',
|
||||
},
|
||||
// {
|
||||
// name: 'Webhook',
|
||||
// value: 'webhook',
|
||||
// },
|
||||
{
|
||||
name: 'Worker',
|
||||
value: 'worker',
|
||||
},
|
||||
],
|
||||
default: 'task',
|
||||
description: 'The resource to perform operations on',
|
||||
},
|
||||
// Operations & fields
|
||||
...adminOperations,
|
||||
...adminFields,
|
||||
...containerOperations,
|
||||
...containerFields,
|
||||
...destinationOperations,
|
||||
...destinationFields,
|
||||
...hubOperations,
|
||||
...hubFields,
|
||||
...organizationOperations,
|
||||
...organizationFields,
|
||||
...recipientOperations,
|
||||
...recipientFields,
|
||||
...taskOperations,
|
||||
...taskFields,
|
||||
...teamOperations,
|
||||
...teamFields,
|
||||
// ...webhookOperations,
|
||||
// ...webhookFields,
|
||||
...workerOperations,
|
||||
...workerFields,
|
||||
],
|
||||
};
|
||||
|
||||
methods = {
|
||||
credentialTest: {
|
||||
async onfleetApiTest(
|
||||
this: ICredentialTestFunctions,
|
||||
credential: ICredentialsDecrypted,
|
||||
): Promise<INodeCredentialTestResult> {
|
||||
const credentials = credential.data as IDataObject;
|
||||
|
||||
const options: IRequestOptions = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': 'n8n-onfleet',
|
||||
},
|
||||
auth: {
|
||||
user: credentials.apiKey as string,
|
||||
pass: '',
|
||||
},
|
||||
method: 'GET',
|
||||
uri: 'https://onfleet.com/api/v2/auth/test',
|
||||
json: true,
|
||||
};
|
||||
|
||||
try {
|
||||
await this.helpers.request(options);
|
||||
return {
|
||||
status: 'OK',
|
||||
message: 'Authentication successful',
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 'Error',
|
||||
message: `Auth settings are not valid: ${error}`,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
loadOptions: resourceLoaders,
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const resource = this.getNodeParameter('resource', 0);
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
const items = this.getInputData();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-restricted-types
|
||||
const operations: { [key: string]: Function } = {
|
||||
task: OnfleetMethods.executeTaskOperations,
|
||||
destination: OnfleetMethods.executeDestinationOperations,
|
||||
organization: OnfleetMethods.executeOrganizationOperations,
|
||||
admin: OnfleetMethods.executeAdministratorOperations,
|
||||
recipient: OnfleetMethods.executeRecipientOperations,
|
||||
hub: OnfleetMethods.executeHubOperations,
|
||||
worker: OnfleetMethods.executeWorkerOperations,
|
||||
webhook: OnfleetMethods.executeWebhookOperations,
|
||||
container: OnfleetMethods.executeContainerOperations,
|
||||
team: OnfleetMethods.executeTeamOperations,
|
||||
};
|
||||
|
||||
const responseData = await operations[resource].call(this, `${resource}s`, operation, items);
|
||||
|
||||
// Map data to n8n data
|
||||
return [this.helpers.returnJsonArray(responseData as IDataObject)];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60"><g fill="none" fill-rule="evenodd"><path fill="#AA81F3" d="M0 0h60v60H0z"/><path fill="#FFF" d="M32.55 32.066c.482.454 1.207 1.066 2.145 1.811.938.721 2.169 1.545 3.643 2.188.75.29 1.553.533 2.412.557.427 0 .86 0 1.261-.133.213-.024.402-.133.591-.212.189-.11.378-.188.56-.321.348-.243.695-.534.963-.903.268-.37.512-.77.725-1.224.378-.903.615-1.92.67-2.981a8.7 8.7 0 0 0-.426-3.2c-.348-1.011-.908-1.945-1.712-2.532-.774-.558-1.767-.77-2.839-.612-.536.109-1.096.242-1.632.478-.269.11-.537.243-.829.376-.268.158-.536.29-.804.454-1.072.643-2.114 1.436-3.107 2.29-.481.455-.993.88-1.444 1.358-.243.242-.48.455-.694.721l-.725.745a40 40 0 0 1-3.083 2.933c-1.096.933-2.247 1.788-3.533 2.533-1.26.721-2.68 1.333-4.258 1.545a6.7 6.7 0 0 1-2.437-.109 5.7 5.7 0 0 1-2.223-1.066 6.4 6.4 0 0 1-1.53-1.758 8 8 0 0 1-.858-2 10.7 10.7 0 0 1-.348-2.023 9.7 9.7 0 0 1 .025-1.97 9.9 9.9 0 0 1 1.06-3.635 7 7 0 0 1 1.072-1.52 5.3 5.3 0 0 1 1.42-1.146c.535-.29 1.096-.509 1.662-.588.56-.103 1.121-.072 1.657-.024 1.042.133 1.956.51 2.73.903 1.553.854 2.68 1.836 3.563 2.69.86.855 1.475 1.6 1.901 2.103l.615.77-.725-.667c-.48-.455-1.206-1.067-2.144-1.788-.938-.72-2.169-1.545-3.643-2.187-.75-.29-1.553-.533-2.412-.557-.829-.025-1.688.157-2.382.666-.347.242-.695.533-.963.903s-.536.77-.725 1.224a7.9 7.9 0 0 0-.67 3.011 8.7 8.7 0 0 0 .427 3.2c.347 1.011.907 1.945 1.711 2.502.774.557 1.767.77 2.84.588.133 0 .267-.055.401-.079s.268-.055.402-.109l.402-.133.403-.158c.134-.054.268-.109.402-.188l.402-.188c.268-.157.536-.29.804-.454 1.072-.642 2.114-1.436 3.107-2.29.993-.879 1.9-1.758 2.893-2.8l.725-.745c.244-.267.512-.51.75-.745a25 25 0 0 1 1.577-1.436c1.097-.934 2.248-1.788 3.534-2.533 1.26-.721 2.68-1.333 4.258-1.545a6.8 6.8 0 0 1 2.436.133 5.6 5.6 0 0 1 2.2 1.09c.645.51 1.127 1.122 1.529 1.758a8 8 0 0 1 .859 2c.188.666.292 1.357.347 2.023a9.7 9.7 0 0 1-.025 1.97c-.134 1.278-.48 2.532-1.041 3.623a7 7 0 0 1-1.072 1.52 5 5 0 0 1-1.444 1.146 5 5 0 0 1-.829.376c-.292.078-.56.187-.859.212-.56.109-1.127.079-1.663.024-1.041-.158-1.955-.533-2.729-.933-1.553-.855-2.68-1.866-3.564-2.715-.859-.854-1.474-1.6-1.9-2.102l-.615-.77c.079-.012.804.655.804.655"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.onfleetTrigger",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Miscellaneous"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/onfleet/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.onfleettrigger/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
import type {
|
||||
IHookFunctions,
|
||||
IWebhookFunctions,
|
||||
IDataObject,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
IWebhookResponseData,
|
||||
JsonObject,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeApiError, NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';
|
||||
|
||||
import { eventDisplay, eventNameField } from './descriptions/OnfleetWebhookDescription';
|
||||
import { onfleetApiRequest } from './GenericFunctions';
|
||||
import { webhookMapping } from './WebhookMapping';
|
||||
|
||||
export class OnfleetTrigger implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Onfleet Trigger',
|
||||
name: 'onfleetTrigger',
|
||||
icon: 'file:Onfleet.svg',
|
||||
group: ['trigger'],
|
||||
version: 1,
|
||||
subtitle: '={{$parameter["triggerOn"]}}',
|
||||
description: 'Starts the workflow when Onfleet events occur',
|
||||
defaults: {
|
||||
name: 'Onfleet Trigger',
|
||||
},
|
||||
inputs: [],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'onfleetApi',
|
||||
required: true,
|
||||
testedBy: 'onfleetApiTest',
|
||||
},
|
||||
],
|
||||
webhooks: [
|
||||
{
|
||||
name: 'setup',
|
||||
httpMethod: 'GET',
|
||||
responseMode: 'onReceived',
|
||||
path: 'webhook',
|
||||
},
|
||||
{
|
||||
name: 'default',
|
||||
httpMethod: 'POST',
|
||||
responseMode: 'onReceived',
|
||||
path: 'webhook',
|
||||
},
|
||||
],
|
||||
properties: [eventDisplay, eventNameField],
|
||||
};
|
||||
|
||||
webhookMethods = {
|
||||
default: {
|
||||
async checkExists(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
const webhookUrl = this.getNodeWebhookUrl('default') as string;
|
||||
|
||||
// Webhook got created before so check if it still exists
|
||||
const endpoint = '/webhooks';
|
||||
|
||||
const webhooks = await onfleetApiRequest.call(this, 'GET', endpoint);
|
||||
|
||||
for (const webhook of webhooks) {
|
||||
if (webhook.url === webhookUrl && webhook.trigger === event) {
|
||||
webhookData.webhookId = webhook.id;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
async create(this: IHookFunctions): Promise<boolean> {
|
||||
const { name = '' } = this.getNodeParameter('additionalFields') as IDataObject;
|
||||
const triggerOn = this.getNodeParameter('triggerOn') as string;
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
const webhookUrl = this.getNodeWebhookUrl('default') as string;
|
||||
|
||||
if (webhookUrl.includes('//localhost')) {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
'The Webhook can not work on "localhost". Please setup n8n on a custom domain.',
|
||||
);
|
||||
}
|
||||
// Webhook name according to the field
|
||||
let newWebhookName = `n8n-webhook:${webhookUrl}`;
|
||||
|
||||
if (name) {
|
||||
newWebhookName = `n8n-webhook:${name}`;
|
||||
}
|
||||
|
||||
const path = '/webhooks';
|
||||
const body = {
|
||||
name: newWebhookName,
|
||||
url: webhookUrl,
|
||||
trigger: webhookMapping[triggerOn].key,
|
||||
};
|
||||
|
||||
try {
|
||||
const webhook = await onfleetApiRequest.call(this, 'POST', path, body);
|
||||
|
||||
if (webhook.id === undefined) {
|
||||
throw new NodeApiError(this.getNode(), webhook as JsonObject, {
|
||||
message: 'Onfleet webhook creation response did not contain the expected data',
|
||||
});
|
||||
}
|
||||
|
||||
webhookData.id = webhook.id as string;
|
||||
} catch (error) {
|
||||
const { httpCode = '' } = error as { httpCode: string };
|
||||
if (httpCode === '422') {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
'A webhook with the identical URL probably exists already. Please delete it manually in Onfleet!',
|
||||
);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
async delete(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
// Get the data of the already registered webhook
|
||||
const endpoint = `/webhooks/${webhookData.id}`;
|
||||
await onfleetApiRequest.call(this, 'DELETE', endpoint);
|
||||
return true;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggered function when an Onfleet webhook is executed
|
||||
*/
|
||||
async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
|
||||
const req = this.getRequestObject();
|
||||
if (this.getWebhookName() === 'setup') {
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Validation request */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
const res = this.getResponseObject();
|
||||
res.status(200).type('text/plain').send(req.query.check);
|
||||
return { noWebhookResponse: true };
|
||||
}
|
||||
|
||||
const returnData: IDataObject = this.getBodyData();
|
||||
|
||||
return {
|
||||
workflowData: [this.helpers.returnJsonArray(returnData)],
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
import type { OnfleetWebhooksMapping } from './interfaces';
|
||||
|
||||
export const webhookMapping: OnfleetWebhooksMapping = {
|
||||
taskStarted: {
|
||||
name: 'Task Started',
|
||||
value: 'taskStarted',
|
||||
key: 0,
|
||||
},
|
||||
taskEta: {
|
||||
name: 'Task ETA',
|
||||
value: 'taskEta',
|
||||
key: 1,
|
||||
},
|
||||
taskArrival: {
|
||||
name: 'Task Arrival',
|
||||
value: 'taskArrival',
|
||||
key: 2,
|
||||
},
|
||||
taskCompleted: {
|
||||
name: 'Task Completed',
|
||||
value: 'taskCompleted',
|
||||
key: 3,
|
||||
},
|
||||
taskFailed: {
|
||||
name: 'Task Failed',
|
||||
value: 'taskFailed',
|
||||
key: 4,
|
||||
},
|
||||
workerDuty: {
|
||||
name: 'Worker Duty',
|
||||
value: 'workerDuty',
|
||||
key: 5,
|
||||
},
|
||||
taskCreated: {
|
||||
name: 'Task Created',
|
||||
value: 'taskCreated',
|
||||
key: 6,
|
||||
},
|
||||
taskUpdated: {
|
||||
name: 'Task Updated',
|
||||
value: 'taskUpdated',
|
||||
key: 7,
|
||||
},
|
||||
taskDeleted: {
|
||||
name: 'Task Deleted',
|
||||
value: 'taskDeleted',
|
||||
key: 8,
|
||||
},
|
||||
taskAssigned: {
|
||||
name: 'Task Assigned',
|
||||
value: 'taskAssigned',
|
||||
key: 9,
|
||||
},
|
||||
taskUnassigned: {
|
||||
name: 'Task Unassigned',
|
||||
value: 'taskUnassigned',
|
||||
key: 10,
|
||||
},
|
||||
taskDelayed: {
|
||||
name: 'Task Delayed',
|
||||
value: 'taskDelayed',
|
||||
key: 12,
|
||||
},
|
||||
taskCloned: {
|
||||
name: 'Task Cloned',
|
||||
value: 'taskCloned',
|
||||
key: 13,
|
||||
},
|
||||
smsRecipientResponseMissed: {
|
||||
name: 'SMS Recipient Response Missed',
|
||||
value: 'smsRecipientResponseMissed',
|
||||
key: 14,
|
||||
},
|
||||
workerCreated: {
|
||||
name: 'Worker Created',
|
||||
value: 'workerCreated',
|
||||
key: 15,
|
||||
},
|
||||
workerDeleted: {
|
||||
name: 'Worker Deleted',
|
||||
value: 'workerDeleted',
|
||||
key: 16,
|
||||
},
|
||||
SMSRecipientOptOut: {
|
||||
name: 'SMS Recipient Opt Out',
|
||||
value: 'SMSRecipientOptOut',
|
||||
key: 17,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,307 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"additionalQuantities": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"quantityA": {
|
||||
"type": "integer"
|
||||
},
|
||||
"quantityB": {
|
||||
"type": "integer"
|
||||
},
|
||||
"quantityC": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appearance": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"triangleColor": {
|
||||
"type": "null"
|
||||
}
|
||||
}
|
||||
},
|
||||
"completionDetails": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"actions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"actionType": {
|
||||
"type": "string"
|
||||
},
|
||||
"adminId": {
|
||||
"type": "string"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"prevState": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"failureNotes": {
|
||||
"type": "string"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"successNotes": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"events": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"location": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"time": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"failureNotes": {
|
||||
"type": "string"
|
||||
},
|
||||
"failureReason": {
|
||||
"type": "string"
|
||||
},
|
||||
"firstLocation": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"lastLocation": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"successNotes": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"creator": {
|
||||
"type": "string"
|
||||
},
|
||||
"dependencies": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"destination": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"apartment": {
|
||||
"type": "string"
|
||||
},
|
||||
"city": {
|
||||
"type": "string"
|
||||
},
|
||||
"country": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"number": {
|
||||
"type": "string"
|
||||
},
|
||||
"postalCode": {
|
||||
"type": "string"
|
||||
},
|
||||
"state": {
|
||||
"type": "string"
|
||||
},
|
||||
"street": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"location": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"timeCreated": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timeLastModified": {
|
||||
"type": "integer"
|
||||
},
|
||||
"useGPS": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"estimatedArrivalTime": {
|
||||
"type": "null"
|
||||
},
|
||||
"estimatedCompletionTime": {
|
||||
"type": "null"
|
||||
},
|
||||
"eta": {
|
||||
"type": "null"
|
||||
},
|
||||
"executor": {
|
||||
"type": "string"
|
||||
},
|
||||
"feedback": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"comments": {
|
||||
"type": "string"
|
||||
},
|
||||
"rating": {
|
||||
"type": "integer"
|
||||
},
|
||||
"recipient": {
|
||||
"type": "string"
|
||||
},
|
||||
"time": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"identity": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"checksum": {
|
||||
"type": "null"
|
||||
},
|
||||
"failedScanCount": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"merchant": {
|
||||
"type": "string"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"orderShortId": {
|
||||
"type": "null"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"pickupTask": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"recipients": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"skipSMSNotifications": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"timeCreated": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timeLastModified": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scanOnlyRequiredBarcodes": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"serviceTime": {
|
||||
"type": "integer"
|
||||
},
|
||||
"shortId": {
|
||||
"type": "string"
|
||||
},
|
||||
"state": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timeCreated": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timeLastModified": {
|
||||
"type": "integer"
|
||||
},
|
||||
"trackingURL": {
|
||||
"type": "string"
|
||||
},
|
||||
"trackingViewed": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"type": "integer"
|
||||
},
|
||||
"worker": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enableSelfAssignment": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"managers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"tasks": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"timeCreated": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timeLastModified": {
|
||||
"type": "integer"
|
||||
},
|
||||
"workers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const adminOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['admin'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a new Onfleet admin',
|
||||
action: 'Create an admin',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete an Onfleet admin',
|
||||
action: 'Delete an admin',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many Onfleet admins',
|
||||
action: 'Get many admins',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update an Onfleet admin',
|
||||
action: 'Update an admin',
|
||||
},
|
||||
],
|
||||
default: 'getAll',
|
||||
},
|
||||
];
|
||||
|
||||
const adminNameField = {
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: "The administrator's name",
|
||||
} as INodeProperties;
|
||||
|
||||
const adminEmailField = {
|
||||
displayName: 'Email',
|
||||
name: 'email',
|
||||
type: 'string',
|
||||
placeholder: 'name@email.com',
|
||||
default: '',
|
||||
description: "The administrator's email address",
|
||||
} as INodeProperties;
|
||||
|
||||
const adminPhoneField = {
|
||||
displayName: 'Phone',
|
||||
name: 'phone',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: "The administrator's phone number",
|
||||
} as INodeProperties;
|
||||
|
||||
const adminReadOnlyField = {
|
||||
displayName: 'Read Only',
|
||||
name: 'isReadOnly',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether this administrator can perform write operations',
|
||||
} as INodeProperties;
|
||||
|
||||
export const adminFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Admin ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['admin'],
|
||||
},
|
||||
hide: {
|
||||
operation: ['create', 'getAll'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
description: 'The ID of the admin object for lookup',
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['admin'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['admin'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 64,
|
||||
},
|
||||
default: 64,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['admin'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
...adminNameField,
|
||||
},
|
||||
{
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['admin'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
...adminEmailField,
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['admin'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: [adminPhoneField, adminReadOnlyField],
|
||||
},
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['admin'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
options: [adminNameField, adminPhoneField, adminReadOnlyField],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,188 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const containerOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['container'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Add Tasks',
|
||||
value: 'addTask',
|
||||
description: 'Add task at index (or append)',
|
||||
action: 'Add tasks',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get container information',
|
||||
action: 'Get a container',
|
||||
},
|
||||
{
|
||||
name: 'Update Tasks',
|
||||
value: 'updateTask',
|
||||
description: "Fully replace a container's tasks",
|
||||
action: 'Update tasks',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
const containerTypeField = {
|
||||
displayName: 'Container Type',
|
||||
name: 'containerType',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Organizations',
|
||||
value: 'organizations',
|
||||
},
|
||||
{
|
||||
name: 'Teams',
|
||||
value: 'teams',
|
||||
},
|
||||
{
|
||||
name: 'Workers',
|
||||
value: 'workers',
|
||||
},
|
||||
],
|
||||
default: '',
|
||||
} as INodeProperties;
|
||||
|
||||
const containerIdField = {
|
||||
displayName: 'Container ID',
|
||||
name: 'containerId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The object ID according to the container chosen',
|
||||
} as INodeProperties;
|
||||
|
||||
const insertTypeField = {
|
||||
displayName: 'Insert Type',
|
||||
name: 'type',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Append',
|
||||
value: -1,
|
||||
},
|
||||
{
|
||||
name: 'Prepend',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: 'At Specific Index',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
default: '',
|
||||
} as INodeProperties;
|
||||
|
||||
const indexField = {
|
||||
displayName: 'Index',
|
||||
name: 'index',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The index given indicates the position where the tasks are going to be inserted',
|
||||
} as INodeProperties;
|
||||
|
||||
const tasksField = {
|
||||
displayName: 'Task IDs',
|
||||
name: 'tasks',
|
||||
type: 'string',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add Task',
|
||||
},
|
||||
default: [],
|
||||
description: "Task's ID that are going to be used",
|
||||
} as INodeProperties;
|
||||
|
||||
const considerDependenciesField = {
|
||||
displayName: 'Consider Dependencies',
|
||||
name: 'considerDependencies',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description:
|
||||
"Whether to include the target task's dependency family (parent and child tasks) in the resulting assignment operation",
|
||||
} as INodeProperties;
|
||||
|
||||
export const containerFields: INodeProperties[] = [
|
||||
{
|
||||
...containerTypeField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['container'],
|
||||
operation: ['get', 'addTask'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...containerIdField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['container'],
|
||||
operation: ['get', 'addTask', 'updateTask'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...insertTypeField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['container'],
|
||||
operation: ['addTask'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...indexField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['container'],
|
||||
operation: ['addTask'],
|
||||
type: [1],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...tasksField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['container'],
|
||||
operation: ['addTask', 'updateTask'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add option',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['container'],
|
||||
operation: ['addTask', 'updateTask'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
...considerDependenciesField,
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,327 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const destinationOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['destination'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a new destination',
|
||||
action: 'Create a destination',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a specific destination',
|
||||
action: 'Get a destination',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
const unparsedField = {
|
||||
displayName: 'Unparsed Address',
|
||||
name: 'unparsed',
|
||||
type: 'boolean',
|
||||
description: 'Whether or not the address is specified in a single unparsed string',
|
||||
default: false,
|
||||
} as INodeProperties;
|
||||
|
||||
const unparsedAddressField = {
|
||||
displayName: 'Destination Address',
|
||||
name: 'address',
|
||||
type: 'string',
|
||||
description: "The destination's street address details",
|
||||
default: '',
|
||||
} as INodeProperties;
|
||||
|
||||
const unparsedAddressNumberField = {
|
||||
displayName: 'Number',
|
||||
name: 'addressNumber',
|
||||
type: 'string',
|
||||
description: 'The number component of this address, it may also contain letters',
|
||||
default: '',
|
||||
} as INodeProperties;
|
||||
|
||||
const unparsedAddressStreetField = {
|
||||
displayName: 'Street',
|
||||
name: 'addressStreet',
|
||||
type: 'string',
|
||||
description: 'The name of the street',
|
||||
default: '',
|
||||
} as INodeProperties;
|
||||
|
||||
const unparsedAddressCityField = {
|
||||
displayName: 'City',
|
||||
name: 'addressCity',
|
||||
type: 'string',
|
||||
description: 'The name of the municipality',
|
||||
default: '',
|
||||
} as INodeProperties;
|
||||
|
||||
const unparsedAddressCountryField = {
|
||||
displayName: 'Country',
|
||||
name: 'addressCountry',
|
||||
type: 'string',
|
||||
description: 'The name of the country',
|
||||
default: '',
|
||||
} as INodeProperties;
|
||||
|
||||
const unparsedAddressStateField = {
|
||||
displayName: 'State',
|
||||
name: 'addressState',
|
||||
type: 'string',
|
||||
default: '',
|
||||
} as INodeProperties;
|
||||
|
||||
const addressNameField = {
|
||||
displayName: 'Address Name',
|
||||
name: 'addressName',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'A name associated with this address',
|
||||
} as INodeProperties;
|
||||
|
||||
const addressApartmentField = {
|
||||
displayName: 'Apartment',
|
||||
name: 'addressApartment',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The suite or apartment number, or any additional relevant information',
|
||||
} as INodeProperties;
|
||||
|
||||
const addressNoteField = {
|
||||
displayName: 'Address Notes',
|
||||
name: 'addressNotes',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Notes about the destination',
|
||||
} as INodeProperties;
|
||||
|
||||
const addressPostalCodeField = {
|
||||
displayName: 'Postal Code',
|
||||
name: 'addressPostalCode',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The postal or zip code',
|
||||
} as INodeProperties;
|
||||
|
||||
export const destinationExternalField = {
|
||||
displayName: 'Destination',
|
||||
name: 'destination',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Destination',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Destination Properties',
|
||||
name: 'destinationProperties',
|
||||
default: {},
|
||||
values: [
|
||||
{
|
||||
...unparsedField,
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
...unparsedAddressField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
unparsed: [true],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...unparsedAddressNumberField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
unparsed: [false],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...unparsedAddressStreetField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
unparsed: [false],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...unparsedAddressCityField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
unparsed: [false],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...unparsedAddressStateField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
unparsed: [false],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...unparsedAddressCountryField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
unparsed: [false],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayOptions: {
|
||||
show: {
|
||||
unparsed: [false],
|
||||
},
|
||||
},
|
||||
...addressPostalCodeField,
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
...addressNameField,
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
...addressApartmentField,
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
...addressNoteField,
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
} as INodeProperties;
|
||||
|
||||
export const destinationFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Destination ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['destination'],
|
||||
},
|
||||
hide: {
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
description: 'The ID of the destination object for lookup',
|
||||
},
|
||||
{
|
||||
...unparsedField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['destination'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...unparsedAddressField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['destination'],
|
||||
operation: ['create'],
|
||||
unparsed: [true],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...unparsedAddressNumberField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['destination'],
|
||||
operation: ['create'],
|
||||
unparsed: [false],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...unparsedAddressStreetField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['destination'],
|
||||
operation: ['create'],
|
||||
unparsed: [false],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...unparsedAddressCityField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['destination'],
|
||||
operation: ['create'],
|
||||
unparsed: [false],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...unparsedAddressCountryField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['destination'],
|
||||
operation: ['create'],
|
||||
unparsed: [false],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['destination'],
|
||||
operation: ['create'],
|
||||
unparsed: [true],
|
||||
},
|
||||
},
|
||||
options: [addressApartmentField, addressNameField, addressNoteField],
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['destination'],
|
||||
operation: ['create'],
|
||||
unparsed: [false],
|
||||
},
|
||||
},
|
||||
options: [addressApartmentField, addressNameField, addressNoteField, addressPostalCodeField],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,168 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { destinationExternalField } from './DestinationDescription';
|
||||
|
||||
export const hubOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['hub'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a new Onfleet hub',
|
||||
action: 'Create a hub',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many Onfleet hubs',
|
||||
action: 'Get many hubs',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update an Onfleet hub',
|
||||
action: 'Update a hub',
|
||||
},
|
||||
],
|
||||
default: 'getAll',
|
||||
},
|
||||
];
|
||||
|
||||
const nameField = {
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'A name to identify the hub',
|
||||
} as INodeProperties;
|
||||
|
||||
const teamsField = {
|
||||
displayName: 'Team Names or IDs',
|
||||
name: 'teams',
|
||||
type: 'multiOptions',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getTeams',
|
||||
},
|
||||
default: [],
|
||||
description:
|
||||
'These are the teams that this Hub will be assigned to. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
} as INodeProperties;
|
||||
|
||||
export const hubFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Hub ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['hub'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
description: 'The ID of the hub object for lookup',
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['hub'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['hub'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 64,
|
||||
},
|
||||
default: 64,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
...nameField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['hub'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...destinationExternalField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['hub'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['hub'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
...teamsField,
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['hub'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
...destinationExternalField,
|
||||
required: false,
|
||||
},
|
||||
nameField,
|
||||
{
|
||||
...teamsField,
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,44 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { webhookMapping } from '../WebhookMapping';
|
||||
|
||||
const sort = (a: { name: string }, b: { name: string }) => {
|
||||
if (a.name < b.name) {
|
||||
return -1;
|
||||
}
|
||||
if (a.name > b.name) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
export const eventDisplay: INodeProperties = {
|
||||
displayName: 'Trigger On',
|
||||
name: 'triggerOn',
|
||||
type: 'options',
|
||||
options: Object.keys(webhookMapping)
|
||||
.map((webhook) => {
|
||||
const { name, value } = webhookMapping[webhook];
|
||||
return { name, value };
|
||||
})
|
||||
.sort(sort),
|
||||
required: true,
|
||||
default: [],
|
||||
};
|
||||
|
||||
export const eventNameField = {
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'A name for the webhook for identification',
|
||||
},
|
||||
],
|
||||
} as INodeProperties;
|
||||
@@ -0,0 +1,47 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const organizationOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['organization'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Get My Organization',
|
||||
value: 'get',
|
||||
description: "Retrieve your own organization's details",
|
||||
action: 'Get my organization',
|
||||
},
|
||||
{
|
||||
name: 'Get Delegatee Details',
|
||||
value: 'getDelegatee',
|
||||
description: 'Retrieve the details of an organization with which you are connected',
|
||||
action: "Get a delegatee's details",
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
export const organizationFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Organization ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['organization'],
|
||||
operation: ['getDelegatee'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
description: 'The ID of the delegatees for lookup',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,283 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const recipientOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['recipient'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a new Onfleet recipient',
|
||||
action: 'Create a recipient',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a specific Onfleet recipient',
|
||||
action: 'Get a recipient',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update an Onfleet recipient',
|
||||
action: 'Update a recipient',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
const additionalRecipientFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Recipient Notes',
|
||||
name: 'recipientNotes',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'Notes for this recipient: these are global notes that should not be task- or destination-specific',
|
||||
},
|
||||
{
|
||||
displayName: 'Skip Recipient SMS Notifications',
|
||||
name: 'recipientSkipSMSNotifications',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether this recipient has requested to skip SMS notifications',
|
||||
},
|
||||
];
|
||||
|
||||
const recipientName = {
|
||||
displayName: 'Recipient Name',
|
||||
name: 'recipientName',
|
||||
type: 'string',
|
||||
description: "The recipient's complete name",
|
||||
default: '',
|
||||
} as INodeProperties;
|
||||
|
||||
const recipientPhone = {
|
||||
displayName: 'Recipient Phone',
|
||||
name: 'recipientPhone',
|
||||
type: 'string',
|
||||
description:
|
||||
"A unique, valid phone number as per the organization's country if there's no leading + sign. If a phone number has a leading + sign, it will disregard the organization's country setting.",
|
||||
default: '',
|
||||
} as INodeProperties;
|
||||
|
||||
const updateFields: INodeProperties[] = [
|
||||
{
|
||||
...recipientName,
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
displayName: 'Recipient Notes',
|
||||
name: 'notes',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'Notes for this recipient: these are global notes that should not be task- or destination-specific',
|
||||
},
|
||||
{
|
||||
...recipientPhone,
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
displayName: 'Skip Recipient SMS Notifications',
|
||||
name: 'skipSMSNotifications',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether this recipient has requested to skip SMS notifications',
|
||||
},
|
||||
];
|
||||
|
||||
export const recipientExternalField = {
|
||||
displayName: 'Recipient',
|
||||
name: 'recipient',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Recipient',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Recipient Properties',
|
||||
name: 'recipientProperties',
|
||||
default: {},
|
||||
values: [
|
||||
{
|
||||
...recipientName,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...recipientPhone,
|
||||
required: true,
|
||||
},
|
||||
...additionalRecipientFields,
|
||||
],
|
||||
},
|
||||
],
|
||||
} as INodeProperties;
|
||||
|
||||
export const recipientFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Get By',
|
||||
name: 'getBy',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['recipient'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'ID',
|
||||
value: 'id',
|
||||
},
|
||||
{
|
||||
name: 'Phone',
|
||||
value: 'phone',
|
||||
},
|
||||
{
|
||||
name: 'Name',
|
||||
value: 'name',
|
||||
},
|
||||
],
|
||||
description: 'The variable that is used for looking up a recipient',
|
||||
required: true,
|
||||
default: 'id',
|
||||
},
|
||||
{
|
||||
displayName: 'Recipient ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['recipient'],
|
||||
operation: ['get'],
|
||||
getBy: ['id'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
description: 'The ID of the recipient object for lookup',
|
||||
},
|
||||
{
|
||||
displayName: 'Recipient ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['recipient'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
description: 'The ID of the recipient object for lookup',
|
||||
},
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['recipient'],
|
||||
operation: ['get'],
|
||||
getBy: ['name'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
description: 'The name of the recipient for lookup',
|
||||
},
|
||||
{
|
||||
displayName: 'Phone',
|
||||
name: 'phone',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['recipient'],
|
||||
operation: ['get'],
|
||||
getBy: ['phone'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
description: 'The phone of the recipient for lookup',
|
||||
},
|
||||
{
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['recipient'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
...recipientName,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['recipient'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
...recipientPhone,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['recipient'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: additionalRecipientFields,
|
||||
},
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Update Fields',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['recipient'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
options: updateFields,
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['recipient'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Skip Recipient Phone Number Validation',
|
||||
name: 'recipientSkipPhoneNumberValidation',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: "Whether to skip validation for this recipient's phone number",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,412 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { destinationExternalField } from './DestinationDescription';
|
||||
import { recipientExternalField } from './RecipientDescription';
|
||||
|
||||
export const taskOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['task'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Clone',
|
||||
value: 'clone',
|
||||
description: 'Clone an Onfleet task',
|
||||
action: 'Clone a task',
|
||||
},
|
||||
{
|
||||
name: 'Complete',
|
||||
value: 'complete',
|
||||
description: 'Force-complete a started Onfleet task',
|
||||
action: 'Complete a task',
|
||||
},
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a new Onfleet task',
|
||||
action: 'Create a task',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete an Onfleet task',
|
||||
action: 'Delete a task',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a specific Onfleet task',
|
||||
action: 'Get a task',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many Onfleet tasks',
|
||||
action: 'Get many tasks',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update an Onfleet task',
|
||||
action: 'Update a task',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
const merchantIdField = {
|
||||
displayName: 'Merchant ID',
|
||||
name: 'merchant',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The ID of the organization that will be displayed to the recipient of the task',
|
||||
} as INodeProperties;
|
||||
|
||||
const executorIdField = {
|
||||
displayName: 'Executor ID',
|
||||
name: 'executor',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The ID of the organization that will be responsible for fulfilling the task',
|
||||
} as INodeProperties;
|
||||
|
||||
const completeAfterField = {
|
||||
displayName: 'Complete After',
|
||||
name: 'completeAfter',
|
||||
type: 'dateTime',
|
||||
default: null,
|
||||
description: 'The earliest time the task should be completed',
|
||||
} as INodeProperties;
|
||||
|
||||
const completeBeforeField = {
|
||||
displayName: 'Complete Before',
|
||||
name: 'completeBefore',
|
||||
type: 'dateTime',
|
||||
default: null,
|
||||
description: 'The latest time the task should be completed',
|
||||
} as INodeProperties;
|
||||
|
||||
const pickupTaskField = {
|
||||
displayName: 'Pick Up Task',
|
||||
name: 'pickupTask',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the task is a pickup task',
|
||||
} as INodeProperties;
|
||||
|
||||
const notesField = {
|
||||
displayName: 'Notes',
|
||||
name: 'notes',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Notes for the task',
|
||||
} as INodeProperties;
|
||||
|
||||
const quantityField = {
|
||||
displayName: 'Quantity',
|
||||
name: 'quantity',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description:
|
||||
'The number of units to be dropped off while completing this task, for route optimization purposes',
|
||||
} as INodeProperties;
|
||||
|
||||
const serviceTimeField = {
|
||||
displayName: 'Service Time',
|
||||
name: 'serviceTime',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description:
|
||||
"The number of minutes to be spent by the worker on arrival at this task's destination, for route optimization purposes",
|
||||
} as INodeProperties;
|
||||
|
||||
export const taskFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Task ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['task'],
|
||||
},
|
||||
hide: {
|
||||
operation: ['create', 'getAll'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
description: 'The ID of the task object for lookup',
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['task'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['task'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 64,
|
||||
},
|
||||
default: 64,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
...destinationExternalField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['task'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Complete as a Success',
|
||||
name: 'success',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['task'],
|
||||
operation: ['complete'],
|
||||
},
|
||||
},
|
||||
description: "Whether the task's completion was successful",
|
||||
required: true,
|
||||
default: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Filter',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['task'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'From',
|
||||
name: 'from',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description:
|
||||
'The starting time of the range. Tasks created or completed at or after this time will be included.',
|
||||
},
|
||||
{
|
||||
displayName: 'State',
|
||||
name: 'state',
|
||||
type: 'multiOptions',
|
||||
options: [
|
||||
{
|
||||
name: '[All]',
|
||||
value: 'all',
|
||||
},
|
||||
{
|
||||
name: 'Active',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
name: 'Assigned',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: 'Completed',
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
name: 'Unassigned',
|
||||
value: 0,
|
||||
},
|
||||
],
|
||||
default: ['all'],
|
||||
description: 'The state of the tasks',
|
||||
},
|
||||
{
|
||||
displayName: 'To',
|
||||
name: 'to',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'The ending time of the range. Defaults to current time if not specified.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Override Fields',
|
||||
name: 'overrideFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['task'],
|
||||
operation: ['clone'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
...completeAfterField,
|
||||
},
|
||||
{
|
||||
...completeBeforeField,
|
||||
},
|
||||
{
|
||||
displayName: 'Include Barcodes',
|
||||
name: 'includeBarcodes',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
displayName: 'Include Dependencies',
|
||||
name: 'includeDependencies',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
displayName: 'Include Metadata',
|
||||
name: 'includeMetadata',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
...notesField,
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
...pickupTaskField,
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
...serviceTimeField,
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['task'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
completeAfterField,
|
||||
completeBeforeField,
|
||||
executorIdField,
|
||||
merchantIdField,
|
||||
notesField,
|
||||
pickupTaskField,
|
||||
quantityField,
|
||||
serviceTimeField,
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['task'],
|
||||
operation: ['complete'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Notes',
|
||||
name: 'notes',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Completion Notes',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['task'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
completeAfterField,
|
||||
completeBeforeField,
|
||||
executorIdField,
|
||||
merchantIdField,
|
||||
notesField,
|
||||
pickupTaskField,
|
||||
quantityField,
|
||||
recipientExternalField,
|
||||
{
|
||||
displayName: 'Recipient Name Override',
|
||||
name: 'recipientName',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Override the recipient name for this task only',
|
||||
},
|
||||
{
|
||||
displayName: 'Recipient Notes Override',
|
||||
name: 'recipientNotes',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Override the recipient notes for this task only',
|
||||
},
|
||||
{
|
||||
displayName: 'Recipient Skip SMS Notifications Override',
|
||||
name: 'recipientSkipSMSNotifications',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether to override the recipient notification settings for this task',
|
||||
},
|
||||
serviceTimeField,
|
||||
{
|
||||
displayName: 'Use Merchant For Proxy Override',
|
||||
name: 'useMerchantForProxy',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description:
|
||||
"Whether to override the organization ID with the merchant's org ID for this task",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,554 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const teamOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['team'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Auto-Dispatch',
|
||||
value: 'autoDispatch',
|
||||
description: 'Automatically dispatch tasks assigned to a team to on-duty drivers',
|
||||
action: 'Auto-dispatch a team',
|
||||
},
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a new Onfleet team',
|
||||
action: 'Create a team',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete an Onfleet team',
|
||||
action: 'Delete a team',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a specific Onfleet team',
|
||||
action: 'Get a team',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many Onfleet teams',
|
||||
action: 'Get many teams',
|
||||
},
|
||||
{
|
||||
name: 'Get Time Estimates',
|
||||
value: 'getTimeEstimates',
|
||||
description: 'Get estimated times for upcoming tasks for a team, returns a selected driver',
|
||||
action: 'Get time estimates for a team',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update an Onfleet team',
|
||||
action: 'Update a team',
|
||||
},
|
||||
],
|
||||
default: 'getAll',
|
||||
},
|
||||
];
|
||||
|
||||
const nameField = {
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'A unique name for the team',
|
||||
} as INodeProperties;
|
||||
|
||||
const workersField = {
|
||||
displayName: 'Worker Names or IDs',
|
||||
name: 'workers',
|
||||
type: 'multiOptions',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getWorkers',
|
||||
},
|
||||
default: [],
|
||||
description:
|
||||
'A list of workers. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
} as INodeProperties;
|
||||
|
||||
const managersField = {
|
||||
displayName: 'Administrator Names or IDs',
|
||||
name: 'managers',
|
||||
type: 'multiOptions',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getAdmins',
|
||||
},
|
||||
default: [],
|
||||
description:
|
||||
'A list of managing administrators. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
} as INodeProperties;
|
||||
|
||||
const hubField = {
|
||||
displayName: 'Hub Name or ID',
|
||||
name: 'hub',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getHubs',
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'The team\'s hub. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
} as INodeProperties;
|
||||
|
||||
const enableSelfAssignmentField = {
|
||||
displayName: 'Self Assignment',
|
||||
name: 'enableSelfAssignment',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description:
|
||||
"Whether or not to allow drivers to self-assign tasks that are in the Team's unassigned container",
|
||||
} as INodeProperties;
|
||||
|
||||
const maxTasksPerRouteField = {
|
||||
displayName: 'Max Number Of Tasks Per Route',
|
||||
name: 'maxTasksPerRoute',
|
||||
type: 'number',
|
||||
default: 100,
|
||||
typeOptions: {
|
||||
maxValue: 200,
|
||||
minValue: 1,
|
||||
},
|
||||
description: 'Total number of tasks allowed on a route',
|
||||
} as INodeProperties;
|
||||
|
||||
const serviceTimeField = {
|
||||
displayName: 'Service Time',
|
||||
name: 'serviceTime',
|
||||
type: 'number',
|
||||
default: 2,
|
||||
typeOptions: {
|
||||
minValue: 0,
|
||||
},
|
||||
description:
|
||||
'The default service time to apply in Minutes to the tasks when no task service time exists',
|
||||
} as INodeProperties;
|
||||
|
||||
const routeEndField = {
|
||||
displayName: 'Route End',
|
||||
name: 'routeEnd',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Team’s Hub',
|
||||
value: 'team_hub',
|
||||
},
|
||||
{
|
||||
name: 'Worker Routing Address',
|
||||
value: 'worker_routing_address',
|
||||
},
|
||||
{
|
||||
name: 'Hub',
|
||||
value: 'hub',
|
||||
},
|
||||
{
|
||||
name: 'End Anywhere',
|
||||
value: 'anywhere',
|
||||
},
|
||||
],
|
||||
default: '',
|
||||
description: 'Where the route will end',
|
||||
} as INodeProperties;
|
||||
|
||||
const maxAllowedDelayField = {
|
||||
displayName: 'Max Allowed Delay',
|
||||
name: 'maxAllowedDelay',
|
||||
type: 'number',
|
||||
default: 10,
|
||||
description: 'Max allowed time in minutes that a task can be late',
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
},
|
||||
} as INodeProperties;
|
||||
|
||||
const longitudeDropOffField = {
|
||||
displayName: 'Drop Off Longitude',
|
||||
name: 'dropOffLongitude',
|
||||
type: 'number',
|
||||
typeOptions: {
|
||||
numberPrecision: 14,
|
||||
},
|
||||
default: 0,
|
||||
description: 'The longitude for drop off location',
|
||||
} as INodeProperties;
|
||||
|
||||
const latitudeDropOffField = {
|
||||
displayName: 'Drop Off Latitude',
|
||||
name: 'dropOffLatitude',
|
||||
type: 'number',
|
||||
typeOptions: {
|
||||
numberPrecision: 14,
|
||||
},
|
||||
default: 0,
|
||||
description: 'The latitude for drop off location',
|
||||
} as INodeProperties;
|
||||
|
||||
const longitudePickupField = {
|
||||
displayName: 'Pick Up Longitude',
|
||||
name: 'pickupLongitude',
|
||||
type: 'number',
|
||||
typeOptions: {
|
||||
numberPrecision: 14,
|
||||
},
|
||||
default: 0,
|
||||
description: 'The longitude for pickup location',
|
||||
} as INodeProperties;
|
||||
|
||||
const latitudePickupField = {
|
||||
displayName: 'Pick Up Latitude',
|
||||
name: 'pickupLatitude',
|
||||
type: 'number',
|
||||
typeOptions: {
|
||||
numberPrecision: 14,
|
||||
},
|
||||
default: 0,
|
||||
description: 'The latitude for pickup location',
|
||||
} as INodeProperties;
|
||||
|
||||
const pickupTimeField = {
|
||||
displayName: 'Pick Up Time',
|
||||
name: 'pickupTime',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description:
|
||||
'If the request includes pickupLocation, pickupTime must be present if the time is fewer than 3 hours in the future',
|
||||
} as INodeProperties;
|
||||
|
||||
const restrictedVehicleTypesField = {
|
||||
displayName: 'Restricted Vehicle Types',
|
||||
name: 'restrictedVehicleTypes',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Car',
|
||||
value: 'CAR',
|
||||
},
|
||||
{
|
||||
name: 'Motorcycle',
|
||||
value: 'MOTORCYCLE',
|
||||
},
|
||||
{
|
||||
name: 'Bicycle',
|
||||
value: 'BICYCLE',
|
||||
},
|
||||
{
|
||||
name: 'Truck',
|
||||
value: 'TRUCK',
|
||||
},
|
||||
],
|
||||
default: 'CAR',
|
||||
description: 'Vehicle types to ignore in the query',
|
||||
} as INodeProperties;
|
||||
|
||||
const serviceTimeEstimateField = {
|
||||
displayName: 'Service Time',
|
||||
name: 'serviceTime',
|
||||
type: 'number',
|
||||
default: 120,
|
||||
typeOptions: {
|
||||
minValue: 0,
|
||||
},
|
||||
description:
|
||||
'The expected time a worker will take at the pickupLocation, dropoffLocation, or both (as applicable) Unit: seconds',
|
||||
} as INodeProperties;
|
||||
|
||||
export const teamFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Team ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['team'],
|
||||
operation: ['get', 'update', 'delete', 'getTimeEstimates', 'autoDispatch'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
description: 'The ID of the team object for lookup',
|
||||
},
|
||||
{
|
||||
...nameField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['team'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...workersField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['team'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...managersField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['team'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['team'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: [hubField, enableSelfAssignmentField],
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['team'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['team'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 64,
|
||||
},
|
||||
default: 64,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['team'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
options: [managersField, hubField, nameField, enableSelfAssignmentField, workersField],
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['team'],
|
||||
operation: ['autoDispatch'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Ending Route',
|
||||
name: 'endingRoute',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Route',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Ending Route Properties',
|
||||
name: 'endingRouteProperties',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
values: [
|
||||
{
|
||||
...routeEndField,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...hubField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
routeEnd: ['hub'],
|
||||
},
|
||||
},
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
maxAllowedDelayField,
|
||||
maxTasksPerRouteField,
|
||||
{
|
||||
displayName: 'Schedule Time Window',
|
||||
name: 'scheduleTimeWindow',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Time Window',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Schedule Time Window Properties',
|
||||
name: 'scheduleTimeWindowProperties',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
values: [
|
||||
{
|
||||
displayName: 'Start Time',
|
||||
name: 'startTime',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'End Time',
|
||||
name: 'endTime',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
serviceTimeField,
|
||||
{
|
||||
displayName: 'Task Time Window',
|
||||
name: 'taskTimeWindow',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Time Window',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Task Time Window Properties',
|
||||
name: 'taskTimeWindowProperties',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
values: [
|
||||
{
|
||||
displayName: 'Start Time',
|
||||
name: 'startTime',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'End Time',
|
||||
name: 'endTime',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['team'],
|
||||
operation: ['getTimeEstimates'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Drop Off',
|
||||
name: 'dropOff',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Drop Off',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'DropOff Properties',
|
||||
name: 'dropOffProperties',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
values: [
|
||||
{
|
||||
...longitudeDropOffField,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...latitudeDropOffField,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Pick Up',
|
||||
name: 'pickUp',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
placeholder: 'Add Pick Up',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Pick Up Properties',
|
||||
name: 'pickUpProperties',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
values: [
|
||||
{
|
||||
...longitudePickupField,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...latitudePickupField,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...pickupTimeField,
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
...restrictedVehicleTypesField,
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
...serviceTimeEstimateField,
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,139 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { webhookMapping } from '../WebhookMapping';
|
||||
|
||||
export const webhookOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['webhook'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a new Onfleet webhook',
|
||||
action: 'Create a webhook',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete an Onfleet webhook',
|
||||
action: 'Delete a webhook',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many Onfleet webhooks',
|
||||
action: 'Get many webhooks',
|
||||
},
|
||||
],
|
||||
default: 'getAll',
|
||||
},
|
||||
];
|
||||
|
||||
const urlField = {
|
||||
displayName: 'URL',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'The URL that Onfleet should issue a request against as soon as the trigger condition is met. It must be HTTPS and have a valid certificate.',
|
||||
} as INodeProperties;
|
||||
|
||||
const nameField = {
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'A name for the webhook for identification',
|
||||
} as INodeProperties;
|
||||
|
||||
const triggerField = {
|
||||
displayName: 'Trigger',
|
||||
name: 'trigger',
|
||||
type: 'options',
|
||||
options: Object.entries(webhookMapping).map(([_key, value]) => {
|
||||
return {
|
||||
name: value.name,
|
||||
value: value.key,
|
||||
};
|
||||
}),
|
||||
default: '',
|
||||
description: 'The number corresponding to the trigger condition on which the webhook should fire',
|
||||
} as INodeProperties;
|
||||
|
||||
const thresholdField = {
|
||||
displayName: 'Threshold',
|
||||
name: 'threshold',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description:
|
||||
'For trigger Task Eta, the time threshold in seconds; for trigger Task Arrival, the distance threshold in meters',
|
||||
} as INodeProperties;
|
||||
|
||||
export const webhookFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Webhook ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['webhook'],
|
||||
operation: ['delete'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
description: 'The ID of the webhook object for lookup',
|
||||
},
|
||||
{
|
||||
...urlField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['webhook'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...nameField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['webhook'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...triggerField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['webhook'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['webhook'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: [thresholdField],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,676 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const workerOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a new Onfleet worker',
|
||||
action: 'Create a worker',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete an Onfleet worker',
|
||||
action: 'Delete a worker',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a specific Onfleet worker',
|
||||
action: 'Get a worker',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many Onfleet workers',
|
||||
action: 'Get many workers',
|
||||
},
|
||||
{
|
||||
name: 'Get Schedule',
|
||||
value: 'getSchedule',
|
||||
description: 'Get a specific Onfleet worker schedule',
|
||||
action: 'Get the schedule for a worker',
|
||||
},
|
||||
// {
|
||||
// name: 'Set Worker\'s Schedule',
|
||||
// value: 'setSchedule',
|
||||
// description: 'Set the worker\'s schedule',
|
||||
// },
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update an Onfleet worker',
|
||||
action: 'Update a worker',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
const byLocationField = {
|
||||
displayName: 'Search by Location',
|
||||
name: 'byLocation',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description:
|
||||
'Whether to search for only those workers who are currently within a certain target area',
|
||||
} as INodeProperties;
|
||||
|
||||
const nameField = {
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: "The worker's name",
|
||||
} as INodeProperties;
|
||||
|
||||
const phoneField = {
|
||||
displayName: 'Phone',
|
||||
name: 'phone',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'A list of worker’s phone numbers',
|
||||
} as INodeProperties;
|
||||
|
||||
const capacityField = {
|
||||
displayName: 'Capacity',
|
||||
name: 'capacity',
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'The maximum number of units this worker can carry, for route optimization purposes',
|
||||
} as INodeProperties;
|
||||
|
||||
const displayNameField = {
|
||||
displayName: 'Display Name',
|
||||
name: 'displayName',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
"This value is used in place of the worker's actual name within sms notifications, delivery tracking pages, and across organization boundaries",
|
||||
} as INodeProperties;
|
||||
|
||||
const vehicleTypeField = {
|
||||
displayName: 'Type',
|
||||
name: 'type',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Bicycle',
|
||||
value: 'BICYCLE',
|
||||
},
|
||||
{
|
||||
name: 'Car',
|
||||
value: 'CAR',
|
||||
},
|
||||
{
|
||||
name: 'Motorcycle',
|
||||
value: 'MOTORCYCLE',
|
||||
},
|
||||
{
|
||||
name: 'Truck',
|
||||
value: 'TRUCK',
|
||||
},
|
||||
],
|
||||
default: '',
|
||||
description:
|
||||
"Whether the worker has vehicle or not. If it's not provided, this worker will be treated as if on foot.",
|
||||
} as INodeProperties;
|
||||
|
||||
const vehicleDescriptionField = {
|
||||
displayName: 'Description',
|
||||
name: 'description',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: "The vehicle's make, model, year, or any other relevant identifying details",
|
||||
} as INodeProperties;
|
||||
|
||||
const vehicleLicensePlateField = {
|
||||
displayName: 'License Plate',
|
||||
name: 'licensePlate',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: "The vehicle's license plate number",
|
||||
} as INodeProperties;
|
||||
|
||||
const vehicleColorField = {
|
||||
displayName: 'Color',
|
||||
name: 'color',
|
||||
// eslint-disable-next-line n8n-nodes-base/node-param-color-type-unused
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: "The vehicle's color",
|
||||
} as INodeProperties;
|
||||
|
||||
const teamsField = {
|
||||
displayName: 'Team Names or IDs',
|
||||
name: 'teams',
|
||||
type: 'multiOptions',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getTeams',
|
||||
},
|
||||
default: [],
|
||||
description:
|
||||
'One or more teams of which the worker is a member. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
} as INodeProperties;
|
||||
|
||||
const teamsFilterField = {
|
||||
displayName: 'Team Names or IDs',
|
||||
name: 'teams',
|
||||
type: 'multiOptions',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getTeams',
|
||||
},
|
||||
default: [],
|
||||
description:
|
||||
'A list of the teams that workers must be part of. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
} as INodeProperties;
|
||||
|
||||
const statesFilterField = {
|
||||
displayName: 'States',
|
||||
name: 'states',
|
||||
type: 'multiOptions',
|
||||
options: [
|
||||
{
|
||||
name: 'Active (On-Duty, Active Task)',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
name: 'Idle (On-Duty, No Active Task)',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: 'Off-Duty',
|
||||
value: 0,
|
||||
},
|
||||
],
|
||||
default: [],
|
||||
description: 'List of worker states',
|
||||
} as INodeProperties;
|
||||
|
||||
const phonesFilterField = {
|
||||
displayName: 'Phones',
|
||||
name: 'phones',
|
||||
type: 'string',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add Phone',
|
||||
},
|
||||
default: [],
|
||||
description: "A list of workers' phone numbers",
|
||||
} as INodeProperties;
|
||||
|
||||
const filterField = {
|
||||
displayName: 'Fields to Return',
|
||||
name: 'filter',
|
||||
type: 'multiOptions',
|
||||
options: [
|
||||
{
|
||||
name: 'Account Status',
|
||||
value: 'accountStatus',
|
||||
},
|
||||
{
|
||||
name: 'Active Task',
|
||||
value: 'activeTask',
|
||||
},
|
||||
{
|
||||
name: 'Capacity',
|
||||
value: 'capacity',
|
||||
},
|
||||
{
|
||||
name: 'Delay Time',
|
||||
value: 'delayTime',
|
||||
},
|
||||
{
|
||||
name: 'Display Name',
|
||||
value: 'displayName',
|
||||
},
|
||||
{
|
||||
name: 'Image Url',
|
||||
value: 'imageUrl',
|
||||
},
|
||||
{
|
||||
name: 'Location',
|
||||
value: 'location',
|
||||
},
|
||||
{
|
||||
name: 'Metadata',
|
||||
value: 'metadata',
|
||||
},
|
||||
{
|
||||
name: 'Name',
|
||||
value: 'name',
|
||||
},
|
||||
{
|
||||
name: 'On Duty',
|
||||
value: 'onDuty',
|
||||
},
|
||||
{
|
||||
name: 'Organization',
|
||||
value: 'organization',
|
||||
},
|
||||
{
|
||||
name: 'Phone',
|
||||
value: 'phone',
|
||||
},
|
||||
{
|
||||
name: 'Tasks',
|
||||
value: 'tasks',
|
||||
},
|
||||
{
|
||||
name: 'Teams',
|
||||
value: 'teams',
|
||||
},
|
||||
{
|
||||
name: 'Time Created',
|
||||
value: 'timeCreated',
|
||||
},
|
||||
{
|
||||
name: 'Time Last Modified',
|
||||
value: 'timeLastModified',
|
||||
},
|
||||
{
|
||||
name: 'Time Last Seen',
|
||||
value: 'timeLastSeen',
|
||||
},
|
||||
{
|
||||
name: 'User Data',
|
||||
value: 'userData',
|
||||
},
|
||||
{
|
||||
name: 'Vehicle',
|
||||
value: 'vehicle',
|
||||
},
|
||||
{
|
||||
name: 'Worker ID',
|
||||
value: 'id',
|
||||
},
|
||||
],
|
||||
default: [],
|
||||
description: 'A list of fields to show in the response, if all are not desired',
|
||||
} as INodeProperties;
|
||||
|
||||
const longitudeFilterField = {
|
||||
displayName: 'Longitude',
|
||||
name: 'longitude',
|
||||
type: 'number',
|
||||
typeOptions: {
|
||||
numberPrecision: 14,
|
||||
},
|
||||
default: 0,
|
||||
description: 'The longitude component of the coordinate pair',
|
||||
} as INodeProperties;
|
||||
|
||||
const latitudeFilterField = {
|
||||
displayName: 'Latitude',
|
||||
name: 'latitude',
|
||||
type: 'number',
|
||||
typeOptions: {
|
||||
numberPrecision: 14,
|
||||
},
|
||||
default: 0,
|
||||
description: 'The latitude component of the coordinate pair',
|
||||
} as INodeProperties;
|
||||
|
||||
const radiusFilterField = {
|
||||
displayName: 'Radius',
|
||||
name: 'radius',
|
||||
type: 'number',
|
||||
typeOptions: {
|
||||
maxValue: 10000,
|
||||
minValue: 0,
|
||||
},
|
||||
default: 1000,
|
||||
description:
|
||||
'The length in meters of the radius of the spherical area in which to look for workers. Defaults to 1000 if missing. Maximum value is 10000.',
|
||||
} as INodeProperties;
|
||||
|
||||
const scheduleDateField = {
|
||||
displayName: 'Date',
|
||||
name: 'date',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: "Schedule's date",
|
||||
} as INodeProperties;
|
||||
|
||||
const scheduleTimezoneField = {
|
||||
displayName: 'Timezone Name or ID',
|
||||
name: 'timezone',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getTimezones',
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'A valid timezone. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
} as INodeProperties;
|
||||
|
||||
const scheduleStartField = {
|
||||
displayName: 'Start',
|
||||
name: 'start',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'Start time',
|
||||
} as INodeProperties;
|
||||
|
||||
const scheduleEndField = {
|
||||
displayName: 'End',
|
||||
name: 'end',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'End time',
|
||||
} as INodeProperties;
|
||||
|
||||
export const workerFields: INodeProperties[] = [
|
||||
{
|
||||
...byLocationField,
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Worker ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['get', 'getSchedule', 'setSchedule', 'update', 'delete'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
description: 'The ID of the worker object for lookup',
|
||||
},
|
||||
{
|
||||
...nameField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...phoneField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...teamsField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...longitudeFilterField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['getAll'],
|
||||
byLocation: [true],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...latitudeFilterField,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['getAll'],
|
||||
byLocation: [true],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 64,
|
||||
},
|
||||
default: 64,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
capacityField,
|
||||
displayNameField,
|
||||
{
|
||||
displayName: 'Vehicle',
|
||||
name: 'vehicle',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Vehicle',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Vehicle Properties',
|
||||
name: 'vehicleProperties',
|
||||
values: [
|
||||
{
|
||||
...vehicleTypeField,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...vehicleDescriptionField,
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
...vehicleLicensePlateField,
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
...vehicleColorField,
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
options: [capacityField, displayNameField, nameField, teamsField],
|
||||
},
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['getAll'],
|
||||
byLocation: [true],
|
||||
},
|
||||
},
|
||||
options: [radiusFilterField],
|
||||
},
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['getAll'],
|
||||
byLocation: [false],
|
||||
},
|
||||
},
|
||||
options: [statesFilterField, teamsFilterField, phonesFilterField],
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
options: [filterField],
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Analytics',
|
||||
name: 'analytics',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description:
|
||||
'Whether a more detailed response is needed, includes basic worker duty event, traveled distance (meters) and time analytics',
|
||||
},
|
||||
{
|
||||
...filterField,
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Schedule',
|
||||
name: 'schedule',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Schedule',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['worker'],
|
||||
operation: ['setSchedule'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add Schedule',
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Schedule Properties',
|
||||
name: 'scheduleProperties',
|
||||
default: {},
|
||||
values: [
|
||||
{
|
||||
...scheduleDateField,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...scheduleTimezoneField,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Shifts',
|
||||
name: 'shifts',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
placeholder: 'Add Shift',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Shifts Properties',
|
||||
name: 'shiftsProperties',
|
||||
default: {},
|
||||
values: [
|
||||
{
|
||||
...scheduleStartField,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
...scheduleEndField,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,184 @@
|
||||
export interface OnfleetRecipient {
|
||||
name?: string;
|
||||
phone?: string;
|
||||
notes?: string;
|
||||
skipSMSNotifications?: boolean;
|
||||
skipPhoneNumberValidation?: boolean;
|
||||
}
|
||||
|
||||
export interface OnfleetDestinationAddress {
|
||||
name?: string;
|
||||
number?: string;
|
||||
street?: string;
|
||||
apartment?: string;
|
||||
city?: string;
|
||||
state?: string;
|
||||
postalCode?: string;
|
||||
country?: string;
|
||||
unparsed?: string;
|
||||
}
|
||||
|
||||
export interface OnfleetDestinationOptions {
|
||||
language?: string;
|
||||
}
|
||||
|
||||
export interface OnfleetDestination {
|
||||
address: OnfleetDestinationAddress;
|
||||
location?: [number, number];
|
||||
notes?: string;
|
||||
options?: OnfleetDestinationOptions;
|
||||
}
|
||||
|
||||
export interface OnfleetTask {
|
||||
merchant?: string;
|
||||
executor?: string;
|
||||
destination: OnfleetDestination;
|
||||
recipients: OnfleetRecipient[];
|
||||
completeAfter?: number;
|
||||
completeBefore?: number;
|
||||
pickupTask?: boolean;
|
||||
notes?: string;
|
||||
quantity?: number;
|
||||
serviceTime?: number;
|
||||
}
|
||||
|
||||
export interface OnfleetTaskUpdate {
|
||||
merchant?: string;
|
||||
executor?: string;
|
||||
completeAfter?: number;
|
||||
completeBefore?: number;
|
||||
pickupTask?: boolean;
|
||||
notes?: string;
|
||||
quantity?: number;
|
||||
serviceTime?: number;
|
||||
}
|
||||
|
||||
export interface OnfleetListTaskFilters {
|
||||
from?: number;
|
||||
to?: number;
|
||||
lastId?: string;
|
||||
state?: string;
|
||||
worker?: string;
|
||||
completeBeforeBefore?: number;
|
||||
completeAfterAfter?: number;
|
||||
dependencies?: string;
|
||||
}
|
||||
|
||||
export interface OnfleetCloneOverrideTaskOptions {
|
||||
completeAfter?: number;
|
||||
completeBefore?: number;
|
||||
destination?: OnfleetDestination;
|
||||
notes?: string;
|
||||
pickupTask?: boolean;
|
||||
recipients?: OnfleetRecipient[];
|
||||
serviceTime?: number;
|
||||
}
|
||||
|
||||
export interface OnfleetCloneTaskOptions {
|
||||
includeMetadata?: boolean;
|
||||
includeBarcodes?: boolean;
|
||||
includeDependencies?: boolean;
|
||||
overrides?: OnfleetCloneOverrideTaskOptions;
|
||||
}
|
||||
|
||||
export interface OnfleetCloneTask {
|
||||
options?: OnfleetCloneTaskOptions;
|
||||
}
|
||||
|
||||
export interface OnfleetTaskCompletionDetails {
|
||||
success: boolean;
|
||||
notes?: string;
|
||||
}
|
||||
|
||||
export interface OnfleetTaskComplete {
|
||||
completionDetails: OnfleetTaskCompletionDetails;
|
||||
}
|
||||
|
||||
export interface OnfleetAdmins {
|
||||
name?: string;
|
||||
email?: string;
|
||||
phone?: string;
|
||||
isReadOnly?: boolean;
|
||||
}
|
||||
|
||||
export interface OnfleetHubs extends OnfleetDestination {
|
||||
name?: string;
|
||||
teams?: string[];
|
||||
}
|
||||
|
||||
export interface OnfleetVehicle {
|
||||
type?: string;
|
||||
description?: string;
|
||||
licensePlate?: string;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export interface OnfleetWorker {
|
||||
name?: string;
|
||||
phone?: string;
|
||||
vehicle?: OnfleetVehicle;
|
||||
teams?: string[];
|
||||
capacity?: number;
|
||||
displayName?: string;
|
||||
}
|
||||
|
||||
export interface OnfleetWorkerFilter {
|
||||
[key: string]: string | undefined;
|
||||
filter?: string;
|
||||
teams?: string;
|
||||
states?: string;
|
||||
phones?: string;
|
||||
analytics?: string;
|
||||
}
|
||||
|
||||
export interface OnfleetWorkerScheduleEntry {
|
||||
date?: string;
|
||||
timezone?: string;
|
||||
shifts?: [[number, number]];
|
||||
}
|
||||
|
||||
export interface OnfleetWebhook {
|
||||
url?: string;
|
||||
name?: string;
|
||||
trigger?: number;
|
||||
threshold?: number;
|
||||
}
|
||||
|
||||
export interface OnfleetTeams {
|
||||
name?: string;
|
||||
workers?: string[];
|
||||
managers?: string[];
|
||||
hub?: string;
|
||||
enableSelfAssignment?: boolean;
|
||||
}
|
||||
|
||||
export interface OnfleetWorkerSchedule {
|
||||
entries: OnfleetWorkerScheduleEntry[];
|
||||
}
|
||||
|
||||
export interface OnfleetWebhookMapping {
|
||||
key: number;
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface OnfleetWebhooksMapping {
|
||||
[key: string]: OnfleetWebhookMapping;
|
||||
}
|
||||
|
||||
export interface OnfleetWorkerEstimates {
|
||||
dropoffLocation?: string;
|
||||
pickupLocation?: string;
|
||||
pickupTime?: number;
|
||||
restrictedVehicleTypes?: string;
|
||||
serviceTime?: number;
|
||||
}
|
||||
|
||||
export interface OnfleetTeamAutoDispatch {
|
||||
maxTasksPerRoute?: number;
|
||||
taskTimeWindow?: [number, number];
|
||||
scheduleTimeWindow?: [number, number];
|
||||
serviceTime?: number;
|
||||
routeEnd?: string;
|
||||
maxAllowedDelay?: number;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import type { IWebhookFunctions } from 'n8n-workflow';
|
||||
|
||||
import { OnfleetTrigger } from '../OnfleetTrigger.node';
|
||||
|
||||
describe('Onfleet Trigger Node', () => {
|
||||
let node: OnfleetTrigger;
|
||||
let mockWebhookFunctions: IWebhookFunctions;
|
||||
|
||||
beforeEach(() => {
|
||||
node = new OnfleetTrigger();
|
||||
mockWebhookFunctions = {
|
||||
getWebhookName: jest.fn(),
|
||||
getRequestObject: jest.fn(),
|
||||
getResponseObject: jest.fn(),
|
||||
getBodyData: jest.fn(),
|
||||
helpers: {
|
||||
returnJsonArray: jest.fn().mockImplementation((data) => [{ json: data }]),
|
||||
},
|
||||
} as unknown as IWebhookFunctions;
|
||||
});
|
||||
|
||||
describe('webhook', () => {
|
||||
describe('setup webhook validation', () => {
|
||||
it('should respond with text/plain content type and check query parameter', async () => {
|
||||
const mockRequest = {
|
||||
query: {
|
||||
check: 'validation-token-123',
|
||||
},
|
||||
};
|
||||
|
||||
const mockResponse = {
|
||||
status: jest.fn().mockReturnThis(),
|
||||
type: jest.fn().mockReturnThis(),
|
||||
send: jest.fn().mockReturnThis(),
|
||||
};
|
||||
|
||||
(mockWebhookFunctions.getWebhookName as jest.Mock).mockReturnValue('setup');
|
||||
(mockWebhookFunctions.getRequestObject as jest.Mock).mockReturnValue(mockRequest);
|
||||
(mockWebhookFunctions.getResponseObject as jest.Mock).mockReturnValue(mockResponse);
|
||||
|
||||
const result = await node.webhook.call(mockWebhookFunctions);
|
||||
|
||||
expect(mockResponse.status).toHaveBeenCalledWith(200);
|
||||
expect(mockResponse.type).toHaveBeenCalledWith('text/plain');
|
||||
expect(mockResponse.send).toHaveBeenCalledWith('validation-token-123');
|
||||
expect(result).toEqual({ noWebhookResponse: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe('default webhook', () => {
|
||||
it('should process incoming webhook data', async () => {
|
||||
const mockRequestData = {
|
||||
taskId: 'task123',
|
||||
workerId: 'worker456',
|
||||
actionContext: 'COMPLETE',
|
||||
};
|
||||
|
||||
const mockRequest = {
|
||||
query: {},
|
||||
};
|
||||
|
||||
(mockWebhookFunctions.getWebhookName as jest.Mock).mockReturnValue('default');
|
||||
(mockWebhookFunctions.getRequestObject as jest.Mock).mockReturnValue(mockRequest);
|
||||
(mockWebhookFunctions.getBodyData as jest.Mock).mockReturnValue(mockRequestData);
|
||||
|
||||
const result = await node.webhook.call(mockWebhookFunctions);
|
||||
|
||||
expect(result).toEqual({
|
||||
workflowData: [[{ json: mockRequestData }]],
|
||||
});
|
||||
expect(mockWebhookFunctions.helpers.returnJsonArray).toHaveBeenCalledWith(mockRequestData);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user