diff --git a/components/tookan/actions/common.ts b/components/tookan/actions/common.ts new file mode 100644 index 0000000000000..ef58cdc708ef8 --- /dev/null +++ b/components/tookan/actions/common.ts @@ -0,0 +1,19 @@ +import tookan from "../app/tookan.app"; + +export default { + props: { + tookan, + additionalOptions: { + propDefinition: [ + tookan, + "additionalOptions", + ], + }, + timezone: { + propDefinition: [ + tookan, + "timezone", + ], + }, + }, +}; diff --git a/components/tookan/actions/create-appointment-task/create-appointment-task.ts b/components/tookan/actions/create-appointment-task/create-appointment-task.ts new file mode 100644 index 0000000000000..63bb696ec9bf1 --- /dev/null +++ b/components/tookan/actions/create-appointment-task/create-appointment-task.ts @@ -0,0 +1,56 @@ +import { defineAction } from "@pipedream/types"; +import { CreateAppointmentTaskParams } from "../../common/requestParams"; +import tookan from "../../app/tookan.app"; +import common from "../common"; +import { TaskData } from "../../common/responseSchemas"; + +export default defineAction({ + ...common, + name: "Create Appointment Task", + description: + "Create an appointment task [See docs here](https://tookanapi.docs.apiary.io/#reference/task/create-task/create-an-appointment-task)", + key: "tookan-create-appointment-task", + version: "0.0.1", + type: "action", + props: { + ...common.props, + customerAddress: { + propDefinition: [ + tookan, + "customerAddress", + ], + }, + jobDeliveryDatetime: { + propDefinition: [ + tookan, + "jobDeliveryDatetime", + ], + }, + jobPickupDatetime: { + propDefinition: [ + tookan, + "jobPickupDatetime", + ], + }, + }, + async run({ $ }) { + const params: CreateAppointmentTaskParams = { + $, + data: { + timezone: this.timezone, + customer_address: this.customerAddress, + job_delivery_datetime: this.jobDeliveryDatetime, + job_pickup_datetime: this.jobPickupDatetime, + has_delivery: 0, + has_pickup: 0, + layout_type: 1, + ...this.additionalOptions, + }, + }; + const data: TaskData = await this.tookan.createAppointmentTask(params); + + $.export("$summary", `Created appointment task successfully (id ${data.job_id})`); + + return data; + }, +}); diff --git a/components/tookan/actions/create-delivery-task/create-delivery-task.ts b/components/tookan/actions/create-delivery-task/create-delivery-task.ts new file mode 100644 index 0000000000000..92b2be4a31718 --- /dev/null +++ b/components/tookan/actions/create-delivery-task/create-delivery-task.ts @@ -0,0 +1,49 @@ +import { defineAction } from "@pipedream/types"; +import { CreateDeliveryTaskParams } from "../../common/requestParams"; +import tookan from "../../app/tookan.app"; +import common from "../common"; +import { TaskData } from "../../common/responseSchemas"; + +export default defineAction({ + ...common, + name: "Create Delivery Task", + description: + "Create a delivery task [See docs here](https://tookanapi.docs.apiary.io/#reference/task/create-task/create-a-delivery-task)", + key: "tookan-create-delivery-task", + version: "0.0.1", + type: "action", + props: { + ...common.props, + customerAddress: { + propDefinition: [ + tookan, + "customerAddress", + ], + }, + jobDeliveryDatetime: { + propDefinition: [ + tookan, + "jobDeliveryDatetime", + ], + }, + }, + async run({ $ }) { + const params: CreateDeliveryTaskParams = { + $, + data: { + timezone: this.timezone, + customer_address: this.customerAddress, + job_delivery_datetime: this.jobDeliveryDatetime, + has_delivery: 1, + has_pickup: 0, + layout_type: 0, + ...this.additionalOptions, + }, + }; + const data: TaskData = await this.tookan.createDeliveryTask(params); + + $.export("$summary", `Created delivery task successfully (id ${data.job_id})`); + + return data; + }, +}); diff --git a/components/tookan/actions/create-field-workforce-task/create-field-workforce-task.ts b/components/tookan/actions/create-field-workforce-task/create-field-workforce-task.ts new file mode 100644 index 0000000000000..e6c379ebcfdc3 --- /dev/null +++ b/components/tookan/actions/create-field-workforce-task/create-field-workforce-task.ts @@ -0,0 +1,56 @@ +import { defineAction } from "@pipedream/types"; +import { CreateFieldWorkforceTaskParams } from "../../common/requestParams"; +import tookan from "../../app/tookan.app"; +import common from "../common"; +import { TaskData } from "../../common/responseSchemas"; + +export default defineAction({ + ...common, + name: "Create Field Workforce Task", + description: + "Create a field workforce task [See docs here](https://tookanapi.docs.apiary.io/#reference/task/create-task/create-a-field-workforce-task)", + key: "tookan-create-field-workforce-task", + version: "0.0.1", + type: "action", + props: { + ...common.props, + customerAddress: { + propDefinition: [ + tookan, + "customerAddress", + ], + }, + jobDeliveryDatetime: { + propDefinition: [ + tookan, + "jobDeliveryDatetime", + ], + }, + jobPickupDatetime: { + propDefinition: [ + tookan, + "jobPickupDatetime", + ], + }, + }, + async run({ $ }) { + const params: CreateFieldWorkforceTaskParams = { + $, + data: { + timezone: this.timezone, + customer_address: this.customerAddress, + job_delivery_datetime: this.jobDeliveryDatetime, + job_pickup_datetime: this.jobPickupDatetime, + has_delivery: 0, + has_pickup: 0, + layout_type: 2, + ...this.additionalOptions, + }, + }; + const data: TaskData = await this.tookan.createFieldWorkforceTask(params); + + $.export("$summary", `Created field workforce task successfully (id ${data.job_id})`); + + return data; + }, +}); diff --git a/components/tookan/actions/create-pickup-and-delivery-task/create-pickup-and-delivery-task.ts b/components/tookan/actions/create-pickup-and-delivery-task/create-pickup-and-delivery-task.ts new file mode 100644 index 0000000000000..b130622069dbc --- /dev/null +++ b/components/tookan/actions/create-pickup-and-delivery-task/create-pickup-and-delivery-task.ts @@ -0,0 +1,68 @@ +import { defineAction } from "@pipedream/types"; +import { CreatePickupAndDeliveryTaskParams } from "../../common/requestParams"; +import tookan from "../../app/tookan.app"; +import common from "../common"; +import { TaskData } from "../../common/responseSchemas"; + +export default defineAction({ + ...common, + name: "Create Pickup And Delivery Task", + description: + "Create a pickup and delivery task [See docs here](https://tookanapi.docs.apiary.io/#reference/task/create-task/create-a-pickup-and-delivery-task)", + key: "tookan-create-pickup-and-delivery-task", + version: "0.0.1", + type: "action", + props: { + ...common.props, + customerAddress: { + propDefinition: [ + tookan, + "customerAddress", + ], + }, + jobDeliveryDatetime: { + propDefinition: [ + tookan, + "jobDeliveryDatetime", + ], + }, + jobPickupAddress: { + propDefinition: [ + tookan, + "jobPickupAddress", + ], + }, + jobPickupDatetime: { + propDefinition: [ + tookan, + "jobPickupDatetime", + ], + }, + }, + async run({ $ }) { + const params: CreatePickupAndDeliveryTaskParams = { + $, + data: { + timezone: this.timezone, + customer_address: this.customerAddress, + job_delivery_datetime: this.jobDeliveryDatetime, + job_pickup_address: this.jobPickupAddress, + job_pickup_datetime: this.jobPickupDatetime, + has_delivery: 1, + has_pickup: 1, + layout_type: 0, + ...this.additionalOptions, + }, + }; + const data: TaskData = await this.tookan.createPickupAndDeliveryTask( + params, + ); + + $.export( + "$summary", + `Created pickup and delivery task successfully (id ${data.job_id})`, + ); + + return data; + }, +}); diff --git a/components/tookan/actions/create-pickup-task/create-pickup-task.ts b/components/tookan/actions/create-pickup-task/create-pickup-task.ts new file mode 100644 index 0000000000000..5bc0cb98c032e --- /dev/null +++ b/components/tookan/actions/create-pickup-task/create-pickup-task.ts @@ -0,0 +1,49 @@ +import { defineAction } from "@pipedream/types"; +import { CreatePickupTaskParams } from "../../common/requestParams"; +import tookan from "../../app/tookan.app"; +import common from "../common"; +import { TaskData } from "../../common/responseSchemas"; + +export default defineAction({ + ...common, + name: "Create Pickup Task", + description: + "Create a pickup task [See docs here](https://tookanapi.docs.apiary.io/#reference/task/create-task/create-a-pickup-task)", + key: "tookan-create-pickup-task", + version: "0.0.1", + type: "action", + props: { + ...common.props, + jobPickupAddress: { + propDefinition: [ + tookan, + "jobPickupAddress", + ], + }, + jobPickupDatetime: { + propDefinition: [ + tookan, + "jobPickupDatetime", + ], + }, + }, + async run({ $ }) { + const params: CreatePickupTaskParams = { + $, + data: { + timezone: this.timezone, + job_pickup_address: this.jobPickupAddress, + job_pickup_datetime: this.jobPickupDatetime, + has_delivery: 0, + has_pickup: 1, + layout_type: 0, + ...this.additionalOptions, + }, + }; + const data: TaskData = await this.tookan.createPickupTask(params); + + $.export("$summary", `Created pickup task successfully (id ${data.job_id})`); + + return data; + }, +}); diff --git a/components/tookan/app/tookan.app.ts b/components/tookan/app/tookan.app.ts index 9db4315131bfb..68279509db0b3 100644 --- a/components/tookan/app/tookan.app.ts +++ b/components/tookan/app/tookan.app.ts @@ -1,13 +1,109 @@ import { defineApp } from "@pipedream/types"; +import { axios } from "@pipedream/platform"; +import { + HttpRequestParams, + CreateAppointmentTaskParams, + CreateDeliveryTaskParams, + CreateFieldWorkforceTaskParams, + CreatePickupAndDeliveryTaskParams, + CreatePickupTaskParams, +} from "../common/requestParams"; +import { CreateTaskResponse } from "../common/responseSchemas"; +import timezoneOptions from "../common/timezones"; export default defineApp({ type: "app", app: "tookan", - propDefinitions: {}, + propDefinitions: { + timezone: { + label: "Time Zone", + description: `Select a **time zone** from the list. + \\ + You can also provide a custom value indicating the difference with UTC in minutes, such as \`+480\` for PST.`, + type: "string", + options: timezoneOptions, + }, + customerAddress: { + label: "Customer Address", + description: + "This is the address of the customer to whom the product should be delivered", + type: "string", + }, + jobDeliveryDatetime: { + label: "Job Delivery Date/Time", + description: + "This is the time before which the product should be delivered. Use a date/time string in the format `2016-08-14 19:00:00`", + type: "string", + }, + jobPickupDatetime: { + label: "Job Pickup Date/Time", + description: + "This is time before which the pickup should be collected. Use a date/time string in the format `2016-08-14 19:00:00`", + type: "string", + }, + jobPickupAddress: { + label: "Job Pickup Address", + description: "The address from which the pickup should be collected", + type: "string", + }, + additionalOptions: { + label: "Additional Options", + description: "Any optional parameters to pass to the request [(see the Tookan API docs for available parameters)](https://tookanapi.docs.apiary.io/#reference/task/create-task)", + type: "object", + optional: true, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl(): string { + return "https://api.tookanapp.com/v2"; + }, + async _httpRequest({ + $ = this, + endpoint, + data, + method, + }: HttpRequestParams): Promise { + return axios($, { + url: this._baseUrl() + endpoint, + headers: { + "Content-Type": "application/json", + }, + data: { + api_key: this.$auth.api_key, + ...data, + }, + method, + }); + }, + async createTask(params: { data: object; }) { + const response: CreateTaskResponse = await this._httpRequest({ + endpoint: "/create_task", + method: "POST", + ...params, + }); + + if (response.status !== 200) { + throw new Error("Tookan response: " + response.message); + } + + return response.data; + }, + async createAppointmentTask(params: CreateAppointmentTaskParams): Promise { + return this.createTask(params); + }, + async createDeliveryTask(params: CreateDeliveryTaskParams): Promise { + return this.createTask(params); + }, + async createFieldWorkforceTask(params: CreateFieldWorkforceTaskParams): Promise { + return this.createTask(params); + }, + async createPickupAndDeliveryTask( + params: CreatePickupAndDeliveryTaskParams, + ): Promise { + return this.createTask(params); + }, + async createPickupTask(params: CreatePickupTaskParams): Promise { + return this.createTask(params); }, }, -}); \ No newline at end of file +}); diff --git a/components/tookan/common/requestParams.ts b/components/tookan/common/requestParams.ts new file mode 100644 index 0000000000000..2b74a3ebda73b --- /dev/null +++ b/components/tookan/common/requestParams.ts @@ -0,0 +1,88 @@ +import { Pipedream } from "@pipedream/types"; + +interface ActionRequestParams { + $: Pipedream; +} + +export interface HttpRequestParams extends ActionRequestParams { + endpoint: string; + data?: object; + method?: string; +} + +type CreateTaskParams = ActionRequestParams & { + data: { + timezone: string; + has_delivery: 0 | 1; + has_pickup: 0 | 1; + layout_type: 0 | 1 | 2; + }; +}; + +interface HasDeliveryParams { + data: { + customer_address: string; + job_delivery_datetime: string; + }; +} +interface HasPickupDate { + data: { + job_pickup_datetime: string; + }; +} + +interface HasPickupAddress { + data: { + job_pickup_address: string; + }; +} + +export type CreateAppointmentTaskParams = CreateTaskParams & + HasDeliveryParams & + HasPickupDate & { + data: { + has_delivery: 0; + has_pickup: 0; + layout_type: 1; + }; + }; + +export type CreateDeliveryTaskParams = CreateTaskParams & + HasDeliveryParams & { + data: { + has_delivery: 1; + has_pickup: 0; + layout_type: 0; + }; + }; + +export type CreateFieldWorkforceTaskParams = CreateTaskParams & + HasDeliveryParams & + HasPickupDate & { + data: { + has_delivery: 0; + has_pickup: 0; + layout_type: 2; + }; + }; + +export type CreatePickupTaskParams = CreateTaskParams & + HasPickupDate & + HasPickupAddress & { + data: { + has_delivery: 0; + has_pickup: 1; + layout_type: 0; + }; + }; + +export type CreatePickupAndDeliveryTaskParams = CreateTaskParams & + HasPickupDate & + HasDeliveryParams & + HasPickupAddress & { + data: { + has_delivery: 1; + has_pickup: 1; + layout_type: 0; + }; + }; diff --git a/components/tookan/common/responseSchemas.ts b/components/tookan/common/responseSchemas.ts new file mode 100644 index 0000000000000..d47d46c9fa210 --- /dev/null +++ b/components/tookan/common/responseSchemas.ts @@ -0,0 +1,10 @@ +export interface TaskData { + job_id: number; +} + +export interface CreateTaskResponse { + message: string; + status: number; + data: TaskData; +} + diff --git a/components/tookan/common/timezones.ts b/components/tookan/common/timezones.ts new file mode 100644 index 0000000000000..e61db6e2aef7a --- /dev/null +++ b/components/tookan/common/timezones.ts @@ -0,0 +1,30 @@ +const timezoneNames = [ + "-8 (PST)", + "-7 (MST)", + "-6 (CST)", + "-5 (EST)", + "-4 (AST)", + "-3 (BRT)", + "-2", + "-1", + "0 (GMT)", + "+1 (CET)", + "+2 (EET)", + "+3 (MSK)", + "+4", +]; +let initialValue = -9 * 60; + +function getTimezoneString() { + const value = (initialValue += 60); + return value > 0 + ? `+${value}` + : value.toString(); +} + +const timezoneOptions = timezoneNames.map((name) => ({ + label: "UTC " + name, + value: getTimezoneString(), +})); + +export default timezoneOptions; diff --git a/components/tookan/package.json b/components/tookan/package.json index 79ac2b4d90c95..c835939e0c4eb 100644 --- a/components/tookan/package.json +++ b/components/tookan/package.json @@ -13,5 +13,11 @@ "license": "MIT", "publishConfig": { "access": "public" + }, + "devDependencies": { + "@pipedream/types": "^0.1.4" + }, + "dependencies": { + "@pipedream/platform": "^1.1.0" } -} \ No newline at end of file +} diff --git a/components/tookan/tsconfig.json b/components/tookan/tsconfig.json new file mode 100644 index 0000000000000..ec9c833423b99 --- /dev/null +++ b/components/tookan/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "lib": ["es2020"], + "module": "ES2020", + "target": "ES2020", + "moduleResolution": "node", + "listEmittedFiles": true, // Used as a part of the build task, since we need to pass emitted files to our post-build script + "composite": true, + "outDir": "dist", + "allowSyntheticDefaultImports": true, + }, + "allowJs": true, + "include": [ + "app", + "actions", + "sources", + "common" + ], + "exclude": [ + "dist", + ] + } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eb4976ccde742..80211e95f06f8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1942,7 +1942,13 @@ importers: specifiers: {} components/tookan: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.1.0 + '@pipedream/types': ^0.1.4 + dependencies: + '@pipedream/platform': 1.1.1 + devDependencies: + '@pipedream/types': 0.1.4 components/totango: specifiers: