Add Activepieces integration for workflow automation

- Add Activepieces fork with SmoothSchedule custom piece
- Create integrations app with Activepieces service layer
- Add embed token endpoint for iframe integration
- Create Automations page with embedded workflow builder
- Add sidebar visibility fix for embed mode
- Add list inactive customers endpoint to Public API
- Include SmoothSchedule triggers: event created/updated/cancelled
- Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-18 22:59:37 -05:00
parent 9848268d34
commit 3aa7199503
16292 changed files with 1284892 additions and 4708 deletions

View File

@@ -0,0 +1,39 @@
{
"collaboration platform for remote teams to organize and manage projects": "kollaborative Plattform für entfernte Teams zum Organisieren und Verwalten von Projekten",
"\n\t1. Navigate to https://taskade.com/settings/password and scroll down to Personal Access Tokens.\n\t2. Create your personal access token with any name.": "\n\t1. Navigiere zu https://taskade.com/settings/password und scrollen Sie nach unten zu Persönlichen Zugangs-Token.\n\t2. Erstelle deinen persönlichen Zugangs-Token mit jedem Namen.",
"Create Task": "Aufgabe erstellen",
"Complete Task": "Complete Task",
"Delete Task": "Aufgabe löschen",
"Custom API Call": "Eigener API-Aufruf",
"Creates a new task.": "Erstellt eine neue Aufgabe.",
"Complete a task in a project.": "Schließe eine Aufgabe in einem Projekt ab.",
"Delete an existing task in a project.": "Lösche eine existierende Aufgabe in einem Projekt.",
"Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
"Workspace": "Arbeitsbereich",
"Folder": "Ordner",
"Project": "Projekt",
"Content Type": "Inhaltstyp",
"Task Content": "Aufgabeninhalt",
"Placement": "Platzierung",
"Task": "Aufgabe",
"Method": "Methode",
"Headers": "Kopfzeilen",
"Query Parameters": "Abfrageparameter",
"Body": "Körper",
"Response is Binary ?": "Antwort ist binär?",
"No Error on Failure": "Kein Fehler bei Fehler",
"Timeout (in seconds)": "Timeout (in Sekunden)",
"Placement of task in block": "Platzierung der Aufgabe im Block",
"Authorization headers are injected automatically from your connection.": "Autorisierungs-Header werden automatisch von Ihrer Verbindung injiziert.",
"Enable for files like PDFs, images, etc..": "Aktivieren für Dateien wie PDFs, Bilder, etc..",
"text/markdown": "text/markdown",
"text/plain": "text/schlicht",
"afterbegin": "nach Start",
"beforeend": "vor Ende",
"GET": "ERHALTEN",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "LÖSCHEN",
"HEAD": "HEAD"
}

View File

@@ -0,0 +1,39 @@
{
"collaboration platform for remote teams to organize and manage projects": "plataforma de colaboración para equipos remotos para organizar y administrar proyectos",
"\n\t1. Navigate to https://taskade.com/settings/password and scroll down to Personal Access Tokens.\n\t2. Create your personal access token with any name.": "\n\t1. Navegue a https://taskade.com/settings/password y desplácese hacia abajo hasta los tokens de acceso personal.\n\t2. Cree su token de acceso personal con cualquier nombre.",
"Create Task": "Crear tarea",
"Complete Task": "Complete Task",
"Delete Task": "Eliminar tarea",
"Custom API Call": "Llamada API personalizada",
"Creates a new task.": "Crea una nueva tarea.",
"Complete a task in a project.": "Completa una tarea en un proyecto.",
"Delete an existing task in a project.": "Eliminar una tarea existente en un proyecto.",
"Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
"Workspace": "Espacio de trabajo",
"Folder": "Carpeta",
"Project": "Projekt",
"Content Type": "Tipo de contenido",
"Task Content": "Contenido de la tarea",
"Placement": "Colocación",
"Task": "Tarea",
"Method": "Método",
"Headers": "Encabezados",
"Query Parameters": "Parámetros de consulta",
"Body": "Cuerpo",
"Response is Binary ?": "¿Respuesta es binaria?",
"No Error on Failure": "No hay ningún error en fallo",
"Timeout (in seconds)": "Tiempo de espera (en segundos)",
"Placement of task in block": "Colocación de la tarea en el bloque",
"Authorization headers are injected automatically from your connection.": "Las cabeceras de autorización se inyectan automáticamente desde tu conexión.",
"Enable for files like PDFs, images, etc..": "Activar para archivos como PDFs, imágenes, etc.",
"text/markdown": "texto/markdown",
"text/plain": "texto/plano",
"afterbegin": "después de comenzar",
"beforeend": "antes",
"GET": "RECOGER",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "BORRAR",
"HEAD": "LIMPIO"
}

View File

@@ -0,0 +1,39 @@
{
"collaboration platform for remote teams to organize and manage projects": "plateforme de collaboration pour les équipes distantes pour organiser et gérer des projets",
"\n\t1. Navigate to https://taskade.com/settings/password and scroll down to Personal Access Tokens.\n\t2. Create your personal access token with any name.": "\n\t1. Naviguez sur https://taskade.com/settings/password et descendez vers les jetons d'accès personnels.\n\t2. Créez votre jeton d'accès personnel avec n'importe quel nom.",
"Create Task": "Créer une tâche",
"Complete Task": "Complete Task",
"Delete Task": "Supprimer la tâche",
"Custom API Call": "Appel d'API personnalisé",
"Creates a new task.": "Crée une nouvelle tâche.",
"Complete a task in a project.": "Terminer une tâche dans un projet.",
"Delete an existing task in a project.": "Supprimer une tâche existante dans un projet.",
"Make a custom API call to a specific endpoint": "Passer un appel API personnalisé à un endpoint spécifique",
"Workspace": "Espace de travail",
"Folder": "Dossier",
"Project": "Projet",
"Content Type": "Type de contenu",
"Task Content": "Contenu de la tâche",
"Placement": "Placement",
"Task": "Tâche",
"Method": "Méthode",
"Headers": "En-têtes",
"Query Parameters": "Paramètres de requête",
"Body": "Corps",
"Response is Binary ?": "La réponse est Binaire ?",
"No Error on Failure": "Aucune erreur en cas d'échec",
"Timeout (in seconds)": "Délai d'expiration (en secondes)",
"Placement of task in block": "Placement de la tâche dans le bloc",
"Authorization headers are injected automatically from your connection.": "Les en-têtes d'autorisation sont injectés automatiquement à partir de votre connexion.",
"Enable for files like PDFs, images, etc..": "Activer pour les fichiers comme les PDFs, les images, etc.",
"text/markdown": "texte/markdown",
"text/plain": "texte/brut",
"afterbegin": "après le début",
"beforeend": "Précédent",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD"
}

View File

@@ -0,0 +1,39 @@
{
"collaboration platform for remote teams to organize and manage projects": "リモートチームがプロジェクトを整理・管理するためのコラボレーションプラットフォーム",
"\n\t1. Navigate to https://taskade.com/settings/password and scroll down to Personal Access Tokens.\n\t2. Create your personal access token with any name.": "\n\t1. https://taskade.com/settings/password に移動し、パーソナルアクセストークンまでスクロールします。\n\t2. 任意の名前でパーソナルアクセストークンを作成します。",
"Create Task": "タスクを作成",
"Complete Task": "Complete Task",
"Delete Task": "タスクの削除",
"Custom API Call": "カスタムAPI通話",
"Creates a new task.": "新しいタスクを作成します。",
"Complete a task in a project.": "プロジェクトでタスクを完了します。",
"Delete an existing task in a project.": "プロジェクト内の既存のタスクを削除します。",
"Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
"Workspace": "ワークスペース",
"Folder": "Folder",
"Project": "プロジェクト",
"Content Type": "コンテンツタイプ",
"Task Content": "タスクの内容",
"Placement": "配置",
"Task": "タスク",
"Method": "方法",
"Headers": "ヘッダー",
"Query Parameters": "クエリパラメータ",
"Body": "本文",
"Response is Binary ?": "応答はバイナリですか?",
"No Error on Failure": "失敗時にエラーはありません",
"Timeout (in seconds)": "タイムアウト(秒)",
"Placement of task in block": "ブロック内のタスクの配置",
"Authorization headers are injected automatically from your connection.": "認証ヘッダは接続から自動的に注入されます。",
"Enable for files like PDFs, images, etc..": "PDF、画像などのファイルを有効にします。",
"text/markdown": "text/markdown",
"text/plain": "text/plain",
"afterbegin": "始めた後",
"beforeend": "beforeend",
"GET": "取得",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "削除",
"HEAD": "頭"
}

View File

@@ -0,0 +1,39 @@
{
"collaboration platform for remote teams to organize and manage projects": "samenwerkingsplatform voor externe teams om projecten te organiseren en beheren",
"\n\t1. Navigate to https://taskade.com/settings/password and scroll down to Personal Access Tokens.\n\t2. Create your personal access token with any name.": "\n\tA31. Ga naar https://taskade.com/settings/password en scroll naar beneden naar Persoonlijke Toegangstokens.\n\tA32. Creëer je persoonlijke toegangstoken met een willekeurige naam.",
"Create Task": "Taak maken",
"Complete Task": "Complete Task",
"Delete Task": "Taak verwijderen",
"Custom API Call": "Custom API Call",
"Creates a new task.": "Maakt een nieuwe taak aan.",
"Complete a task in a project.": "Voltooi een taak in een project.",
"Delete an existing task in a project.": "Een bestaande taak in een project verwijderen.",
"Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
"Workspace": "werkruimte",
"Folder": "Map",
"Project": "Project",
"Content Type": "Type inhoud",
"Task Content": "Taak inhoud",
"Placement": "Plaatsing",
"Task": "Opdracht",
"Method": "Methode",
"Headers": "Kopteksten",
"Query Parameters": "Query parameters",
"Body": "Lichaam",
"Response is Binary ?": "Antwoord is binair?",
"No Error on Failure": "Geen fout bij fout",
"Timeout (in seconds)": "Time-out (in seconden)",
"Placement of task in block": "Plaatsing van taak in blok",
"Authorization headers are injected automatically from your connection.": "Autorisatie headers worden automatisch geïnjecteerd vanuit uw verbinding.",
"Enable for files like PDFs, images, etc..": "Inschakelen voor bestanden zoals PDF's, afbeeldingen etc..",
"text/markdown": "tekst/markdown",
"text/plain": "tekst/gewoon",
"afterbegin": "nastart",
"beforeend": "betoverd",
"GET": "KRIJG",
"POST": "POSTE",
"PATCH": "BEKIJK",
"PUT": "PUT",
"DELETE": "VERWIJDEREN",
"HEAD": "HOOFD"
}

View File

@@ -0,0 +1,39 @@
{
"collaboration platform for remote teams to organize and manage projects": "plataforma de colaboração para equipes remotas para organizar e gerenciar projetos",
"\n\t1. Navigate to https://taskade.com/settings/password and scroll down to Personal Access Tokens.\n\t2. Create your personal access token with any name.": "U\n\t1. Navegue até https://taskade.com/settings/password e role para baixo até Fichas de Acesso Pessoal.\n\tn° 2. Crie seu token de acesso pessoal com qualquer nome.",
"Create Task": "Criar tarefa",
"Complete Task": "Complete Task",
"Delete Task": "Excluir Tarefa",
"Custom API Call": "Chamada de API personalizada",
"Creates a new task.": "Cria uma nova tarefa.",
"Complete a task in a project.": "Complete uma tarefa em um projeto.",
"Delete an existing task in a project.": "Apagar uma tarefa existente em um projeto.",
"Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
"Workspace": "Workspace",
"Folder": "Pasta",
"Project": "Projecto",
"Content Type": "Tipo de Conteúdo",
"Task Content": "Conteúdo da tarefa",
"Placement": "Colocação",
"Task": "Tarefas",
"Method": "Método",
"Headers": "Cabeçalhos",
"Query Parameters": "Parâmetros da consulta",
"Body": "Conteúdo",
"Response is Binary ?": "A resposta é binária ?",
"No Error on Failure": "Nenhum erro no Failure",
"Timeout (in seconds)": "Tempo limite (em segundos)",
"Placement of task in block": "Colocação de tarefa no bloco",
"Authorization headers are injected automatically from your connection.": "Os cabeçalhos de autorização são inseridos automaticamente a partir da sua conexão.",
"Enable for files like PDFs, images, etc..": "Habilitar para arquivos como PDFs, imagens, etc..",
"text/markdown": "texto/markdown",
"text/plain": "texto/simples",
"afterbegin": "depois",
"beforeend": "anti",
"GET": "OBTER",
"POST": "POSTAR",
"PATCH": "COMPRAR",
"PUT": "COLOCAR",
"DELETE": "EXCLUIR",
"HEAD": "CABEÇA"
}

View File

@@ -0,0 +1,38 @@
{
"Taskade": "Taskade",
"collaboration platform for remote teams to organize and manage projects": "платформа для удаленных команд для организации и управления проектами",
"\n\t1. Navigate to https://taskade.com/settings/password and scroll down to Personal Access Tokens.\n\t2. Create your personal access token with any name.": "\n\t1. Перейдите по ссылке https://taskade.com/settings/password и прокрутите вниз до персональных маркеров доступа.\n\t2. Создайте ваш персональный токен доступа с любым именем.",
"Create Task": "Создать задачу",
"Complete Task": "Complete Task",
"Delete Task": "Удалить задачу",
"Custom API Call": "Пользовательский вызов API",
"Creates a new task.": "Создает новую задачу.",
"Complete a task in a project.": "Завершите задание в проекте.",
"Delete an existing task in a project.": "Удалить существующую задачу в проекте.",
"Make a custom API call to a specific endpoint": "Сделать пользовательский API вызов к определенной конечной точке",
"Workspace": "Рабочая область",
"Folder": "Папка",
"Project": "Проект",
"Content Type": "Тип контента",
"Task Content": "Содержание задачи",
"Placement": "Размещение",
"Task": "Задача",
"Method": "Метод",
"Headers": "Заголовки",
"Query Parameters": "Параметры запроса",
"Body": "Тело",
"No Error on Failure": "Нет ошибок при ошибке",
"Timeout (in seconds)": "Таймаут (в секундах)",
"Placement of task in block": "Размещение задачи в блоке",
"Authorization headers are injected automatically from your connection.": "Заголовки авторизации включаются автоматически из вашего соединения.",
"text/markdown": "текст/markdown",
"text/plain": "текст/простой",
"afterbegin": "после начала",
"beforeend": "до",
"GET": "ПОЛУЧИТЬ",
"POST": "ПОСТ",
"PATCH": "ПАТЧ",
"PUT": "ПОКУПИТЬ",
"DELETE": "УДАЛИТЬ",
"HEAD": "HEAD"
}

View File

@@ -0,0 +1,39 @@
{
"collaboration platform for remote teams to organize and manage projects": "collaboration platform for remote teams to organize and manage projects",
"\n\t1. Navigate to https://taskade.com/settings/password and scroll down to Personal Access Tokens.\n\t2. Create your personal access token with any name.": "\n\t1. Navigate to https://taskade.com/settings/password and scroll down to Personal Access Tokens.\n\t2. Create your personal access token with any name.",
"Create Task": "Create Task",
"Complete Task": "Complete Task",
"Delete Task": "Delete Task",
"Custom API Call": "Custom API Call",
"Creates a new task.": "Creates a new task.",
"Complete a task in a project.": "Complete a task in a project.",
"Delete an existing task in a project.": "Delete an existing task in a project.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Workspace": "Workspace",
"Folder": "Folder",
"Project": "Project",
"Content Type": "Content Type",
"Task Content": "Task Content",
"Placement": "Placement",
"Task": "Task",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Placement of task in block": "Placement of task in block",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
"text/markdown": "text/markdown",
"text/plain": "text/plain",
"afterbegin": "afterbegin",
"beforeend": "beforeend",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD"
}

View File

@@ -0,0 +1,38 @@
{
"Taskade": "Taskade",
"collaboration platform for remote teams to organize and manage projects": "collaboration platform for remote teams to organize and manage projects",
"\n\t1. Navigate to https://taskade.com/settings/password and scroll down to Personal Access Tokens.\n\t2. Create your personal access token with any name.": "\n\t1. Navigate to https://taskade.com/settings/password and scroll down to Personal Access Tokens.\n\t2. Create your personal access token with any name.",
"Create Task": "Create Task",
"Complete Task": "Complete Task",
"Delete Task": "Delete Task",
"Custom API Call": "Custom API Call",
"Creates a new task.": "Creates a new task.",
"Complete a task in a project.": "Complete a task in a project.",
"Delete an existing task in a project.": "Delete an existing task in a project.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Workspace": "Workspace",
"Folder": "Folder",
"Project": "Project",
"Content Type": "Content Type",
"Task Content": "Task Content",
"Placement": "Placement",
"Task": "Task",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Placement of task in block": "Placement of task in block",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"text/markdown": "text/markdown",
"text/plain": "text/plain",
"afterbegin": "afterbegin",
"beforeend": "beforeend",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD"
}

View File

@@ -0,0 +1,39 @@
{
"collaboration platform for remote teams to organize and manage projects": "collaboration platform for remote teams to organize and manage projects",
"\n\t1. Navigate to https://taskade.com/settings/password and scroll down to Personal Access Tokens.\n\t2. Create your personal access token with any name.": "\n\t1. Navigate to https://taskade.com/settings/password and scroll down to Personal Access Tokens.\n\t2. Create your personal access token with any name.",
"Create Task": "Create Task",
"Complete Task": "Complete Task",
"Delete Task": "Delete Task",
"Custom API Call": "自定义 API 呼叫",
"Creates a new task.": "Creates a new task.",
"Complete a task in a project.": "Complete a task in a project.",
"Delete an existing task in a project.": "Delete an existing task in a project.",
"Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
"Workspace": "Workspace",
"Folder": "Folder",
"Project": "项目",
"Content Type": "Content Type",
"Task Content": "Task Content",
"Placement": "Placement",
"Task": "Task",
"Method": "方法",
"Headers": "信头",
"Query Parameters": "查询参数",
"Body": "正文内容",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "失败时没有错误",
"Timeout (in seconds)": "超时(秒)",
"Placement of task in block": "Placement of task in block",
"Authorization headers are injected automatically from your connection.": "授权头自动从您的连接中注入。",
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
"text/markdown": "text/markdown",
"text/plain": "text/plain",
"afterbegin": "afterbegin",
"beforeend": "beforeend",
"GET": "获取",
"POST": "帖子",
"PATCH": "PATCH",
"PUT": "弹出",
"DELETE": "删除",
"HEAD": "黑色"
}

View File

@@ -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.30.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: async (auth) => ({ Authorization: `Bearer ${auth.secret_text}` }),
}),
],
triggers: [],
});

View File

@@ -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.secret_text);
return await client.completeTask(project_id, task_id);
},
});

View File

@@ -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.secret_text);
return await client.createTask(project_id, {
content,
contentType: content_type,
placement,
});
},
});

View File

@@ -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.secret_text);
return await client.deleteTask(project_id, task_id);
},
});

View File

@@ -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}`);
}
}

View File

@@ -0,0 +1,133 @@
import { DropdownOption, Property } from '@activepieces/pieces-framework';
import { TaskadeAPIClient } from './client';
import { taskadeAuth } from '../..';
const createEmptyOptions = (placeholder: string) => {
return {
disabled: true,
options: [],
placeholder,
};
};
export const taskadeProps = {
workspace_id: Property.Dropdown({
auth: taskadeAuth,
displayName: 'Workspace',
refreshers: [],
required: true,
options: async ({ auth }) => {
if (!auth) {
return createEmptyOptions('Please connect account first.');
}
const client = new TaskadeAPIClient(auth.secret_text);
const response = await client.listWorkspaces();
const options: DropdownOption<string>[] = [];
for (const workspace of response.items) {
options.push({ label: workspace.name, value: workspace.id });
}
return {
disabled: false,
options,
};
},
}),
folder_id: Property.Dropdown({
auth: taskadeAuth,
displayName: 'Folder',
refreshers: ['workspace_id'],
required: false,
options: async ({ auth, workspace_id }) => {
if (!auth) {
return createEmptyOptions('Please connect account first.');
}
if (!workspace_id) {
return createEmptyOptions('Please select workspace.');
}
const client = new TaskadeAPIClient(auth.secret_text);
const response = await client.listWorkspaceFolders(workspace_id as string);
const options: DropdownOption<string>[] = [];
for (const folder of response.items) {
options.push({ label: folder.name, value: folder.id });
}
return {
disabled: false,
options,
};
},
}),
project_id: Property.Dropdown({
auth: taskadeAuth,
displayName: 'Project',
refreshers: ['workspace_id', 'folder_id'],
required: true,
options: async ({ auth, workspace_id, folder_id }) => {
if (!auth) {
return createEmptyOptions('Please connect account first.');
}
if (!workspace_id) {
return createEmptyOptions('Please select workspace.');
}
const workspaceId = workspace_id as string;
const folderId = (folder_id as string) ?? workspaceId;
const client = new TaskadeAPIClient(auth.secret_text);
const response = await client.listProjects(folderId as string);
const options: DropdownOption<string>[] = [];
for (const project of response.items) {
options.push({ label: project.name, value: project.id });
}
return {
disabled: false,
options,
};
},
}),
task_id: Property.Dropdown({
auth: taskadeAuth,
displayName: 'Task',
refreshers: ['project_id'],
required: true,
options: async ({ auth, project_id }) => {
if (!auth) {
return createEmptyOptions('Please connect account first.');
}
if (!project_id) {
return createEmptyOptions('Please select project.');
}
const client = new TaskadeAPIClient(auth.secret_text);
const options: DropdownOption<string>[] = [];
let after;
let moreTasks = true;
while (moreTasks) {
const response = await client.listTasks(project_id as string, { limit: 100, after });
if (response.items.length === 0) {
moreTasks = false;
} else {
after = response.items[response.items.length - 1].id;
for (const task of response.items) {
options.push({ label: task.text, value: task.id });
}
}
}
return {
disabled: false,
options,
};
},
}),
};

View File

@@ -0,0 +1,42 @@
export interface ListAPIResponse<T> {
ok: boolean;
items: Array<T>;
}
export interface BaseResponse {
id: string;
name: string;
}
export type WorkspaceResponse = BaseResponse;
export type WorkspaceFolderResponse = BaseResponse;
export type ProjectResponse = BaseResponse;
export interface CreateTaskParams {
contentType: string;
content: string;
placement: string;
}
export interface TaskResponse {
id: string;
parentId: string;
text: string;
completed: boolean;
}
export interface CreateTaskResponse {
ok: boolean;
item: TaskResponse[];
}
export interface CreateTaskDateParams {
start: {
date: string;
time: string;
};
end?: {
date: string;
time: string;
};
}