diff --git a/packages/nodes-base/nodes/Onfleet/GenericFunctions.ts b/packages/nodes-base/nodes/Onfleet/GenericFunctions.ts index f4c2f99f829bd..02e93879dcd48 100644 --- a/packages/nodes-base/nodes/Onfleet/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Onfleet/GenericFunctions.ts @@ -21,17 +21,22 @@ import * as moment from 'moment-timezone'; export async function onfleetApiRequest( this: IWebhookFunctions | IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions, method: string, - apikey: string, resource: string, body: any = {}, // tslint:disable-line:no-any qs?: any, // tslint:disable-line:no-any uri?: string): Promise { // tslint:disable-line:no-any + + const credentials = await this.getCredentials('onfleetApi') as ICredentialDataDecryptedObject; + const options: OptionsWithUri = { headers: { 'Content-Type': 'application/json', - 'Authorization': `Basic ${apikey}`, 'User-Agent': 'n8n-onfleet', }, + auth: { + user: credentials.apiKey as string, + pass: '', + }, method, body, qs, @@ -42,17 +47,41 @@ export async function onfleetApiRequest( //@ts-ignore return await this.helpers.request(options); } catch (error) { - throw new NodeApiError(this.getNode(), error as JsonObject); + console.log(error.message); + //throw new NodeApiError(this.getNode(), error as JsonObject); } } +export async function onfleetApiRequestAllItems( + this: IExecuteFunctions | ILoadOptionsFunctions, + propertyName: string, + method: string, + apiKey: string, + endpoint: string, + // tslint:disable-next-line: no-any + body: any = {}, + query: IDataObject = {}, +): Promise { // tslint:disable-line:no-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]); + } while ( + responseData['lastId'] !== undefined + ); + + return returnData; +} export const resourceLoaders = { async getTeams(this: ILoadOptionsFunctions): Promise { try { - const credentials = await this.getCredentials('onfleetApi') as ICredentialDataDecryptedObject; - const encodedApiKey = Buffer.from(`${credentials.apiKey}:`).toString('base64'); - const teams = await onfleetApiRequest.call(this, 'GET', encodedApiKey, 'teams') as IDataObject[]; - return teams.map(({name = '', id: value = ''}) => ( {name, value} )) as INodePropertyOptions[]; + const teams = await onfleetApiRequest.call(this, 'GET', 'teams') as IDataObject[]; + return teams.map(({ name = '', id: value = '' }) => ({ name, value })) as INodePropertyOptions[]; } catch (error) { return []; } @@ -60,32 +89,26 @@ export const resourceLoaders = { async getWorkers(this: ILoadOptionsFunctions): Promise { try { - const credentials = await this.getCredentials('onfleetApi') as ICredentialDataDecryptedObject; - const encodedApiKey = Buffer.from(`${credentials.apiKey}:`).toString('base64'); - const workers = await onfleetApiRequest.call(this, 'GET', encodedApiKey, 'workers') as IDataObject[]; - return workers.map(({name = '', id: value = ''}) => ( {name, value} )) as INodePropertyOptions[]; + 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 { + async getAdmins(this: ILoadOptionsFunctions): Promise { try { - const credentials = await this.getCredentials('onfleetApi') as ICredentialDataDecryptedObject; - const encodedApiKey = Buffer.from(`${credentials.apiKey}:`).toString('base64'); - const admins = await onfleetApiRequest.call(this, 'GET', encodedApiKey, 'admins') as IDataObject[]; - return admins.map(({name = '', id: value = ''}) => ( {name, value} )) as INodePropertyOptions[]; + 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 { + async getHubs(this: ILoadOptionsFunctions): Promise { try { - const credentials = await this.getCredentials('onfleetApi') as ICredentialDataDecryptedObject; - const encodedApiKey = Buffer.from(`${credentials.apiKey}:`).toString('base64'); - const hubs = await onfleetApiRequest.call(this, 'GET', encodedApiKey, 'hubs') as IDataObject[]; - return hubs.map(({name = '', id: value = ''}) => ( {name, value} )) as INodePropertyOptions[]; + const hubs = await onfleetApiRequest.call(this, 'GET', 'hubs') as IDataObject[]; + return hubs.map(({ name = '', id: value = '' }) => ({ name, value })) as INodePropertyOptions[]; } catch (error) { return []; } diff --git a/packages/nodes-base/nodes/Onfleet/Onfleet.node.ts b/packages/nodes-base/nodes/Onfleet/Onfleet.node.ts index 2acf8a10b8c6e..3db311ebd411a 100644 --- a/packages/nodes-base/nodes/Onfleet/Onfleet.node.ts +++ b/packages/nodes-base/nodes/Onfleet/Onfleet.node.ts @@ -1,5 +1,4 @@ import { - ICredentialDataDecryptedObject, ICredentialsDecrypted, ICredentialTestFunctions, IDataObject, @@ -9,7 +8,6 @@ import { NodeCredentialTestResult, NodeOperationError, } from 'n8n-workflow'; -import * as moment from 'moment-timezone'; import { OnfleetAdmins, @@ -25,7 +23,6 @@ import { OnfleetTaskUpdate, OnfleetTeamAutoDispatch, OnfleetTeams, - OnfleetVehicle, OnfleetWebhook, OnfleetWorker, OnfleetWorkerEstimates, @@ -33,162 +30,185 @@ import { OnfleetWorkerSchedule, OnfleetWorkerScheduleEntry } from './interfaces'; -import { taskFields, taskOperations } from './descriptions/TaskDescription'; -import { IExecuteFunctions } from 'n8n-core'; +import { + taskFields, + taskOperations, +} from './descriptions/TaskDescription'; + +import { + IExecuteFunctions, +} from 'n8n-core'; + import { destinationFields, destinationOperations, } from './descriptions/DestinationDescription'; + import { onfleetApiRequest, + onfleetApiRequestAllItems, resourceLoaders, } from './GenericFunctions'; + import { recipientFields, recipientOperations, } from './descriptions/RecipientDescription'; + import { organizationFields, organizationOperations, } from './descriptions/OrganizationDescription'; + import { adminFields, adminOperations, } from './descriptions/AdministratorDescription'; + import { hubFields, hubOperations, } from './descriptions/HubDescription'; + import { workerFields, workerOperations, } from './descriptions/WorkerDescription'; + import { webhookFields, webhookOperations, } from './descriptions/WebhookDescription'; + import { containerFields, containerOperations, } from './descriptions/ContainerDescription'; + import { teamFields, teamOperations, } from './descriptions/TeamDescription'; -import { OptionsWithUri } from 'request'; +import { + OptionsWithUri, +} from 'request'; + +import * as moment from 'moment-timezone'; 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: 'Onfleet API', - defaults: { - color: '#AA81F3', - description: 'Use the Onfleet API', - name: 'Onfleet', - testedBy: 'onfeletApiTest', + displayName: 'Onfleet', + name: 'onfleet', + icon: 'file:Onfleet.svg', + group: ['input'], + version: 1, + subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', + description: 'Onfleet API', + defaults: { + color: '#AA81F3', + description: 'Use the Onfleet API', + name: 'Onfleet', + testedBy: 'onfeletApiTest', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'onfleetApi', + required: true, }, - inputs: [ 'main' ], - outputs: [ 'main' ], - credentials: [ - { - name: 'onfleetApi', - required: true, - }, - ], - properties: [ - // List of option resources - { - displayName: 'Resource', - name: 'resource', - type: 'options', - 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, - ], + ], + properties: [ + // List of option resources + { + displayName: 'Resource', + name: 'resource', + type: 'options', + 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 onfeletApiTest(this: ICredentialTestFunctions, credential: ICredentialsDecrypted): Promise { const credentials = credential.data as IDataObject; - const encodedApiKey = Buffer.from(`${credentials.apiKey}:`).toString('base64'); const options: OptionsWithUri = { headers: { 'Content-Type': 'application/json', - 'Authorization': `Basic ${encodedApiKey}`, 'User-Agent': 'n8n-onfleet', }, + auth: { + user: credentials.apiKey as string, + pass: '', + }, method: 'GET', uri: 'https://onfleet.com/api/v2/auth/test', json: true, @@ -222,7 +242,7 @@ export class Onfleet implements INodeType { * @param additionalFields Destination additional fields * @returns */ - static formatAddress ( + static formatAddress( unparsed: boolean, address: string | undefined, addressNumber: string | undefined, @@ -365,7 +385,7 @@ export class Onfleet implements INodeType { * @param operation Current hub operation * @returns {OnfleetHubs|null} Hub information */ - static getHubFields(this: IExecuteFunctions, item: number, operation: string): OnfleetHubs | null { + static getHubFields(this: IExecuteFunctions, item: number, operation: string): OnfleetHubs | null { if (operation === 'create') { /* -------------------------------------------------------------------------- */ /* Get fields for create hub */ @@ -402,7 +422,7 @@ export class Onfleet implements INodeType { * @param operation Current worker operation * @returns {OnfleetWorker|OnfleetWorkerFilter|OnfleetWorkerSchedule|null} Worker information */ - static getWorkerFields(this: IExecuteFunctions, item: number, operation: string): OnfleetWorker | OnfleetWorkerFilter | OnfleetWorkerSchedule | null { + static getWorkerFields(this: IExecuteFunctions, item: number, operation: string): OnfleetWorker | OnfleetWorkerFilter | OnfleetWorkerSchedule | null { if (operation === 'create') { /* -------------------------------------------------------------------------- */ /* Get fields for create worker */ @@ -428,41 +448,50 @@ export class Onfleet implements INodeType { /* -------------------------------------------------------------------------- */ /* Get fields for update worker */ /* -------------------------------------------------------------------------- */ - const {vehicleProperties} = this.getNodeParameter('vehicle', item) as IDataObject; - const { additionalFields: vehicle = {} } = vehicleProperties as IDataObject; - const workerData: OnfleetWorker = { vehicle: (vehicle as OnfleetVehicle) }; + + const workerData: OnfleetWorker = {}; // Adding additional fields const updateFields = this.getNodeParameter('updateFields', item) as IDataObject; - Object.assign(workerData, updateFields); + Object.assign(workerData, updateFields); return workerData; - } else if (['getAll', 'get'].includes(operation)) { + } else if (operation === 'get') { + const options = this.getNodeParameter('options', item, {}) as IDataObject; + const workerFilter: OnfleetWorkerFilter = {}; + if (options.filter) { + options.filter = (options.filter as string[]).join(','); + } + if (typeof options.analytics === 'boolean') { + options.analytics = options.analytics ? 'true' : 'false'; + } + Object.assign(workerFilter, options); + return workerFilter; + + } else if (operation === 'getAll') { /* -------------------------------------------------------------------------- */ /* Get fields for get and getAll workers */ /* -------------------------------------------------------------------------- */ - const { - filter, states, teams, phones, analytics, ...filterFields - } = this.getNodeParameter('filterFields', item) as IDataObject; + + const options = this.getNodeParameter('options', item, {}) as IDataObject; + const filters = this.getNodeParameter('filters', item, {}) as IDataObject; const workerFilter: OnfleetWorkerFilter = {}; - if (states) { - filterFields.states = (states as number[]).join(','); - } - if (filter) { - filterFields.filter = (filter as string[]).join(','); + if (filters.states) { + filters.states = (filters.states as number[]).join(','); } - if (teams) { - filterFields.teams = (teams as string[]).join(','); + if (filters.teams) { + filters.teams = (filters.teams as string[]).join(','); } - if (phones) { - filterFields.phones = (phones as string[]).join(','); + if (filters.phones) { + filters.phones = (filters.phones as string[]).join(','); } - if (typeof analytics === 'boolean') { - filterFields.analytics = analytics ? 'true' : 'false'; + if (options.filter) { + options.filter = (options.filter as string[]).join(','); } - Object.assign(workerFilter, filterFields); + Object.assign(workerFilter, options); + Object.assign(workerFilter, filters); return workerFilter; } else if (operation === 'setSchedule') { /* -------------------------------------------------------------------------- */ @@ -475,7 +504,7 @@ export class Onfleet implements INodeType { return { timezone: timezone as string, date: moment(new Date(date as Date)).format('YYYY-MM-DD'), - shifts: (shiftsProperties as IDataObject[]).map(({ start, end}) => [ + shifts: (shiftsProperties as IDataObject[]).map(({ start, end }) => [ new Date(start as Date).getTime(), new Date(end as Date).getTime(), ]), @@ -492,7 +521,7 @@ export class Onfleet implements INodeType { * @param operation Current webhooks operation * @returns {OnfleetWebhook} Webhooks information */ - static getWebhookFields(this: IExecuteFunctions, item: number, operation: string): OnfleetWebhook | null { + static getWebhookFields(this: IExecuteFunctions, item: number, operation: string): OnfleetWebhook | null { if (operation === 'create') { /* -------------------------------------------------------------------------- */ /* Get fields for create webhook */ @@ -599,7 +628,7 @@ export class Onfleet implements INodeType { * @returns {OnfleetListTaskFilters | OnfleetTask } Task information */ static getTaskFields(this: IExecuteFunctions, item: number, operation: string): - OnfleetListTaskFilters | OnfleetTask | OnfleetCloneTask | OnfleetTaskComplete | OnfleetTaskUpdate | null { + OnfleetListTaskFilters | OnfleetTask | OnfleetCloneTask | OnfleetTaskComplete | OnfleetTaskUpdate | null { if (operation === 'create') { /* -------------------------------------------------------------------------- */ /* Get fields to create a task */ @@ -610,7 +639,7 @@ export class Onfleet implements INodeType { // Adding recipients information const recipient = Onfleet.getRecipientFields.call(this, item, operation, true) as OnfleetRecipient; - const taskData: OnfleetTask = { destination, recipients: [ recipient ] }; + const taskData: OnfleetTask = { destination, recipients: [recipient] }; const { completeAfter = null, completeBefore = null, ...extraFields } = additionalFields; if (completeAfter) taskData.completeAfter = new Date(completeAfter as Date).getTime(); if (completeBefore) taskData.completeBefore = new Date(completeBefore as Date).getTime(); @@ -635,9 +664,9 @@ export class Onfleet implements INodeType { const additionalFields = this.getNodeParameter('additionalFields', item) as IDataObject; const options: OnfleetCloneTaskOptions = {}; - if (additionalFields.includeMetadata) options.includeMetadata = additionalFields.includeMetadata as boolean; - if (additionalFields.includeBarcodes) options.includeBarcodes = additionalFields.includeBarcodes as boolean; - if (additionalFields.includeDependencies) options.includeDependencies = additionalFields.includeDependencies as boolean; + if (additionalFields.includeMetadata) options.includeMetadata = additionalFields.includeMetadata as boolean; + if (additionalFields.includeBarcodes) options.includeBarcodes = additionalFields.includeBarcodes as boolean; + if (additionalFields.includeDependencies) options.includeDependencies = additionalFields.includeDependencies as boolean; // Adding overrides data const { @@ -645,11 +674,11 @@ export class Onfleet implements INodeType { } = additionalFields as IDataObject; const overridesData = {} as OnfleetCloneOverrideTaskOptions; - if (notes) overridesData.notes = notes as string; - if (typeof pickupTask !== 'undefined') overridesData.pickupTask = pickupTask as boolean; - if (serviceTime) overridesData.serviceTime = serviceTime as number; - if (completeAfter) overridesData.completeAfter = new Date(completeAfter as Date).getTime(); - if (completeBefore) overridesData.completeBefore = new Date(completeBefore as Date).getTime(); + if (notes) overridesData.notes = notes as string; + if (typeof pickupTask !== 'undefined') overridesData.pickupTask = pickupTask as boolean; + if (serviceTime) overridesData.serviceTime = serviceTime as number; + if (completeAfter) overridesData.completeAfter = new Date(completeAfter as Date).getTime(); + if (completeBefore) overridesData.completeBefore = new Date(completeBefore as Date).getTime(); if (overridesData && Object.keys(overridesData).length > 0) { options.overrides = overridesData; @@ -661,13 +690,15 @@ export class Onfleet implements INodeType { /* Get fields to list tasks */ /* -------------------------------------------------------------------------- */ const filters = this.getNodeParameter('filters', item) as IDataObject; - const listTaskData: OnfleetListTaskFilters = { }; + const listTaskData: OnfleetListTaskFilters = {}; - const twoWeeksInMilisecods = () => (604800 * 60); + const twoWeeksInMilisecods = () => (604800 * 1000); // Adding extra fields to search tasks if (filters.from) { - listTaskData.from = new Date(filters.to as Date).getTime() - twoWeeksInMilisecods(); + listTaskData.from = new Date(filters.from as Date).getTime(); + } else { + listTaskData.from = new Date().getTime() - twoWeeksInMilisecods(); } if (filters.to) { listTaskData.to = new Date(filters.to as Date).getTime(); @@ -675,12 +706,9 @@ export class Onfleet implements INodeType { if (filters.state) { listTaskData.state = (filters.state as number[]).join(','); } - if (filters.lastId) { - listTaskData.lastId = filters.lastId as string; - } return listTaskData; - } else if (operation === 'complete') { + } else if (operation === 'complete') { /* -------------------------------------------------------------------------- */ /* Get fields to complete a task */ /* -------------------------------------------------------------------------- */ @@ -699,7 +727,7 @@ export class Onfleet implements INodeType { * @param operation Current team operation * @returns {OnfleetTeams} Team information */ - static getTeamFields(this: IExecuteFunctions, item: number, operation: string): OnfleetTeams | OnfleetWorkerEstimates | OnfleetTeamAutoDispatch | null { + static getTeamFields(this: IExecuteFunctions, item: number, operation: string): OnfleetTeams | OnfleetWorkerEstimates | OnfleetTeamAutoDispatch | null { if (operation === 'create') { /* -------------------------------------------------------------------------- */ /* Get fields to create a team */ @@ -728,8 +756,8 @@ export class Onfleet implements INodeType { /* Get driver time estimates for tasks that haven't been created yet */ /* -------------------------------------------------------------------------- */ const { dropOff = {}, pickUp = {}, ...additionalFields } = this.getNodeParameter('additionalFields', item) as IDataObject; - const { dropOffProperties = {} }= dropOff as IDataObject; - const { pickUpProperties = {} }= pickUp as IDataObject; + const { dropOffProperties = {} } = dropOff as IDataObject; + const { pickUpProperties = {} } = pickUp as IDataObject; const hasPickUp = pickUp && Object.keys(pickUpProperties as IDataObject).length > 0; const hasDropOff = dropOffProperties && Object.keys(dropOffProperties as IDataObject).length > 0; @@ -749,8 +777,8 @@ export class Onfleet implements INodeType { workerTimeEstimates.pickupTime = moment(new Date(pickupTime as Date)).local().unix(); } } - if(hasDropOff) { - const { dropOffLongitude: longitude, dropOffLatitude: latitude} = dropOffProperties as IDataObject; + if (hasDropOff) { + const { dropOffLongitude: longitude, dropOffLatitude: latitude } = dropOffProperties as IDataObject; workerTimeEstimates.dropoffLocation = `${longitude},${latitude}`; } @@ -803,7 +831,6 @@ export class Onfleet implements INodeType { * @param resource Resource to be executed (Task) * @param operation Operation to be executed * @param items Number of items to process by the node - * @param encodedApiKey API KEY for the current organization * @returns Task information */ static async executeTaskOperations( @@ -811,15 +838,14 @@ export class Onfleet implements INodeType { resource: string, operation: string, items: INodeExecutionData[], - encodedApiKey: string, - ): Promise { + ): Promise { if (operation === 'create' && Object.keys(items).length > 1) { /* -------------------------------------------------------------------------- */ /* Create multiple tasks by batch */ /* -------------------------------------------------------------------------- */ const path = `${resource}/batch`; const tasksData = { tasks: items.map((_item, index) => Onfleet.getTaskFields.call(this, index, operation)) }; - const { tasks: tasksCreated } = await onfleetApiRequest.call(this, 'POST', encodedApiKey, path, tasksData); + const { tasks: tasksCreated } = await onfleetApiRequest.call(this, 'POST', path, tasksData); return tasksCreated; } @@ -832,8 +858,8 @@ export class Onfleet implements INodeType { /* Create a new task */ /* -------------------------------------------------------------------------- */ const taskData = Onfleet.getTaskFields.call(this, index, operation); - if (!taskData) { continue ;} - responseData.push(await onfleetApiRequest.call(this, 'POST', encodedApiKey, resource, taskData)); + if (!taskData) { continue; } + responseData.push(await onfleetApiRequest.call(this, 'POST', resource, taskData)); } else if (operation === 'get') { /* -------------------------------------------------------------------------- */ /* Get a single task */ @@ -841,23 +867,23 @@ export class Onfleet implements INodeType { const id = this.getNodeParameter('id', index) as string; const shortId = String(id).length <= 8; const path = `${resource}${(shortId ? '/shortId' : '')}/${id}`; - responseData.push(await onfleetApiRequest.call(this, 'GET', encodedApiKey, path)); + responseData.push(await onfleetApiRequest.call(this, 'GET', path)); } else if (operation === 'clone') { /* -------------------------------------------------------------------------- */ /* Clone a task */ /* -------------------------------------------------------------------------- */ - const id = this.getNodeParameter('id', index) as string; - const taskData = Onfleet.getTaskFields.call(this, index, operation) as any; - if (!taskData) { continue; } - const path = `${resource}/${id}/clone`; - responseData.push(await onfleetApiRequest.call(this, 'POST', encodedApiKey, path, taskData)); + const id = this.getNodeParameter('id', index) as string; + const taskData = Onfleet.getTaskFields.call(this, index, operation) as any; + if (!taskData) { continue; } + const path = `${resource}/${id}/clone`; + responseData.push(await onfleetApiRequest.call(this, 'POST', path, taskData)); } else if (operation === 'delete') { /* -------------------------------------------------------------------------- */ /* Delete a single task */ /* -------------------------------------------------------------------------- */ const id = this.getNodeParameter('id', index) as string; const path = `${resource}/${id}`; - await onfleetApiRequest.call(this, 'DELETE', encodedApiKey, path); + await onfleetApiRequest.call(this, 'DELETE', path); responseData.push({ success: true }); } else if (operation === 'getAll') { /* -------------------------------------------------------------------------- */ @@ -865,9 +891,17 @@ export class Onfleet implements INodeType { /* -------------------------------------------------------------------------- */ const taskData = Onfleet.getTaskFields.call(this, 0, operation) as IDataObject; if (!taskData) return []; - + const returnAll = this.getNodeParameter('returnAll', 0, false); const path = `${resource}/all`; - const { tasks = [] } = await onfleetApiRequest.call(this, 'GET', encodedApiKey, path, {}, taskData); + let tasks; + if (returnAll === true) { + tasks = await onfleetApiRequestAllItems.call(this, 'tasks', 'GET', path, {}, taskData); + } else { + const limit = this.getNodeParameter('limit', 0); + tasks = await onfleetApiRequest.call(this, 'GET', path, {}, taskData); + tasks = tasks.tasks; + tasks = tasks.splice(0, limit); + } responseData.push(...tasks); } else if (operation === 'complete') { /* -------------------------------------------------------------------------- */ @@ -877,7 +911,7 @@ export class Onfleet implements INodeType { const taskData = Onfleet.getTaskFields.call(this, index, operation); if (!taskData) { continue; } const path = `${resource}/${id}/complete`; - await onfleetApiRequest.call(this, 'POST', encodedApiKey, path, taskData); + await onfleetApiRequest.call(this, 'POST', path, taskData); responseData.push({ success: true }); } else if (operation === 'update') { /* -------------------------------------------------------------------------- */ @@ -887,17 +921,16 @@ export class Onfleet implements INodeType { const path = `${resource}/${id}`; const taskData = Onfleet.getTaskFields.call(this, index, operation); if (!taskData) { continue; } - responseData.push(await onfleetApiRequest.call(this, 'PUT', encodedApiKey, path, taskData)); + responseData.push(await onfleetApiRequest.call(this, 'PUT', path, taskData)); } } catch (error) { if (this.continueOnFail()) { responseData.push({ error: (error as IDataObject).toString() }); + continue; } + throw error; } } - if (['delete', 'complete'].includes(operation)) { - return { success: true }; - } return responseData; } @@ -906,7 +939,6 @@ export class Onfleet implements INodeType { * @param resource Resource to be executed (Destination) * @param operation Operation to be executed * @param items Number of items to process by the node - * @param encodedApiKey API KEY for the current organization * @returns Destination information */ static async executeDestinationOperations( @@ -914,8 +946,7 @@ export class Onfleet implements INodeType { resource: string, operation: string, items: INodeExecutionData[], - encodedApiKey: string, - ): Promise { + ): Promise { const responseData = []; for (const key of Object.keys(items)) { const index = Number(key); @@ -926,19 +957,21 @@ export class Onfleet implements INodeType { /* -------------------------------------------------------------------------- */ const destinationData = Onfleet.getDestinationFields.call(this, index, operation); if (!destinationData) { continue; } - responseData.push(await onfleetApiRequest.call(this, 'POST', encodedApiKey, resource, destinationData)); + responseData.push(await onfleetApiRequest.call(this, 'POST', resource, destinationData)); } else if (operation === 'get') { /* -------------------------------------------------------------------------- */ /* Get single destination */ /* -------------------------------------------------------------------------- */ const id = this.getNodeParameter('id', index) as string; const path = `${resource}/${id}`; - responseData.push(await onfleetApiRequest.call(this, 'GET', encodedApiKey, path)); + responseData.push(await onfleetApiRequest.call(this, 'GET', path)); } } catch (error) { if (this.continueOnFail()) { responseData.push({ error: (error as IDataObject).toString() }); + continue; } + throw error; } } @@ -950,16 +983,14 @@ export class Onfleet implements INodeType { * @param resource Resource to be executed (Organization) * @param operation Operation to be executed * @param items Number of items to process by the node - * @param encodedApiKey API KEY for the current organization * @returns Organization information */ - static async executeOrganizationOperations( + static async executeOrganizationOperations( this: IExecuteFunctions, resource: string, operation: string, items: INodeExecutionData[], - encodedApiKey: string, - ): Promise { + ): Promise { const responseData = []; for (const key of Object.keys(items)) { const index = Number(key); @@ -969,19 +1000,21 @@ export class Onfleet implements INodeType { /* Get organization details */ /* -------------------------------------------------------------------------- */ const path = 'organization'; - responseData.push(await onfleetApiRequest.call(this, 'GET', encodedApiKey, path)); + responseData.push(await onfleetApiRequest.call(this, 'GET', path)); } else if (operation === 'getDelegatee') { /* -------------------------------------------------------------------------- */ /* Get organization delegatee */ /* -------------------------------------------------------------------------- */ const id = this.getNodeParameter('id', index) as string; const path = `${resource}/${id}`; - responseData.push(await onfleetApiRequest.call(this, 'GET', encodedApiKey, path)); + responseData.push(await onfleetApiRequest.call(this, 'GET', path)); } } catch (error) { if (this.continueOnFail()) { responseData.push({ error: (error as IDataObject).toString() }); + continue; } + throw error; } } @@ -993,15 +1026,13 @@ export class Onfleet implements INodeType { * @param resource Resource to be executed (Recipient) * @param operation Operation to be executed * @param items Number of items to process by the node - * @param encodedApiKey API KEY for the current organization * @returns Recipient information */ static async executeRecipientOperations(this: IExecuteFunctions, resource: string, operation: string, items: INodeExecutionData[], - encodedApiKey: string, - ): Promise { + ): Promise { const responseData = []; for (const key of Object.keys(items)) { const index = Number(key); @@ -1012,7 +1043,7 @@ export class Onfleet implements INodeType { /* -------------------------------------------------------------------------- */ const recipientData = Onfleet.getRecipientFields.call(this, index, operation); if (!recipientData) { continue; } - responseData.push(await onfleetApiRequest.call(this, 'POST', encodedApiKey, resource, recipientData)); + responseData.push(await onfleetApiRequest.call(this, 'POST', resource, recipientData)); } else if (operation === 'update') { /* -------------------------------------------------------------------------- */ /* Update a recipient */ @@ -1021,7 +1052,7 @@ export class Onfleet implements INodeType { if (!recipientData) { continue; } const id = this.getNodeParameter('id', index) as string; const path = `${resource}/${id}`; - responseData.push(await onfleetApiRequest.call(this, 'PUT', encodedApiKey, path, recipientData)); + responseData.push(await onfleetApiRequest.call(this, 'PUT', path, recipientData)); } else if (operation === 'get') { /* -------------------------------------------------------------------------- */ /* Get recipient information */ @@ -1029,12 +1060,14 @@ export class Onfleet implements INodeType { const lookupBy = this.getNodeParameter('getBy', index) as string; const lookupByValue = this.getNodeParameter(lookupBy, index) as string; const path = `${resource}${lookupBy === 'id' ? '' : ('/' + lookupBy)}/${lookupByValue}`; - responseData.push(await onfleetApiRequest.call(this, 'GET', encodedApiKey, path)); + responseData.push(await onfleetApiRequest.call(this, 'GET', path)); } } catch (error) { if (this.continueOnFail()) { responseData.push({ error: (error as IDataObject).toString() }); + continue; } + throw error; } } @@ -1046,16 +1079,14 @@ export class Onfleet implements INodeType { * @param resource Resource to be executed (Administrator) * @param operation Operation to be executed * @param items Number of items to process by the node - * @param encodedApiKey API KEY for the current organization * @returns Administrator information */ - static async executeAdministratorOperations( + static async executeAdministratorOperations( this: IExecuteFunctions, resource: string, operation: string, items: INodeExecutionData[], - encodedApiKey: string, - ): Promise { + ): Promise { const responseData = []; for (const key of Object.keys(items)) { const index = Number(key); @@ -1064,13 +1095,20 @@ export class Onfleet implements INodeType { /* -------------------------------------------------------------------------- */ /* Get administrators */ /* -------------------------------------------------------------------------- */ - responseData.push(...await onfleetApiRequest.call(this, 'GET', encodedApiKey, resource)); + + const returnAll = this.getNodeParameter('returnAll', 0, false); + let adminUsers = await onfleetApiRequest.call(this, 'GET', resource); + if (!returnAll) { + const limit = this.getNodeParameter('limit', 0); + adminUsers = adminUsers.slice(0, limit); + } + responseData.push(...adminUsers); } else if (operation === 'create') { /* -------------------------------------------------------------------------- */ /* Create a new admin */ /* -------------------------------------------------------------------------- */ const adminData = Onfleet.getAdminFields.call(this, index, operation); - responseData.push(await onfleetApiRequest.call(this, 'POST', encodedApiKey, resource, adminData)); + responseData.push(await onfleetApiRequest.call(this, 'POST', resource, adminData)); } else if (operation === 'update') { /* -------------------------------------------------------------------------- */ /* Update admin */ @@ -1078,26 +1116,24 @@ export class Onfleet implements INodeType { const id = this.getNodeParameter('id', index) as string; const adminData = Onfleet.getAdminFields.call(this, index, operation); const path = `${resource}/${id}`; - responseData.push(await onfleetApiRequest.call(this, 'PUT', encodedApiKey, path, adminData)); + responseData.push(await onfleetApiRequest.call(this, 'PUT', path, adminData)); } else if (operation === 'delete') { /* -------------------------------------------------------------------------- */ /* Delete admin */ /* -------------------------------------------------------------------------- */ const id = this.getNodeParameter('id', index) as string; const path = `${resource}/${id}`; - await onfleetApiRequest.call(this, 'DELETE', encodedApiKey, path); + await onfleetApiRequest.call(this, 'DELETE', path); responseData.push({ success: true }); } } catch (error) { if (this.continueOnFail()) { responseData.push({ error: (error as IDataObject).toString() }); + continue; } + throw error; } } - if (operation === 'delete') { - return { success: true }; - } - return responseData; } @@ -1106,16 +1142,14 @@ export class Onfleet implements INodeType { * @param resource Resource to be executed (Hub) * @param operation Operation to be executed * @param items Number of items to process by the node - * @param encodedApiKey API KEY for the current organization * @returns Hub information */ - static async executeHubOperations( + static async executeHubOperations( this: IExecuteFunctions, resource: string, operation: string, items: INodeExecutionData[], - encodedApiKey: string, - ): Promise { + ): Promise { const responseData = []; for (const key of Object.keys(items)) { const index = Number(key); @@ -1124,13 +1158,20 @@ export class Onfleet implements INodeType { /* -------------------------------------------------------------------------- */ /* Get all hubs */ /* -------------------------------------------------------------------------- */ - responseData.push(...await onfleetApiRequest.call(this, 'GET', encodedApiKey, resource)); + + const returnAll = this.getNodeParameter('returnAll', 0, false); + let hubs = await onfleetApiRequest.call(this, 'GET', resource); + if (returnAll === false) { + const limit = this.getNodeParameter('limit', 0); + hubs = hubs.slice(0, limit); + } + responseData.push(...hubs); } else if (operation === 'create') { /* -------------------------------------------------------------------------- */ /* Create a new hub */ /* -------------------------------------------------------------------------- */ const hubData = Onfleet.getHubFields.call(this, index, operation); - responseData.push(await onfleetApiRequest.call(this, 'POST', encodedApiKey, resource, hubData)); + responseData.push(await onfleetApiRequest.call(this, 'POST', resource, hubData)); } if (operation === 'update') { /* -------------------------------------------------------------------------- */ @@ -1139,12 +1180,14 @@ export class Onfleet implements INodeType { const id = this.getNodeParameter('id', index) as string; const hubData = Onfleet.getHubFields.call(this, index, operation); const path = `${resource}/${id}`; - responseData.push(await onfleetApiRequest.call(this, 'PUT', encodedApiKey, path, hubData)); + responseData.push(await onfleetApiRequest.call(this, 'PUT', path, hubData)); } } catch (error) { if (this.continueOnFail()) { responseData.push({ error: (error as IDataObject).toString() }); + continue; } + throw error; } } @@ -1156,16 +1199,14 @@ export class Onfleet implements INodeType { * @param resource Resource to be executed (Worker) * @param operation Operation to be executed * @param items Number of items to process by the node - * @param encodedApiKey API KEY for the current organization * @returns Workers information */ - static async executeWorkerOperations( + static async executeWorkerOperations( this: IExecuteFunctions, resource: string, operation: string, items: INodeExecutionData[], - encodedApiKey: string, - ): Promise { + ): Promise { const responseData = []; for (const key of Object.keys(items)) { const index = Number(key); @@ -1175,21 +1216,30 @@ export class Onfleet implements INodeType { /* Get all workers */ /* -------------------------------------------------------------------------- */ const byLocation = this.getNodeParameter('byLocation', index) as boolean; + const returnAll = this.getNodeParameter('returnAll', index, false) as boolean; + let workers; if (byLocation) { const longitude = this.getNodeParameter('longitude', index) as string; const latitude = this.getNodeParameter('latitude', index) as number; - const filterFields = this.getNodeParameter('filterFields', index) as IDataObject; + const filters = this.getNodeParameter('filters', index) as IDataObject; const path = `${resource}/location`; - const { workers } = await onfleetApiRequest.call( - this, 'GET', encodedApiKey, path, {}, { longitude, latitude, ...filterFields}, + workers = await onfleetApiRequest.call( + this, 'GET', path, {}, { longitude, latitude, ...filters }, ); - responseData.push(...workers); + workers = workers.workers; } else { const workerFilters = Onfleet.getWorkerFields.call(this, 0, operation) as OnfleetWorkerFilter; + workers = await onfleetApiRequest.call(this, 'GET', resource, {}, workerFilters); + } - responseData.push(... await onfleetApiRequest.call(this, 'GET', encodedApiKey, resource, {}, workerFilters)); + if (!returnAll) { + const limit = this.getNodeParameter('limit', index) as number; + workers = workers.slice(0, limit); } + + responseData.push(...workers); + } else if (operation === 'get') { /* -------------------------------------------------------------------------- */ /* Get a worker */ @@ -1198,13 +1248,13 @@ export class Onfleet implements INodeType { const workerFilters = Onfleet.getWorkerFields.call(this, index, operation) as OnfleetWorkerFilter; const path = `${resource}/${id}`; - responseData.push(await onfleetApiRequest.call(this, 'GET', encodedApiKey, path, {}, workerFilters)); + responseData.push(await onfleetApiRequest.call(this, 'GET', path, {}, workerFilters)); } else if (operation === 'create') { /* -------------------------------------------------------------------------- */ /* Create a new worker */ /* -------------------------------------------------------------------------- */ const workerData = Onfleet.getWorkerFields.call(this, index, operation); - responseData.push(await onfleetApiRequest.call(this, 'POST', encodedApiKey, resource, workerData)); + responseData.push(await onfleetApiRequest.call(this, 'POST', resource, workerData)); } else if (operation === 'update') { /* -------------------------------------------------------------------------- */ /* Update worker */ @@ -1212,14 +1262,14 @@ export class Onfleet implements INodeType { const id = this.getNodeParameter('id', index) as string; const workerData = Onfleet.getWorkerFields.call(this, index, operation); const path = `${resource}/${id}`; - responseData.push(await onfleetApiRequest.call(this, 'PUT', encodedApiKey, path, workerData)); + responseData.push(await onfleetApiRequest.call(this, 'PUT', path, workerData)); } else if (operation === 'delete') { /* -------------------------------------------------------------------------- */ /* Delete worker */ /* -------------------------------------------------------------------------- */ const id = this.getNodeParameter('id', index) as string; const path = `${resource}/${id}`; - await onfleetApiRequest.call(this, 'DELETE', encodedApiKey, path); + await onfleetApiRequest.call(this, 'DELETE', path); responseData.push({ success: true }); } else if (operation === 'getSchedule') { /* -------------------------------------------------------------------------- */ @@ -1227,7 +1277,7 @@ export class Onfleet implements INodeType { /* -------------------------------------------------------------------------- */ const id = this.getNodeParameter('id', index) as string; const path = `${resource}/${id}/schedule`; - responseData.push(await onfleetApiRequest.call(this, 'GET', encodedApiKey, path)); + responseData.push(await onfleetApiRequest.call(this, 'GET', path)); } else if (operation === 'setSchedule') { /* -------------------------------------------------------------------------- */ /* Set a worker schedule */ @@ -1235,18 +1285,16 @@ export class Onfleet implements INodeType { const id = this.getNodeParameter('id', index) as string; const workerSchedule = Onfleet.getWorkerFields.call(this, index, operation) as OnfleetWorkerSchedule; const path = `${resource}/${id}/schedule`; - responseData.push(await onfleetApiRequest.call(this, 'POST', encodedApiKey, path, workerSchedule)); + responseData.push(await onfleetApiRequest.call(this, 'POST', path, workerSchedule)); } } catch (error) { if (this.continueOnFail()) { responseData.push({ error: (error as IDataObject).toString() }); + continue; } + throw error; } } - if (operation === 'delete') { - return { success: true }; - } - return responseData; } @@ -1255,16 +1303,14 @@ export class Onfleet implements INodeType { * @param resource Resource to be executed (Webhook) * @param operation Operation to be executed * @param items Number of items to process by the node - * @param encodedApiKey API KEY for the current organization * @returns Webhook information */ - static async executeWebhookOperations( + static async executeWebhookOperations( this: IExecuteFunctions, resource: string, operation: string, items: INodeExecutionData[], - encodedApiKey: string, - ): Promise { + ): Promise { const responseData = []; for (const key of Object.keys(items)) { const index = Number(key); @@ -1273,31 +1319,30 @@ export class Onfleet implements INodeType { /* -------------------------------------------------------------------------- */ /* Get all webhooks */ /* -------------------------------------------------------------------------- */ - responseData.push(...await onfleetApiRequest.call(this, 'GET', encodedApiKey, resource)); + responseData.push(...await onfleetApiRequest.call(this, 'GET', resource)); } else if (operation === 'create') { /* -------------------------------------------------------------------------- */ /* Create a new webhook */ /* -------------------------------------------------------------------------- */ const webhookData = Onfleet.getWebhookFields.call(this, index, operation); - responseData.push(await onfleetApiRequest.call(this, 'POST', encodedApiKey, resource, webhookData)); + responseData.push(await onfleetApiRequest.call(this, 'POST', resource, webhookData)); } else if (operation === 'delete') { /* -------------------------------------------------------------------------- */ /* Delete a webhook */ /* -------------------------------------------------------------------------- */ const id = this.getNodeParameter('id', index) as string; const path = `${resource}/${id}`; - await onfleetApiRequest.call(this, 'DELETE', encodedApiKey, path) + await onfleetApiRequest.call(this, 'DELETE', path); responseData.push({ success: true }); } } catch (error) { if (this.continueOnFail()) { responseData.push({ error: (error as IDataObject).toString() }); + continue; } + throw error; } } - if (operation === 'delete') { - return { success: true }; - } return responseData; } @@ -1307,16 +1352,14 @@ export class Onfleet implements INodeType { * @param resource Resource to be executed (Container) * @param operation Operation to be executed * @param items Number of items to process by the node - * @param encodedApiKey API KEY for the current organization * @returns Container information */ - static async executeContainerOperations( + static async executeContainerOperations( this: IExecuteFunctions, resource: string, operation: string, items: INodeExecutionData[], - encodedApiKey: string, - ): Promise { + ): Promise { const responseData = []; for (const key of Object.keys(items)) { const index = Number(key); @@ -1328,7 +1371,7 @@ export class Onfleet implements INodeType { const containerId = this.getNodeParameter('containerId', index) as string; const containerType = this.getNodeParameter('containerType', index) as string; const path = `${resource}/${containerType}/${containerId}`; - responseData.push(await onfleetApiRequest.call(this, 'GET', encodedApiKey, path)); + responseData.push(await onfleetApiRequest.call(this, 'GET', path)); } else if (['add', 'update'].includes(operation)) { /* -------------------------------------------------------------------------- */ /* Add or update tasks to container */ @@ -1337,7 +1380,7 @@ export class Onfleet implements INodeType { const containerType = this.getNodeParameter('containerType', index) as string; const options = this.getNodeParameter('options', index) as IDataObject; - const tasks = this.getNodeParameter('tasks', index) as Array; + const tasks = this.getNodeParameter('tasks', index) as Array; if (operation === 'add') { const type = this.getNodeParameter('type', index) as number; if (type === 1) { @@ -1350,13 +1393,15 @@ export class Onfleet implements INodeType { const path = `${resource}/${containerType}/${containerId}`; responseData.push( - await onfleetApiRequest.call(this, 'PUT', encodedApiKey, path, { tasks, ...options }), + await onfleetApiRequest.call(this, 'PUT', path, { tasks, ...options }), ); } } catch (error) { if (this.continueOnFail()) { responseData.push({ error: (error as IDataObject).toString() }); + continue; } + throw error; } } @@ -1368,16 +1413,14 @@ export class Onfleet implements INodeType { * @param resource Resource to be executed (Team) * @param operation Operation to be executed * @param items Number of items to process by the node - * @param encodedApiKey API KEY for the current organization * @returns Team information */ - static async executeTeamOperations( + static async executeTeamOperations( this: IExecuteFunctions, resource: string, operation: string, items: INodeExecutionData[], - encodedApiKey: string, - ): Promise { + ): Promise { const responseData = []; for (const key of Object.keys(items)) { const index = Number(key); @@ -1386,20 +1429,20 @@ export class Onfleet implements INodeType { /* -------------------------------------------------------------------------- */ /* Get all teams */ /* -------------------------------------------------------------------------- */ - responseData.push(...await onfleetApiRequest.call(this, 'GET', encodedApiKey, resource)); + responseData.push(...await onfleetApiRequest.call(this, 'GET', resource)); } else if (operation === 'get') { /* -------------------------------------------------------------------------- */ /* Get a single team */ /* -------------------------------------------------------------------------- */ const id = this.getNodeParameter('id', index) as string; const path = `${resource}/${id}`; - responseData.push(await onfleetApiRequest.call(this, 'GET', encodedApiKey, path)); + responseData.push(await onfleetApiRequest.call(this, 'GET', path)); } else if (operation === 'create') { /* -------------------------------------------------------------------------- */ /* Create a new team */ /* -------------------------------------------------------------------------- */ const teamData = Onfleet.getTeamFields.call(this, index, operation); - responseData.push(await onfleetApiRequest.call(this, 'POST', encodedApiKey, resource, teamData)); + responseData.push(await onfleetApiRequest.call(this, 'POST', resource, teamData)); } else if (operation === 'update') { /* -------------------------------------------------------------------------- */ /* Update a team */ @@ -1407,14 +1450,14 @@ export class Onfleet implements INodeType { const id = this.getNodeParameter('id', index) as string; const teamData = Onfleet.getTeamFields.call(this, index, operation); const path = `${resource}/${id}`; - responseData.push(await onfleetApiRequest.call(this, 'PUT', encodedApiKey, path, teamData)); + responseData.push(await onfleetApiRequest.call(this, 'PUT', path, teamData)); } else if (operation === 'delete') { /* -------------------------------------------------------------------------- */ /* Delete a team */ /* -------------------------------------------------------------------------- */ const id = this.getNodeParameter('id', index) as string; const path = `${resource}/${id}`; - await onfleetApiRequest.call(this, 'DELETE', encodedApiKey, path); + await onfleetApiRequest.call(this, 'DELETE', path); responseData.push({ success: true }); } else if (operation === 'getTimeEstimates') { /* -------------------------------------------------------------------------- */ @@ -1423,7 +1466,7 @@ export class Onfleet implements INodeType { const id = this.getNodeParameter('id', index) as string; const workerTimeEstimates = Onfleet.getTeamFields.call(this, index, operation) as OnfleetWorkerSchedule; const path = `${resource}/${id}/estimate`; - responseData.push(await onfleetApiRequest.call(this, 'GET', encodedApiKey, path, {}, workerTimeEstimates)); + responseData.push(await onfleetApiRequest.call(this, 'GET', path, {}, workerTimeEstimates)); } else if (operation === 'autoDispatch') { /* -------------------------------------------------------------------------- */ /* Dynamically dispatching tasks on the fly */ @@ -1431,17 +1474,16 @@ export class Onfleet implements INodeType { const id = this.getNodeParameter('id', index) as string; const teamAutoDispatch = Onfleet.getTeamFields.call(this, index, operation) as OnfleetWorkerSchedule; const path = `${resource}/${id}/dispatch`; - responseData.push(await onfleetApiRequest.call(this, 'POST', encodedApiKey, path, teamAutoDispatch)); + responseData.push(await onfleetApiRequest.call(this, 'POST', path, teamAutoDispatch)); } } catch (error) { if (this.continueOnFail()) { responseData.push({ error: (error as IDataObject).toString() }); + continue; } + throw error; } } - if (operation === 'delete') { - return { success: true }; - } return responseData; } @@ -1450,11 +1492,8 @@ export class Onfleet implements INodeType { const resource = this.getNodeParameter('resource', 0) as string; const operation = this.getNodeParameter('operation', 0) as string; const items = this.getInputData(); - //Get credentials the user provided for this node - const credentials = await this.getCredentials('onfleetApi') as ICredentialDataDecryptedObject; - const encodedApiKey = Buffer.from(`${credentials.apiKey}:`).toString('base64'); - const operations: { [ key:string ]: Function} = { + const operations: { [key: string]: Function } = { task: Onfleet.executeTaskOperations, destination: Onfleet.executeDestinationOperations, organization: Onfleet.executeOrganizationOperations, @@ -1467,9 +1506,9 @@ export class Onfleet implements INodeType { team: Onfleet.executeTeamOperations, }; - const responseData = await operations[resource].call(this, `${resource}s`, operation, items, encodedApiKey); + const responseData = await operations[resource].call(this, `${resource}s`, operation, items); + // Map data to n8n data return [this.helpers.returnJsonArray(responseData)]; } - } diff --git a/packages/nodes-base/nodes/Onfleet/OnfleetTrigger.node.ts b/packages/nodes-base/nodes/Onfleet/OnfleetTrigger.node.ts index 0be93880d169e..bfd1210cb9c38 100644 --- a/packages/nodes-base/nodes/Onfleet/OnfleetTrigger.node.ts +++ b/packages/nodes-base/nodes/Onfleet/OnfleetTrigger.node.ts @@ -19,16 +19,25 @@ import { eventDisplay, eventNameField, } from './descriptions/OnfleetWebhookDescription'; -import { onfleetApiRequest } from './GenericFunctions'; -import { webhookMapping } from './WebhookMapping'; -import { OptionsWithUri } from 'request'; + +import { + onfleetApiRequest, +} from './GenericFunctions'; + +import { + webhookMapping, +} from './WebhookMapping'; + +import { + OptionsWithUri, +} from 'request'; export class OnfleetTrigger implements INodeType { description: INodeTypeDescription = { displayName: 'Onfleet Trigger', name: 'onfleetTrigger', icon: 'file:Onfleet.svg', - group: [ 'trigger' ], + group: ['trigger'], version: 1, subtitle: '={{$parameter["events"]}}', description: 'Starts the workflow when Onfleet events occur', @@ -38,23 +47,24 @@ export class OnfleetTrigger implements INodeType { description: 'Handle Onfleet events via webhooks', }, inputs: [], - outputs: [ 'main' ], + outputs: ['main'], credentials: [ { name: 'onfleetApi', required: true, + testedBy: 'onfeletApiTest', }, ], webhooks: [ { - name: 'default', - httpMethod: 'POST', + name: 'setup', + httpMethod: 'GET', responseMode: 'onReceived', path: 'webhook', }, { - name: 'validate', - httpMethod: 'GET', + name: 'default', + httpMethod: 'POST', responseMode: 'onReceived', path: 'webhook', }, @@ -69,15 +79,17 @@ export class OnfleetTrigger implements INodeType { credentialTest: { async onfeletApiTest(this: ICredentialTestFunctions, credential: ICredentialsDecrypted): Promise { const credentials = credential.data as IDataObject; - const encodedApiKey = Buffer.from(`${credentials.apiKey}:`).toString('base64'); const options: OptionsWithUri = { headers: { 'Content-Type': 'application/json', - 'Authorization': `Basic ${encodedApiKey}`, 'User-Agent': 'n8n-onfleet', }, method: 'GET', + auth: { + user: credentials.apiKey as string, + pass: '', + }, uri: 'https://onfleet.com/api/v2/auth/test', json: true, }; @@ -102,110 +114,69 @@ export class OnfleetTrigger implements INodeType { webhookMethods = { default: { async checkExists(this: IHookFunctions): Promise { - const { name = '' } = this.getNodeParameter('additionalFields', 0) as IDataObject; - const credentials = await this.getCredentials('onfleetApi') as ICredentialDataDecryptedObject; - const encodedApiKey = Buffer.from(`${credentials.apiKey}:`).toString('base64'); - const event = this.getNodeParameter('event', 0) as string; + const event = this.getNodeParameter('event') as string; const webhookData = this.getWorkflowStaticData('node') as IDataObject; const webhookUrl = this.getNodeWebhookUrl('default') as string; - if (!webhookData[event] || typeof webhookData[event] !== 'string') { - // No webhook id is set so no webhook can exist - return false; - } - // Webhook got created before so check if it still exists const endpoint = '/webhooks'; - try { - const webhooks = await onfleetApiRequest.call(this, 'GET', encodedApiKey, endpoint); - // tslint:disable-next-line: no-any - const exist = webhooks.some((webhook: any) => webhook.url === webhookUrl); - - // Changing the name if it's different - // tslint:disable-next-line: no-any - const webhook = webhooks.find((webhook: any) => webhook.url === webhookUrl); - - // Webhook name according to the field - let newWebhookName = `[N8N] ${webhookMapping[event].name}`; - if (name) { - newWebhookName = `[N8N] ${name}`; - } + const webhooks = await onfleetApiRequest.call(this, 'GET', endpoint); - // If webhook name is different so, it's updated - if (webhook && webhook.name !== newWebhookName) { - const path = `${endpoint}/${webhook.id}`; - await onfleetApiRequest.call(this, 'PUT', encodedApiKey, path, { name: newWebhookName }); + for (const webhook of webhooks) { + if (webhook.url === webhookUrl && webhook.trigger === event) { + webhookData.webhookId = webhook.id; + return true; } - return exist; - } catch (error) { - const { httpCode = '' } = error as { httpCode: string }; - if (httpCode === '404') { - // Webhook does not exist - delete webhookData[event]; - return false; - } - - // Some error occurred - throw error; } - + return false; }, async create(this: IHookFunctions): Promise { - const { name = '' } = this.getNodeParameter('additionalFields', 0) as IDataObject; - const credentials = await this.getCredentials('onfleetApi') as ICredentialDataDecryptedObject; - const encodedApiKey = Buffer.from(`${credentials.apiKey}:`).toString('base64'); - const event = this.getNodeParameter('event', 0) as string; + const { name = '' } = this.getNodeParameter('additionalFields') as IDataObject; + const event = this.getNodeParameter('event') as string; + const webhookData = this.getWorkflowStaticData('node') as IDataObject; const webhookUrl = this.getNodeWebhookUrl('default') as string; if (webhookUrl.includes('//localhost')) { throw new NodeOperationError(this.getNode(), 'The Webhook can not work on "localhost". Please, either setup n8n on a custom domain or start with "--tunnel"!'); } - // Webhook name according to the field - let newWebhookName = `[N8N] ${webhookMapping[event].name}`; + let newWebhookName = `n8n-webhook:${webhookUrl}`; + if (name) { - newWebhookName = `[N8N] ${name}`; + newWebhookName = `n8n-webhook:${name}`; } const path = `/webhooks`; const body = { - name : newWebhookName, - url : webhookUrl, - trigger : webhookMapping[event].key, + name: newWebhookName, + url: webhookUrl, + trigger: webhookMapping[event].key, }; try { - onfleetApiRequest.call(this, 'POST', encodedApiKey, path, body) - .then(responseData => { - if (responseData.id === undefined) { - // Required data is missing so was not successful - throw new NodeApiError(this.getNode(), responseData, { message: 'Onfleet webhook creation response did not contain the expected data' }); - } - - return Promise.resolve(true); - }); + const webhook = await onfleetApiRequest.call(this, 'POST', path, body); + + if (webhook.id === undefined) { + throw new NodeApiError(this.getNode(), webhook, { 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 { - const credentials = await this.getCredentials('onfleetApi') as ICredentialDataDecryptedObject; - const encodedApiKey = Buffer.from(`${credentials.apiKey}:`).toString('base64'); - const webhookUrl = this.getNodeWebhookUrl('default') as string; - + const webhookData = this.getWorkflowStaticData('node') as IDataObject; // Get the data of the already registered webhook - const webhooks = await onfleetApiRequest.call(this, 'GET', encodedApiKey, 'webhooks'); - const webhook = webhooks.find((webhook: IDataObject) => webhook.url === webhookUrl); - const endpoint = `/webhooks/${webhook.id}`; - await onfleetApiRequest.call(this, 'DELETE', encodedApiKey, endpoint); - + const endpoint = `/webhooks/${webhookData.id}`; + await onfleetApiRequest.call(this, 'DELETE', endpoint); return true; }, }, @@ -217,7 +188,7 @@ export class OnfleetTrigger implements INodeType { */ async webhook(this: IWebhookFunctions): Promise { const req = this.getRequestObject(); - if (req.method === 'GET') { + if (this.getWebhookName() === 'setup') { /* -------------------------------------------------------------------------- */ /* Validation request */ /* -------------------------------------------------------------------------- */ diff --git a/packages/nodes-base/nodes/Onfleet/descriptions/AdministratorDescription.ts b/packages/nodes-base/nodes/Onfleet/descriptions/AdministratorDescription.ts index 3adb397af145d..31cbdb15bc329 100644 --- a/packages/nodes-base/nodes/Onfleet/descriptions/AdministratorDescription.ts +++ b/packages/nodes-base/nodes/Onfleet/descriptions/AdministratorDescription.ts @@ -9,7 +9,7 @@ export const adminOperations: INodeProperties[] = [ type: 'options', displayOptions: { show: { - resource: [ 'admin' ], + resource: ['admin'], }, }, options: [ @@ -77,7 +77,7 @@ export const adminFields: INodeProperties[] = [ type: 'string', displayOptions: { show: { - resource: [ 'admin' ], + resource: ['admin'], }, hide: { operation: [ @@ -91,10 +91,51 @@ export const adminFields: INodeProperties[] = [ description: 'The ID of the admin object for lookup', }, { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', displayOptions: { show: { - resource: [ 'admin' ], - operation: [ 'create' ], + resource: [ + 'admin', + ], + operation: [ + 'getAll', + ], + }, + }, + default: false, + description: 'If all results should be returned or only up to a given limit', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource: [ + 'admin', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 64, + }, + default: 64, + description: 'How many results to return', + }, + { + displayOptions: { + show: { + resource: ['admin'], + operation: ['create'], }, }, required: true, @@ -103,8 +144,8 @@ export const adminFields: INodeProperties[] = [ { displayOptions: { show: { - resource: [ 'admin' ], - operation: [ 'create' ], + resource: ['admin'], + operation: ['create'], }, }, required: true, @@ -118,8 +159,8 @@ export const adminFields: INodeProperties[] = [ default: {}, displayOptions: { show: { - resource: [ 'admin' ], - operation: [ 'create' ], + resource: ['admin'], + operation: ['create'], }, }, options: [ @@ -135,8 +176,8 @@ export const adminFields: INodeProperties[] = [ default: {}, displayOptions: { show: { - resource: [ 'admin' ], - operation: [ 'update' ], + resource: ['admin'], + operation: ['update'], }, }, options: [ diff --git a/packages/nodes-base/nodes/Onfleet/descriptions/HubDescription.ts b/packages/nodes-base/nodes/Onfleet/descriptions/HubDescription.ts index 082790fb009ef..2ec8e0bb97eae 100644 --- a/packages/nodes-base/nodes/Onfleet/descriptions/HubDescription.ts +++ b/packages/nodes-base/nodes/Onfleet/descriptions/HubDescription.ts @@ -1,7 +1,10 @@ import { INodeProperties } from 'n8n-workflow'; -import { destinationExternalField } from './DestinationDescription'; + +import { + destinationExternalField, +} from './DestinationDescription'; export const hubOperations: INodeProperties[] = [ { @@ -10,7 +13,7 @@ export const hubOperations: INodeProperties[] = [ type: 'options', displayOptions: { show: { - resource: [ 'hub' ], + resource: ['hub'], }, }, options: [ @@ -60,20 +63,61 @@ export const hubFields: INodeProperties[] = [ type: 'string', displayOptions: { show: { - resource: [ 'hub' ], - operation: [ 'update' ], + 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: 'If all results should be returned 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: 'How many results to return', + }, { ...nameField, displayOptions: { show: { - resource: [ 'hub' ], - operation: [ 'create' ], + resource: ['hub'], + operation: ['create'], }, }, required: true, @@ -82,8 +126,8 @@ export const hubFields: INodeProperties[] = [ ...destinationExternalField, displayOptions: { show: { - resource: [ 'hub' ], - operation: [ 'create' ], + resource: ['hub'], + operation: ['create'], }, }, }, @@ -95,8 +139,8 @@ export const hubFields: INodeProperties[] = [ default: {}, displayOptions: { show: { - resource: [ 'hub' ], - operation: [ 'create' ], + resource: ['hub'], + operation: ['create'], }, }, options: [ @@ -114,8 +158,8 @@ export const hubFields: INodeProperties[] = [ default: {}, displayOptions: { show: { - resource: [ 'hub' ], - operation: [ 'update' ], + resource: ['hub'], + operation: ['update'], }, }, options: [ diff --git a/packages/nodes-base/nodes/Onfleet/descriptions/OnfleetWebhookDescription.ts b/packages/nodes-base/nodes/Onfleet/descriptions/OnfleetWebhookDescription.ts index 7408dd14d7b41..6d7f8c94fa504 100644 --- a/packages/nodes-base/nodes/Onfleet/descriptions/OnfleetWebhookDescription.ts +++ b/packages/nodes-base/nodes/Onfleet/descriptions/OnfleetWebhookDescription.ts @@ -1,15 +1,18 @@ import { INodeProperties } from 'n8n-workflow'; -import { webhookMapping } from '../WebhookMapping'; + +import { + webhookMapping, +} from '../WebhookMapping'; export const eventDisplay: INodeProperties = { displayName: 'Event', name: 'event', type: 'options', options: Object.keys(webhookMapping).map((webhook) => { - const {name, value} = webhookMapping[webhook]; - return {name, value}; + const { name, value } = webhookMapping[webhook]; + return { name, value }; }), required: true, default: [], diff --git a/packages/nodes-base/nodes/Onfleet/descriptions/TaskDescription.ts b/packages/nodes-base/nodes/Onfleet/descriptions/TaskDescription.ts index aa4386fa62f25..fd23ed7288a26 100644 --- a/packages/nodes-base/nodes/Onfleet/descriptions/TaskDescription.ts +++ b/packages/nodes-base/nodes/Onfleet/descriptions/TaskDescription.ts @@ -140,6 +140,47 @@ export const taskFields: INodeProperties[] = [ 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: 'If all results should be returned 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: 'How many results to return', + }, { ...destinationExternalField, displayOptions: { @@ -217,13 +258,6 @@ export const taskFields: INodeProperties[] = [ default: [], description: 'The state of the tasks', }, - { - displayName: 'Last ID', - name: 'lastId', - type: 'string', - default: '', - description: 'The last ID to walk the paginated response', - }, ], }, { diff --git a/packages/nodes-base/nodes/Onfleet/descriptions/WebhookDescription.ts b/packages/nodes-base/nodes/Onfleet/descriptions/WebhookDescription.ts index a2606bc52e143..23d28be97e216 100644 --- a/packages/nodes-base/nodes/Onfleet/descriptions/WebhookDescription.ts +++ b/packages/nodes-base/nodes/Onfleet/descriptions/WebhookDescription.ts @@ -1,7 +1,10 @@ import { INodeProperties } from 'n8n-workflow'; -import { webhookMapping } from '../WebhookMapping'; + +import { + webhookMapping, +} from '../WebhookMapping'; export const webhookOperations: INodeProperties[] = [ { @@ -10,7 +13,7 @@ export const webhookOperations: INodeProperties[] = [ type: 'options', displayOptions: { show: { - resource: [ 'webhook' ], + resource: ['webhook'], }, }, options: [ @@ -35,7 +38,7 @@ export const webhookOperations: INodeProperties[] = [ ]; const urlField = { - displayName: 'Url', + displayName: 'URL', name: 'url', type: 'string', default: '', @@ -54,8 +57,11 @@ const triggerField = { displayName: 'Trigger', name: 'trigger', type: 'options', - options: Object.keys(webhookMapping).map((name, value) => { - return { name, value }; + 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', @@ -76,8 +82,8 @@ export const webhookFields: INodeProperties[] = [ type: 'string', displayOptions: { show: { - resource: [ 'webhook' ], - operation: [ 'delete' ], + resource: ['webhook'], + operation: ['delete'], }, }, default: '', @@ -88,8 +94,8 @@ export const webhookFields: INodeProperties[] = [ ...urlField, displayOptions: { show: { - resource: [ 'webhook' ], - operation: [ 'create' ], + resource: ['webhook'], + operation: ['create'], }, }, required: true, @@ -98,8 +104,8 @@ export const webhookFields: INodeProperties[] = [ ...nameField, displayOptions: { show: { - resource: [ 'webhook' ], - operation: [ 'create' ], + resource: ['webhook'], + operation: ['create'], }, }, required: true, @@ -108,8 +114,8 @@ export const webhookFields: INodeProperties[] = [ ...triggerField, displayOptions: { show: { - resource: [ 'webhook' ], - operation: [ 'create' ], + resource: ['webhook'], + operation: ['create'], }, }, required: true, @@ -122,10 +128,10 @@ export const webhookFields: INodeProperties[] = [ default: {}, displayOptions: { show: { - resource: [ 'webhook' ], - operation: [ 'create' ], + resource: ['webhook'], + operation: ['create'], }, }, - options: [ thresholdField ], + options: [thresholdField], }, ]; diff --git a/packages/nodes-base/nodes/Onfleet/descriptions/WorkerDescription.ts b/packages/nodes-base/nodes/Onfleet/descriptions/WorkerDescription.ts index d7de0a8a02190..42119e64cf471 100644 --- a/packages/nodes-base/nodes/Onfleet/descriptions/WorkerDescription.ts +++ b/packages/nodes-base/nodes/Onfleet/descriptions/WorkerDescription.ts @@ -9,7 +9,7 @@ export const workerOperations: INodeProperties[] = [ type: 'options', displayOptions: { show: { - resource: [ 'worker' ], + resource: ['worker'], }, }, options: [ @@ -200,7 +200,7 @@ const phonesFilterField = { } as INodeProperties; const filterField = { - displayName: 'List Of Fields To Return', + displayName: 'Fields to Return', name: 'filter', type: 'multiOptions', options: [ @@ -364,8 +364,8 @@ export const workerFields: INodeProperties[] = [ required: true, displayOptions: { show: { - resource: [ 'worker' ], - operation: [ 'getAll' ], + resource: ['worker'], + operation: ['getAll'], }, }, }, @@ -375,7 +375,7 @@ export const workerFields: INodeProperties[] = [ type: 'string', displayOptions: { show: { - resource: [ 'worker' ], + resource: ['worker'], operation: [ 'get', 'getSchedule', @@ -393,8 +393,8 @@ export const workerFields: INodeProperties[] = [ ...nameField, displayOptions: { show: { - resource: [ 'worker' ], - operation: [ 'create' ], + resource: ['worker'], + operation: ['create'], }, }, required: true, @@ -403,8 +403,8 @@ export const workerFields: INodeProperties[] = [ ...phoneField, displayOptions: { show: { - resource: [ 'worker' ], - operation: [ 'create' ], + resource: ['worker'], + operation: ['create'], }, }, required: true, @@ -415,53 +415,8 @@ export const workerFields: INodeProperties[] = [ type: 'fixedCollection', displayOptions: { show: { - resource: [ 'worker' ], - operation: [ 'update' ], - }, - }, - default: {}, - options: [ - { - displayName: 'Vehicle Properties', - name: 'vehicleProperties', - values: [ - { - displayName: 'Additional Fields', - name: 'additionalFields', - type: 'collection', - placeholder: 'Add Field', - default: {}, - options: [ - { - ...vehicleTypeField, - required: true, - }, - { - ...vehicleDescriptionField, - required: false, - }, - { - ...vehicleLicensePlateField, - required: false, - }, - { - ...vehicleColorField, - required: false, - }, - ], - }, - ], - }, - ], - }, - { - displayName: 'Vehicle', - name: 'vehicle', - type: 'fixedCollection', - displayOptions: { - show: { - resource: [ 'worker' ], - operation: [ 'create' ], + resource: ['worker'], + operation: ['create'], }, }, default: {}, @@ -503,8 +458,8 @@ export const workerFields: INodeProperties[] = [ ...teamsField, displayOptions: { show: { - resource: [ 'worker' ], - operation: [ 'create' ], + resource: ['worker'], + operation: ['create'], }, }, required: true, @@ -513,9 +468,9 @@ export const workerFields: INodeProperties[] = [ ...longitudeFilterField, displayOptions: { show: { - resource: [ 'worker' ], - operation: [ 'getAll' ], - byLocation: [ true ], + resource: ['worker'], + operation: ['getAll'], + byLocation: [true], }, }, required: true, @@ -524,27 +479,53 @@ export const workerFields: INodeProperties[] = [ ...latitudeFilterField, displayOptions: { show: { - resource: [ 'worker' ], - operation: [ 'getAll' ], - byLocation: [ true ], + resource: ['worker'], + operation: ['getAll'], + byLocation: [true], }, }, required: true, }, { - displayName: 'Filter Fields', - name: 'filterFields', - type: 'collection', - placeholder: 'Add Field', - default: {}, + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', displayOptions: { show: { - resource: [ 'worker' ], - operation: [ 'getAll' ], - byLocation: [ true ], + resource: [ + 'worker', + ], + operation: [ + 'getAll', + ], }, }, - options: [ radiusFilterField ], + default: false, + description: 'If all results should be returned or only up to a given limit', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource: [ + 'worker', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 64, + }, + default: 64, + description: 'How many results to return', }, { displayName: 'Additional Fields', @@ -554,8 +535,8 @@ export const workerFields: INodeProperties[] = [ default: {}, displayOptions: { show: { - resource: [ 'worker' ], - operation: [ 'create' ], + resource: ['worker'], + operation: ['create'], }, }, options: [ @@ -571,8 +552,8 @@ export const workerFields: INodeProperties[] = [ default: {}, displayOptions: { show: { - resource: [ 'worker' ], - operation: [ 'update' ], + resource: ['worker'], + operation: ['update'], }, }, options: [ @@ -583,35 +564,68 @@ export const workerFields: INodeProperties[] = [ ], }, { - displayName: 'Filter Fields', - name: 'filterFields', + displayName: 'Filters', + name: 'filters', type: 'collection', placeholder: 'Add Field', default: {}, displayOptions: { show: { - resource: [ 'worker' ], - operation: [ 'getAll' ], - byLocation: [ false ], + 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: [ - filterField, teamsFilterField, statesFilterField, phonesFilterField, ], }, { - displayName: 'Filter Fields', - name: 'additionalFields', + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: ['worker'], + operation: ['getAll'], + byLocation: [false], + }, + }, + options: [ + filterField, + ], + }, + { + displayName: 'Options', + name: 'options', type: 'collection', placeholder: 'Add Field', default: {}, displayOptions: { show: { - resource: [ 'worker' ], - operation: [ 'get' ], + resource: ['worker'], + operation: ['get'], }, }, options: [ @@ -633,10 +647,11 @@ export const workerFields: INodeProperties[] = [ displayName: 'Schedule', name: 'schedule', type: 'fixedCollection', + placeholder: 'Add Schedule', displayOptions: { show: { - resource: [ 'worker' ], - operation: [ 'setSchedule' ], + resource: ['worker'], + operation: ['setSchedule'], }, }, default: {}, @@ -663,9 +678,9 @@ export const workerFields: INodeProperties[] = [ name: 'shifts', type: 'fixedCollection', default: {}, + placeholder: 'Add Shift', typeOptions: { multipleValues: true, - multipleValueButtonText: 'Add Shift', }, options: [ {