Skip to content

Commit 8baf6c1

Browse files
authored
New Components - taskade (#12646)
* taskade init * new-components * pnpm-lock.yaml
1 parent 572351b commit 8baf6c1

File tree

6 files changed

+277
-7
lines changed

6 files changed

+277
-7
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import taskade from "../../taskade.app.mjs";
2+
3+
export default {
4+
key: "taskade-create-task",
5+
name: "Create Task",
6+
description: "Creates a new task in Taskade. [See the documentation](https://developers.taskade.com/docs/api/tasks/create)",
7+
version: "0.0.1",
8+
type: "action",
9+
props: {
10+
taskade,
11+
projectId: {
12+
propDefinition: [
13+
taskade,
14+
"projectId",
15+
],
16+
},
17+
content: {
18+
type: "string",
19+
label: "Content",
20+
description: "Content of the task",
21+
},
22+
contentType: {
23+
type: "string",
24+
label: "Content Type",
25+
description: "The type of content",
26+
options: [
27+
"text/markdown",
28+
"text/plain",
29+
],
30+
},
31+
placement: {
32+
type: "string",
33+
label: "Placement",
34+
description: "Placement of the task",
35+
options: [
36+
"afterbegin",
37+
"beforeend",
38+
],
39+
},
40+
assignees: {
41+
type: "string[]",
42+
label: "Assignees",
43+
description: "An array of user handles to assign to the task",
44+
optional: true,
45+
},
46+
},
47+
async run({ $ }) {
48+
const task = await this.taskade.createTask({
49+
$,
50+
projectId: this.projectId,
51+
data: {
52+
tasks: [
53+
{
54+
content: this.content,
55+
contentType: this.contentType,
56+
placement: this.placement,
57+
},
58+
],
59+
},
60+
});
61+
const taskId = task.item[0].id;
62+
if (this.assignees?.length) {
63+
await this.taskade.assignTask({
64+
$,
65+
projectId: this.projectId,
66+
taskId,
67+
data: {
68+
handles: this.assignees,
69+
},
70+
});
71+
}
72+
$.export("$summary", `Successfully created task with ID ${taskId}`);
73+
return task;
74+
},
75+
};

components/taskade/package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pipedream/taskade",
3-
"version": "0.0.1",
3+
"version": "0.1.0",
44
"description": "Pipedream Taskade Components",
55
"main": "taskade.app.mjs",
66
"keywords": [
@@ -11,5 +11,8 @@
1111
"author": "Pipedream <[email protected]> (https://pipedream.com/)",
1212
"publishConfig": {
1313
"access": "public"
14+
},
15+
"dependencies": {
16+
"@pipedream/platform": "^3.0.0"
1417
}
15-
}
18+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import taskade from "../../taskade.app.mjs";
2+
import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform";
3+
import sampleEmit from "./test-event.mjs";
4+
5+
export default {
6+
key: "taskade-new-task-created",
7+
name: "New Task Created",
8+
description: "Emit new event when a new task is created in Taskade",
9+
version: "0.0.1",
10+
type: "source",
11+
dedupe: "unique",
12+
props: {
13+
taskade,
14+
db: "$.service.db",
15+
timer: {
16+
type: "$.interface.timer",
17+
default: {
18+
intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
19+
},
20+
},
21+
projectId: {
22+
propDefinition: [
23+
taskade,
24+
"projectId",
25+
],
26+
},
27+
},
28+
hooks: {
29+
async deploy() {
30+
await this.processEvent(25);
31+
},
32+
},
33+
methods: {
34+
_getPreviousIds() {
35+
return this.db.get("previousIds") || {};
36+
},
37+
_setPreviousIds(previousIds) {
38+
this.db.set("previousIds", previousIds);
39+
},
40+
emitEvent(task) {
41+
const meta = this.generateMeta(task);
42+
this.$emit(task, meta);
43+
},
44+
generateMeta(task) {
45+
return {
46+
id: task.id,
47+
summary: `New Task ID: ${task.id}`,
48+
ts: Date.now(),
49+
};
50+
},
51+
async processEvent(max) {
52+
const tasks = [];
53+
const items = this.taskade.paginate({
54+
resourceFn: this.taskade.listTasks,
55+
args: {
56+
projectId: this.projectId,
57+
},
58+
resourceType: "items",
59+
});
60+
for await (const item of items) {
61+
tasks.push(item);
62+
}
63+
let previousIds = this._getPreviousIds();
64+
let newTasks = tasks.filter(({ id }) => !previousIds[id]);
65+
newTasks.forEach(({ id }) => previousIds[id] = true);
66+
this._setPreviousIds(previousIds);
67+
newTasks = max
68+
? newTasks.slice(0, max)
69+
: newTasks;
70+
newTasks.forEach((task) => this.emitEvent(task));
71+
},
72+
},
73+
async run() {
74+
await this.processEvent();
75+
},
76+
sampleEmit,
77+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default {
2+
"id": "85e89694-3ca9-49ac-8393-4595543d4643",
3+
"text": "Getting Started",
4+
"completed": false
5+
}

components/taskade/taskade.app.mjs

Lines changed: 111 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,118 @@
1+
import { axios } from "@pipedream/platform";
2+
13
export default {
24
type: "app",
35
app: "taskade",
4-
propDefinitions: {},
6+
propDefinitions: {
7+
projectId: {
8+
type: "string",
9+
label: "Project ID",
10+
description: "The identifier of a project",
11+
async options({ page }) {
12+
const { items } = await this.listProjects({
13+
params: {
14+
page: page + 1,
15+
},
16+
});
17+
return items?.map(({
18+
id: value, name: label,
19+
}) => ({
20+
value,
21+
label,
22+
})) || [];
23+
},
24+
},
25+
},
526
methods: {
6-
// this.$auth contains connected account data
7-
authKeys() {
8-
console.log(Object.keys(this.$auth));
27+
_baseUrl() {
28+
return "https://www.taskade.com/api/v1";
29+
},
30+
_makeRequest(opts = {}) {
31+
const {
32+
$ = this,
33+
path,
34+
...otherOpts
35+
} = opts;
36+
return axios($, {
37+
...otherOpts,
38+
url: `${this._baseUrl()}${path}`,
39+
headers: {
40+
"Content-Type": "application/json",
41+
"Authorization": `Bearer ${this.$auth.oauth_access_token}`,
42+
},
43+
});
44+
},
45+
listProjects(opts = {}) {
46+
return this._makeRequest({
47+
path: "/me/projects",
48+
...opts,
49+
});
50+
},
51+
listTasks({
52+
projectId, ...opts
53+
}) {
54+
return this._makeRequest({
55+
path: `/projects/${projectId}/tasks`,
56+
...opts,
57+
});
58+
},
59+
createTask({
60+
projectId, ...opts
61+
}) {
62+
return this._makeRequest({
63+
method: "POST",
64+
path: `/projects/${projectId}/tasks`,
65+
...opts,
66+
});
67+
},
68+
assignTask({
69+
projectId, taskId, ...opts
70+
}) {
71+
return this._makeRequest({
72+
method: "PUT",
73+
path: `/projects/${projectId}/tasks/${taskId}/assignees`,
74+
...opts,
75+
});
76+
},
77+
createOrUpdateDueDate({
78+
projectId, taskId, ...opts
79+
}) {
80+
return this._makeRequest({
81+
method: "PUT",
82+
path: `/projects/${projectId}/tasks/${taskId}/date`,
83+
...opts,
84+
});
85+
},
86+
async *paginate({
87+
resourceFn,
88+
args,
89+
resourceType,
90+
max,
91+
}) {
92+
args = {
93+
...args,
94+
params: {
95+
...args.params,
96+
},
97+
};
98+
let count = 0;
99+
do {
100+
const results = await resourceFn(args);
101+
const items = resourceType
102+
? results[resourceType]
103+
: results;
104+
if (!items?.length) {
105+
return;
106+
}
107+
for (const item of items) {
108+
yield item;
109+
count++;
110+
if (max && max >= count) {
111+
return;
112+
}
113+
}
114+
args.params.after = items[items.length - 1].id;
115+
} while (args.params.after);
9116
},
10117
},
11118
};

pnpm-lock.yaml

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)