From 084c77d74340a3914b26678f8bbc64bd7e37ea6c Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Thu, 8 May 2025 16:55:26 -0400 Subject: [PATCH 1/5] create-task --- .../nifty/actions/assign-task/assign-task.mjs | 2 +- .../actions/create-message/create-message.mjs | 2 +- .../actions/create-project/create-project.mjs | 2 +- .../nifty/actions/create-task/create-task.mjs | 112 +++++++++++++++++ components/nifty/nifty.app.mjs | 118 +++++++++++++++--- components/nifty/package.json | 4 +- .../new-message-posted/new-message-posted.mjs | 2 +- .../new-task-created/new-task-created.mjs | 2 +- 8 files changed, 218 insertions(+), 26 deletions(-) create mode 100644 components/nifty/actions/create-task/create-task.mjs diff --git a/components/nifty/actions/assign-task/assign-task.mjs b/components/nifty/actions/assign-task/assign-task.mjs index 0440e791ff631..a226bfa95be1a 100644 --- a/components/nifty/actions/assign-task/assign-task.mjs +++ b/components/nifty/actions/assign-task/assign-task.mjs @@ -4,7 +4,7 @@ export default { key: "nifty-assign-task", name: "Assign Task to Team Member", description: "Assigns a specific task to a team member in Nifty. [See the documentation](https://openapi.niftypm.com/api#put-api-v1-0-tasks-task_id-assignees)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { nifty, diff --git a/components/nifty/actions/create-message/create-message.mjs b/components/nifty/actions/create-message/create-message.mjs index 3e1247b9d0a74..b1ea6a88e704c 100644 --- a/components/nifty/actions/create-message/create-message.mjs +++ b/components/nifty/actions/create-message/create-message.mjs @@ -5,7 +5,7 @@ export default { key: "nifty-create-message", name: "Create Message", description: "Sends a new message in a team's discussion. [See the documentation](https://openapi.niftypm.com/api)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { nifty, diff --git a/components/nifty/actions/create-project/create-project.mjs b/components/nifty/actions/create-project/create-project.mjs index 1bfedfc7acd93..74a242fef16c6 100644 --- a/components/nifty/actions/create-project/create-project.mjs +++ b/components/nifty/actions/create-project/create-project.mjs @@ -7,7 +7,7 @@ export default { key: "nifty-create-project", name: "Create Project", description: "Creates a new project in a designated portfolio. [See the documentation](https://openapi.niftypm.com/api#/Projects/ProjectAPIController_createProject)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { nifty, diff --git a/components/nifty/actions/create-task/create-task.mjs b/components/nifty/actions/create-task/create-task.mjs new file mode 100644 index 0000000000000..a17aafcbb155a --- /dev/null +++ b/components/nifty/actions/create-task/create-task.mjs @@ -0,0 +1,112 @@ +import nifty from "../../nifty.app.mjs"; + +export default { + key: "nifty-create-task", + name: "Create Task", + description: "Creates a new task. [See the documentation](https://developers.niftypm.com/operation/operation-taskapicontroller_createtask)", + version: "0.0.1", + type: "action", + props: { + nifty, + projectId: { + propDefinition: [ + nifty, + "projectId", + ], + }, + taskGroupId: { + propDefinition: [ + nifty, + "taskGroupId", + (c) => ({ + projectId: c.projectId, + }), + ], + }, + name: { + type: "string", + label: "Name", + description: "The name of the task", + }, + description: { + type: "string", + label: "Description", + description: "A description of the task", + optional: true, + }, + order: { + type: "integer", + label: "Order", + description: "The order of the task", + optional: true, + }, + parentTaskId: { + propDefinition: [ + nifty, + "taskId", + (c) => ({ + projectId: c.projectId, + }), + ], + label: "Parent Task ID", + description: "Enter a parent task ID to create this task as subtask of another task", + optional: true, + }, + milestoneId: { + propDefinition: [ + nifty, + "milestoneId", + (c) => ({ + projectId: c.projectId, + }), + ], + }, + dueDate: { + type: "string", + label: "Due Date", + description: "Due date of the task in ISO-8601 format", + optional: true, + }, + startDate: { + type: "string", + label: "Start Date", + description: "Start date of the task in ISO-8601 format", + optional: true, + }, + assigneeIds: { + propDefinition: [ + nifty, + "memberId", + ], + type: "string[]", + label: "Assignee IDs", + description: "An array of assignee IDs to assigne to the task", + optional: true, + }, + labels: { + type: "string[]", + label: "Labels", + description: "An array of labels to add to the tasK", + optional: true, + }, + }, + async run({ $ }) { + const response = await this.nifty.createTask({ + $, + data: { + task_group_id: this.taskGroupId, + name: this.name, + description: this.description, + order: this.order, + task_id: this.parentTaskId, + milestone_id: this.milestoneId, + due_date: this.dueDate, + start_date: this.startDate, + assignee_ids: this.assigneeIds, + labels: this.labels, + }, + }); + $.export("$summary", `Successfully created task with ID: ${response.id}`); + return response; + }, +}; diff --git a/components/nifty/nifty.app.mjs b/components/nifty/nifty.app.mjs index a9d97cb087852..3e1e208d2fbde 100644 --- a/components/nifty/nifty.app.mjs +++ b/components/nifty/nifty.app.mjs @@ -7,7 +7,7 @@ export default { propDefinitions: { appId: { type: "string", - label: "App Id", + label: "App ID", description: `The unique identifier for the App. On Nifty, a new app can be created by following these steps: 1. Access Profile Settings > App Center > Integrate with API > Create a new App. 2. In the Create App popup, add the following Pipedream Redirect URL to the Redirect URLs: \`https://api.pipedream.com/connect/oauth/oa_aWyi2m/callback\`. @@ -20,7 +20,9 @@ export default { }, }); - return apps.map(({ id: value, name: label }) => ({ + return apps.map(({ + id: value, name: label, + }) => ({ label, value, })); @@ -28,13 +30,14 @@ export default { }, memberId: { type: "string", - label: "Member Id", - description: - "The unique identifier for the member that the task will be assigned.", + label: "Member ID", + description: "The unique identifier for the member that the task will be assigned", async options() { const members = await this.listMembers(); - return members.map(({ id: value, name: label }) => ({ + return members.map(({ + id: value, name: label, + }) => ({ label, value, })); @@ -42,8 +45,8 @@ export default { }, projectId: { type: "string", - label: "Project Id", - description: "The unique identifier for the project.", + label: "Project ID", + description: "The unique identifier for the project", async options({ page }) { const { projects } = await this.listProjects({ params: { @@ -52,7 +55,9 @@ export default { }, }); - return projects.map(({ id: value, name: label }) => ({ + return projects.map(({ + id: value, name: label, + }) => ({ label, value, })); @@ -60,17 +65,22 @@ export default { }, taskId: { type: "string", - label: "Task Id", - description: "The unique identifier for the task.", - async options({ page }) { + label: "Task ID", + description: "The unique identifier for the task", + async options({ + page, projectId, + }) { const { tasks } = await this.listTasks({ params: { limit: LIMIT, offset: LIMIT * page, + project_id: projectId, }, }); - return tasks.map(({ id: value, name: label }) => ({ + return tasks.map(({ + id: value, name: label, + }) => ({ label, value, })); @@ -78,8 +88,8 @@ export default { }, templateId: { type: "string", - label: "Template Id", - description: "The unique identifier for the template.", + label: "Template ID", + description: "The unique identifier for the template", async options({ page }) { const { items } = await this.listTemplates({ params: { @@ -89,12 +99,63 @@ export default { }, }); - return items.map(({ id: value, name: label }) => ({ + return items.map(({ + id: value, name: label, + }) => ({ + label, + value, + })); + }, + }, + milestoneId: { + type: "string", + label: "Milestone ID", + description: "The unique identifier of a milestone", + optional: true, + async options({ + page, projectId, + }) { + const { items } = await this.listMilestones({ + params: { + limit: LIMIT, + offset: LIMIT * page, + project_id: projectId, + }, + }); + + return items.map(({ + id: value, name: label, + }) => ({ label, value, })); }, }, + taskGroupId: { + type: "string", + label: "Task Group ID", + description: "The unique identifier of a task group", + async options({ + page, projectId, + }) { + const { items } = await this.listMilestones({ + params: { + limit: LIMIT, + offset: LIMIT * page, + project_id: projectId, + }, + }); + + return items + .filter(({ task_group }) => task_group ) + .map(({ + task_group: value, name: label, + }) => ({ + label, + value, + })); + }, + }, }, methods: { _baseUrl() { @@ -105,7 +166,9 @@ export default { Authorization: `Bearer ${this.$auth.oauth_access_token}`, }; }, - _makeRequest({ $ = this, path, ...opts }) { + _makeRequest({ + $ = this, path, ...opts + }) { return axios($, { url: this._baseUrl() + path, headers: this._headers(), @@ -160,6 +223,12 @@ export default { ...opts, }); }, + listMilestones(opts = {}) { + return this._makeRequest({ + path: "/milestones", + ...opts, + }); + }, listTemplates(opts = {}) { return this._makeRequest({ path: "/templates", @@ -173,7 +242,9 @@ export default { ...opts, }); }, - deleteHook({ hookId, ...opts }) { + deleteHook({ + hookId, ...opts + }) { return this._makeRequest({ method: "DELETE", path: `/webhooks/${hookId}`, @@ -187,7 +258,9 @@ export default { ...opts, }); }, - assignTask({ taskId, ...opts }) { + assignTask({ + taskId, ...opts + }) { return this._makeRequest({ method: "PUT", path: `/tasks/${taskId}/assignees`, @@ -201,5 +274,12 @@ export default { ...opts, }); }, + createTask(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/tasks", + ...opts, + }); + }, }, }; diff --git a/components/nifty/package.json b/components/nifty/package.json index af9c6c3b5df37..2806dadec89ca 100644 --- a/components/nifty/package.json +++ b/components/nifty/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/nifty", - "version": "0.1.0", + "version": "0.2.0", "description": "Pipedream Nifty Components", "main": "nifty.app.mjs", "keywords": [ @@ -13,6 +13,6 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^1.5.1" + "@pipedream/platform": "^3.0.3" } } diff --git a/components/nifty/sources/new-message-posted/new-message-posted.mjs b/components/nifty/sources/new-message-posted/new-message-posted.mjs index ba8b3f08748c4..9509901e6f42c 100644 --- a/components/nifty/sources/new-message-posted/new-message-posted.mjs +++ b/components/nifty/sources/new-message-posted/new-message-posted.mjs @@ -6,7 +6,7 @@ export default { key: "nifty-new-message-posted", name: "New Message Posted", description: "Emit new event when a new message is posted in a team's discussion.", - version: "0.0.1", + version: "0.0.2", type: "source", dedupe: "unique", methods: { diff --git a/components/nifty/sources/new-task-created/new-task-created.mjs b/components/nifty/sources/new-task-created/new-task-created.mjs index 0dc443471bdd5..b13ca06d53623 100644 --- a/components/nifty/sources/new-task-created/new-task-created.mjs +++ b/components/nifty/sources/new-task-created/new-task-created.mjs @@ -6,7 +6,7 @@ export default { key: "nifty-new-task-created", name: "New Task Created", description: "Emit new event when a task is created in a project.", - version: "0.0.1", + version: "0.0.2", type: "source", dedupe: "unique", methods: { From 4b1d565f34bd5d500bded8851185a59d6946b7b9 Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Thu, 8 May 2025 16:57:19 -0400 Subject: [PATCH 2/5] pnpm-lock.yaml --- pnpm-lock.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e0e174ac54173..a7f979aaf23cd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8651,8 +8651,8 @@ importers: components/nifty: dependencies: '@pipedream/platform': - specifier: ^1.5.1 - version: 1.6.6 + specifier: ^3.0.3 + version: 3.0.3 components/niftyimages: dependencies: From 6b1e561ffee962f6feed8fe1eaa6b686fd1d2941 Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Thu, 8 May 2025 17:05:03 -0400 Subject: [PATCH 3/5] updates --- components/nifty/actions/create-task/create-task.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/nifty/actions/create-task/create-task.mjs b/components/nifty/actions/create-task/create-task.mjs index a17aafcbb155a..ddf97dd7936e1 100644 --- a/components/nifty/actions/create-task/create-task.mjs +++ b/components/nifty/actions/create-task/create-task.mjs @@ -80,13 +80,13 @@ export default { ], type: "string[]", label: "Assignee IDs", - description: "An array of assignee IDs to assigne to the task", + description: "An array of assignee IDs to assign to the task", optional: true, }, labels: { type: "string[]", label: "Labels", - description: "An array of labels to add to the tasK", + description: "An array of labels to add to the task", optional: true, }, }, From a8416fb387b80a2d8b4d75dfac9cc546118496f1 Mon Sep 17 00:00:00 2001 From: michelle0927 Date: Fri, 9 May 2025 11:40:33 -0400 Subject: [PATCH 4/5] updates --- components/nifty/nifty.app.mjs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/components/nifty/nifty.app.mjs b/components/nifty/nifty.app.mjs index 3e1e208d2fbde..e6ad58e91e45c 100644 --- a/components/nifty/nifty.app.mjs +++ b/components/nifty/nifty.app.mjs @@ -138,22 +138,21 @@ export default { async options({ page, projectId, }) { - const { items } = await this.listMilestones({ + const { items } = await this.listTaskGroups({ params: { limit: LIMIT, offset: LIMIT * page, project_id: projectId, + archived: false, }, }); - return items - .filter(({ task_group }) => task_group ) - .map(({ - task_group: value, name: label, - }) => ({ - label, - value, - })); + return items?.map(({ + id: value, name: label, + }) => ({ + label, + value, + })) || []; }, }, }, @@ -229,6 +228,12 @@ export default { ...opts, }); }, + listTaskGroups(opts = {}) { + return this._makeRequest({ + path: "/taskgroups", + ...opts, + }); + }, listTemplates(opts = {}) { return this._makeRequest({ path: "/templates", From ba3b874a34d5f0f94a04c8eadb52cfee21281207 Mon Sep 17 00:00:00 2001 From: Michelle Bergeron Date: Mon, 12 May 2025 12:02:15 -0400 Subject: [PATCH 5/5] updates --- .../nifty/actions/create-task/create-task.mjs | 25 +++++++++-------- components/nifty/common/utils.mjs | 26 +++++++++++++++++ components/nifty/nifty.app.mjs | 28 +++++++++++++++++++ 3 files changed, 67 insertions(+), 12 deletions(-) diff --git a/components/nifty/actions/create-task/create-task.mjs b/components/nifty/actions/create-task/create-task.mjs index ddf97dd7936e1..bb5a5dd4f6c4a 100644 --- a/components/nifty/actions/create-task/create-task.mjs +++ b/components/nifty/actions/create-task/create-task.mjs @@ -1,4 +1,5 @@ import nifty from "../../nifty.app.mjs"; +import { parseObjectEntries } from "../../common/utils.mjs"; export default { key: "nifty-create-task", @@ -34,12 +35,6 @@ export default { description: "A description of the task", optional: true, }, - order: { - type: "integer", - label: "Order", - description: "The order of the task", - optional: true, - }, parentTaskId: { propDefinition: [ nifty, @@ -83,10 +78,16 @@ export default { description: "An array of assignee IDs to assign to the task", optional: true, }, - labels: { - type: "string[]", - label: "Labels", - description: "An array of labels to add to the task", + labelIds: { + propDefinition: [ + nifty, + "labelIds", + ], + }, + additionalFields: { + type: "object", + label: "Additional Fields", + description: "Additional fields to add to the task. [See the documentation](https://developers.niftypm.com/operation/operation-taskapicontroller_createtask)", optional: true, }, }, @@ -97,13 +98,13 @@ export default { task_group_id: this.taskGroupId, name: this.name, description: this.description, - order: this.order, task_id: this.parentTaskId, milestone_id: this.milestoneId, due_date: this.dueDate, start_date: this.startDate, assignee_ids: this.assigneeIds, - labels: this.labels, + labels: this.labelIds, + ...parseObjectEntries(this.additionalFields), }, }); $.export("$summary", `Successfully created task with ID: ${response.id}`); diff --git a/components/nifty/common/utils.mjs b/components/nifty/common/utils.mjs index 816afd11fddb2..81170425a66f2 100644 --- a/components/nifty/common/utils.mjs +++ b/components/nifty/common/utils.mjs @@ -14,3 +14,29 @@ export const clearObj = (obj) => { : v, }), {}); }; + +function optionalParseAsJSON(value) { + try { + return JSON.parse(value); + } catch (e) { + return value; + } +} + +export function parseObjectEntries(value) { + if (!value) { + return {}; + } + const obj = typeof value === "string" + ? JSON.parse(value) + : value; + return Object.fromEntries( + Object.entries(obj).map(([ + key, + value, + ]) => [ + key, + optionalParseAsJSON(value), + ]), + ); +} diff --git a/components/nifty/nifty.app.mjs b/components/nifty/nifty.app.mjs index e6ad58e91e45c..5b9a90d22c048 100644 --- a/components/nifty/nifty.app.mjs +++ b/components/nifty/nifty.app.mjs @@ -155,6 +155,28 @@ export default { })) || []; }, }, + labelIds: { + type: "string[]", + label: "Label IDs", + description: "An array of unique identifiers for the labels", + optional: true, + async options({ page }) { + const { items } = await this.listLabels({ + params: { + limit: LIMIT, + offset: LIMIT * page, + type: "others", + }, + }); + + return items.map(({ + id: value, name: label, + }) => ({ + label, + value, + })); + }, + }, }, methods: { _baseUrl() { @@ -240,6 +262,12 @@ export default { ...opts, }); }, + listLabels(opts = {}) { + return this._makeRequest({ + path: "/labels", + ...opts, + }); + }, createHook(opts = {}) { return this._makeRequest({ method: "POST",