Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(taskade): Create Task, Complete Task and Delete Task Actions #4664

Merged
merged 5 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 33 additions & 0 deletions packages/pieces/community/taskade/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"extends": [
"../../../../.eslintrc.base.json"
],
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts",
"*.tsx",
"*.js",
"*.jsx"
],
"rules": {}
},
{
"files": [
"*.ts",
"*.tsx"
],
"rules": {}
},
{
"files": [
"*.js",
"*.jsx"
],
"rules": {}
}
]
}
7 changes: 7 additions & 0 deletions packages/pieces/community/taskade/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# pieces-taskade

This library was generated with [Nx](https://nx.dev).

## Building

Run `nx build pieces-taskade` to build the library.
4 changes: 4 additions & 0 deletions packages/pieces/community/taskade/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "@activepieces/piece-taskade",
"version": "0.0.1"
}
38 changes: 38 additions & 0 deletions packages/pieces/community/taskade/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "pieces-taskade",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/pieces/community/taskade/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/packages/pieces/community/taskade",
"tsConfig": "packages/pieces/community/taskade/tsconfig.lib.json",
"packageJson": "packages/pieces/community/taskade/package.json",
"main": "packages/pieces/community/taskade/src/index.ts",
"assets": [
"packages/pieces/community/taskade/*.md"
],
"buildableProjectDepsInPackageJsonType": "dependencies",
"updateBuildableProjectDepsInPackageJson": true
}
},
"publish": {
"command": "node tools/scripts/publish.mjs pieces-taskade {args.ver} {args.tag}",
"dependsOn": [
"build"
]
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": [
"{options.outputFile}"
]
}
},
"tags": []
}
35 changes: 35 additions & 0 deletions packages/pieces/community/taskade/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { createPiece, PieceAuth } from '@activepieces/pieces-framework';
import { createTaskAction } from './lib/actions/create-task.action';
import { PieceCategory } from '@activepieces/shared';
import { completeTaskAction } from './lib/actions/complete-task.action';
import { deleteTaskAction } from './lib/actions/delete-task.action';
import { createCustomApiCallAction } from '@activepieces/pieces-common';

export const taskadeAuth = PieceAuth.SecretText({
displayName: 'Personal Token',
required: true,
description: `
1. Navigate to https://taskade.com/settings/password and scroll down to Personal Access Tokens.
2. Create your personal access token with any name.`,
});

export const taskade = createPiece({
displayName: 'Taskade',
auth: taskadeAuth,
minimumSupportedRelease: '0.20.0',
categories: [PieceCategory.PRODUCTIVITY],
description: 'collaboration platform for remote teams to organize and manage projects',
logoUrl: 'https://cdn.activepieces.com/pieces/taskade.png',
authors: ['kishanprmr'],
actions: [
createTaskAction,
completeTaskAction,
deleteTaskAction,
createCustomApiCallAction({
baseUrl: () => 'https://www.taskade.com/api/v1',
auth: taskadeAuth,
authMapping: (auth) => ({ Authorization: `Bearer ${auth as string}` }),
}),
],
triggers: [],
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { taskadeAuth } from '../../';
import { createAction } from '@activepieces/pieces-framework';
import { taskadeProps } from '../common/props';
import { TaskadeAPIClient } from '../common/client';

export const completeTaskAction = createAction({
auth: taskadeAuth,
name: 'taskade-complete-task',
displayName: 'Complete Task',
description: 'Complete a task in a project.',
props: {
workspace_id: taskadeProps.workspace_id,
folder_id: taskadeProps.folder_id,
project_id: taskadeProps.project_id,
task_id: taskadeProps.task_id,
},
async run(context) {
const { project_id, task_id } = context.propsValue;

const client = new TaskadeAPIClient(context.auth);

return await client.completeTask(project_id, task_id);
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { taskadeAuth } from '../../';
import { createAction, Property } from '@activepieces/pieces-framework';
import { taskadeProps } from '../common/props';
import { TaskadeAPIClient } from '../common/client';

export const createTaskAction = createAction({
auth: taskadeAuth,
name: 'taskade-create-task',
displayName: 'Create Task',
description: 'Creates a new task.',
props: {
workspace_id: taskadeProps.workspace_id,
folder_id: taskadeProps.folder_id,
project_id: taskadeProps.project_id,
content_type: Property.StaticDropdown({
displayName: 'Content Type',
required: true,
defaultValue: 'text/markdown',
options: {
disabled: false,
options: [
{
label: 'text/markdown',
value: 'text/markdown',
},
{
label: 'text/plain',
value: 'text/plain',
},
],
},
}),
content: Property.LongText({
displayName: 'Task Content',
required: true,
}),
placement: Property.StaticDropdown({
displayName: 'Placement',
description: 'Placement of task in block',
required: true,
defaultValue: 'afterbegin',
options: {
disabled: false,
options: [
{
label: 'afterbegin',
value: 'afterbegin',
},
{
label: 'beforeend',
value: 'beforeend',
},
],
},
}),
},
async run(context) {
const { project_id, content_type, content, placement } = context.propsValue;

const client = new TaskadeAPIClient(context.auth);

return await client.createTask(project_id, {
content,
contentType: content_type,
placement,
});
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { taskadeAuth } from '../../';
import { createAction } from '@activepieces/pieces-framework';
import { taskadeProps } from '../common/props';
import { TaskadeAPIClient } from '../common/client';

export const deleteTaskAction = createAction({
auth: taskadeAuth,
name: 'taskade-delete-task',
displayName: 'Delete Task',
description: 'Delete an existing task in a project.',
props: {
workspace_id: taskadeProps.workspace_id,
folder_id: taskadeProps.folder_id,
project_id: taskadeProps.project_id,
task_id: taskadeProps.task_id,
},
async run(context) {
const { project_id, task_id } = context.propsValue;

const client = new TaskadeAPIClient(context.auth);

return await client.deleteTask(project_id, task_id);
},
});
105 changes: 105 additions & 0 deletions packages/pieces/community/taskade/src/lib/common/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import {
HttpMessageBody,
HttpMethod,
QueryParams,
httpClient,
HttpRequest,
AuthenticationType,
} from '@activepieces/pieces-common';
import {
CreateTaskDateParams,
CreateTaskParams,
ListAPIResponse,
ProjectResponse,
CreateTaskResponse,
WorkspaceFolderResponse,
WorkspaceResponse,
TaskResponse,
} from './types';

type RequestParams = Record<string, string | number | string[] | undefined>;

export class TaskadeAPIClient {
constructor(private personalToken: string) {}

async makeRequest<T extends HttpMessageBody>(
method: HttpMethod,
resourceUri: string,
query?: RequestParams,
body: any | undefined = undefined,
): Promise<T> {
const baseUrl = 'https://www.taskade.com/api/v1';
const qs: QueryParams = {};

if (query) {
for (const [key, value] of Object.entries(query)) {
if (value !== null && value !== undefined) {
qs[key] = String(value);
}
}
}

const request: HttpRequest = {
method,
url: baseUrl + resourceUri,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: this.personalToken,
},
queryParams: qs,
body,
};

const response = await httpClient.sendRequest<T>(request);
return response.body;
}

async listWorkspaces(): Promise<ListAPIResponse<WorkspaceResponse>> {
return await this.makeRequest(HttpMethod.GET, '/workspaces');
}

async listWorkspaceFolders(
workspace_id: string,
): Promise<ListAPIResponse<WorkspaceFolderResponse>> {
return await this.makeRequest(HttpMethod.GET, `/workspaces/${workspace_id}/folders`);
}

async listProjects(folder_id: string): Promise<ListAPIResponse<ProjectResponse>> {
return await this.makeRequest(HttpMethod.GET, `/folders/${folder_id}/projects`);
}

async createTask(projectId: string, params: CreateTaskParams): Promise<CreateTaskResponse> {
return await this.makeRequest(HttpMethod.POST, `/projects/${projectId}/tasks`, undefined, {
tasks: [params],
});
}

async createTaskDate(projectId: string, taskId: string, params: CreateTaskDateParams) {
return await this.makeRequest(
HttpMethod.PUT,
`/projects/${projectId}/tasks/${taskId}/date`,
undefined,
params,
);
}

async listTasks(
projectId: string,
params: RequestParams,
): Promise<ListAPIResponse<TaskResponse>> {
return await this.makeRequest(HttpMethod.GET, `/projects/${projectId}/tasks`, params);
}

async completeTask(projectId: string, taskId: string) {
return await this.makeRequest(
HttpMethod.POST,
`/projects/${projectId}/tasks/${taskId}/complete`,
undefined,
{},
);
}

async deleteTask(projectId: string, taskId: string) {
return await this.makeRequest(HttpMethod.DELETE, `/projects/${projectId}/tasks/${taskId}`);
}
}