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,3 @@
{
"presets": [["@nx/js/babel", { "useBuiltIns": "usage" }]]
}

View File

@@ -0,0 +1,18 @@
{
"extends": ["../../../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}

View File

@@ -0,0 +1,7 @@
# pieces-todoist
This library was generated with [Nx](https://nx.dev).
## Running lint
Run `nx lint pieces-todoist` to execute the lint via [ESLint](https://eslint.org/).

View File

@@ -0,0 +1,4 @@
{
"name": "@activepieces/piece-todoist",
"version": "0.3.17"
}

View File

@@ -0,0 +1,51 @@
{
"name": "pieces-todoist",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/pieces/community/todoist/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/packages/pieces/community/todoist",
"tsConfig": "packages/pieces/community/todoist/tsconfig.lib.json",
"packageJson": "packages/pieces/community/todoist/package.json",
"main": "packages/pieces/community/todoist/src/index.ts",
"assets": [
"packages/pieces/community/todoist/*.md",
{
"input": "packages/pieces/community/todoist/src/i18n",
"output": "./src/i18n",
"glob": "**/!(i18n.json)"
}
],
"buildableProjectDepsInPackageJsonType": "dependencies",
"updateBuildableProjectDepsInPackageJson": true
},
"dependsOn": [
"^build",
"prebuild"
]
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": [
"{options.outputFile}"
]
},
"prebuild": {
"executor": "nx:run-commands",
"options": {
"cwd": "packages/pieces/community/todoist",
"command": "bun install --no-save --silent"
},
"dependsOn": [
"^build"
]
}
},
"tags": []
}

View File

@@ -0,0 +1,47 @@
{
"Todoist": "Todoist",
"To-do list and task manager": "To-do list and task manager",
"Create Task": "Create Task",
"Update Task": "Update Task",
"Find Task": "Find Task",
"Mark Task as Completed": "Mark Task as Completed",
"Custom API Call": "Custom API Call",
"Create task": "Create task",
"Updates an existing task.": "Updates an existing task.",
"Finds a task by name.": "Finds a task by name.",
"Marks a task as being completed.": "Marks a task as being completed.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Project": "Project",
"content": "content",
"Description": "Description",
"Labels": "Labels",
"Priority": "Priority",
"Due date": "Due date",
"Section": "Section",
"Task ID": "Task ID",
"Name": "Name",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Task project ID. If not set, task is put to user's Inbox.": "Task project ID. If not set, task is put to user's Inbox.",
"The task's content. It may contain some markdown-formatted text and hyperlinks": "The task's content. It may contain some markdown-formatted text and hyperlinks",
"A description for the task. This value may contain some markdown-formatted text and hyperlinks.": "A description for the task. This value may contain some markdown-formatted text and hyperlinks.",
"The task's labels (a list of names that may represent either personal or shared labels)": "The task's labels (a list of names that may represent either personal or shared labels)",
"Task priority from 1 (normal) to 4 (urgent)": "Task priority from 1 (normal) to 4 (urgent)",
"Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time": "Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time",
"The name of the task to search for.": "The name of the task to search for.",
"Search for tasks within the selected project. If left blank, then all projects are searched.": "Search for tasks within the selected project. If left blank, then all projects are searched.",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"Task Completed": "Task Completed",
"Triggers when a new task is completed": "Triggers when a new task is completed",
"Leave it blank if you want to get completed tasks from all your projects.": "Leave it blank if you want to get completed tasks from all your projects."
}

View File

@@ -0,0 +1,48 @@
{
"To-do list and task manager": "To-do-Liste und Task-Manager",
"Create Task": "Aufgabe erstellen",
"Update Task": "Aufgabe aktualisieren",
"Find Task": "Aufgabe finden",
"Mark Task as Completed": "Aufgabe als erledigt markieren",
"Custom API Call": "Eigener API-Aufruf",
"Create task": "Aufgabe erstellen",
"Updates an existing task.": "Aktualisiert eine existierende Aufgabe.",
"Finds a task by name.": "Findet eine Aufgabe nach Namen.",
"Marks a task as being completed.": "Markiert eine Aufgabe als erledigt.",
"Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
"Project": "Projekt",
"content": "inhalt",
"Description": "Beschreibung",
"Labels": "Etiketten",
"Priority": "Priorität",
"Due date": "Fälligkeitsdatum",
"Section": "Abschnitt",
"Task ID": "Task ID",
"Name": "Name",
"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)",
"Task project ID. If not set, task is put to user's Inbox.": "Projekt-ID der Aufgabe. Wenn nicht festgelegt, wird die Aufgabe in den Posteingang des Benutzers gestellt.",
"The task's content. It may contain some markdown-formatted text and hyperlinks": "Der Inhalt der Aufgabe. Er kann einige markdownformatierte Texte und Hyperlinks enthalten",
"A description for the task. This value may contain some markdown-formatted text and hyperlinks.": "Eine Beschreibung für die Aufgabe. Dieser Wert kann einige markdownformatierte Texte und Hyperlinks enthalten.",
"The task's labels (a list of names that may represent either personal or shared labels)": "Die Labels der Aufgabe (eine Liste von Namen, die persönliche oder geteilte Labels darstellen können)",
"Task priority from 1 (normal) to 4 (urgent)": "Aufgabenpriorität von 1 (normal) bis 4 (dringend)",
"Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time": "Kann entweder ein bestimmtes Datum im Format JJJJJ-MM-TT im Verhältnis zur Zeitzone des Benutzers sein ein bestimmtes Datum und Uhrzeit im RFC3339 Format oder ein von Menschen definiertes Datum (z. . 'Nächsten Montag') mit lokaler Zeit",
"The name of the task to search for.": "Der Name der zu suchenden Aufgabe.",
"Search for tasks within the selected project. If left blank, then all projects are searched.": "Suche nach Aufgaben innerhalb des ausgewählten Projekts. Wenn leer gelassen, werden alle Projekte durchsucht.",
"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..",
"GET": "ERHALTEN",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "LÖSCHEN",
"HEAD": "HEAD",
"Task Completed": "Aufgabe erledigt",
"Triggers when a new task is completed": "Wird ausgelöst, wenn eine neue Aufgabe abgeschlossen ist",
"Leave it blank if you want to get completed tasks from all your projects.": "Lassen Sie es leer, wenn Sie erledigte Aufgaben aus all Ihren Projekten erhalten möchten."
}

View File

@@ -0,0 +1,48 @@
{
"To-do list and task manager": "Lista de tareas y administrador de tareas",
"Create Task": "Crear tarea",
"Update Task": "Actualizar tarea",
"Find Task": "Buscar tarea",
"Mark Task as Completed": "Marcar tarea como completada",
"Custom API Call": "Llamada API personalizada",
"Create task": "Crear tarea",
"Updates an existing task.": "Actualiza una tarea existente.",
"Finds a task by name.": "Encuentra una tarea por nombre.",
"Marks a task as being completed.": "Marca una tarea como completada.",
"Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
"Project": "Projekt",
"content": "contenido",
"Description": "Descripción",
"Labels": "Etiquetas",
"Priority": "Prioridad",
"Due date": "Fecha de fin",
"Section": "Sección",
"Task ID": "Task ID",
"Name": "Nombre",
"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)",
"Task project ID. If not set, task is put to user's Inbox.": "ID de proyecto de tarea. Si no se establece, la tarea se pone en la bandeja de entrada del usuario.",
"The task's content. It may contain some markdown-formatted text and hyperlinks": "El contenido de la tarea. Puede contener algunos hipervínculos y texto con formato markdown",
"A description for the task. This value may contain some markdown-formatted text and hyperlinks.": "Una descripción para la tarea. Este valor puede contener algunos hiperenlaces y texto con formato markdown.",
"The task's labels (a list of names that may represent either personal or shared labels)": "Etiquetas de la tarea (una lista de nombres que pueden representar etiquetas personales o compartidas)",
"Task priority from 1 (normal) to 4 (urgent)": "Prioridad de la tarea de 1 (normal) a 4 (urgente)",
"Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time": "Puede ser una fecha específica en formato AAA-MM-DD relativa a la zona horaria del usuario, una fecha y hora específicas en formato RFC33339, o una fecha humana definida (e. . 'próximo lunes') usando la hora local",
"The name of the task to search for.": "El nombre de la tarea a buscar.",
"Search for tasks within the selected project. If left blank, then all projects are searched.": "Buscar tareas dentro del proyecto seleccionado. Si se deja en blanco, se buscan todos los proyectos.",
"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.",
"GET": "RECOGER",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "BORRAR",
"HEAD": "LIMPIO",
"Task Completed": "Tarea completada",
"Triggers when a new task is completed": "Se activa cuando se completa una nueva tarea",
"Leave it blank if you want to get completed tasks from all your projects.": "Déjalo en blanco si quieres obtener las tareas completadas de todos tus proyectos."
}

View File

@@ -0,0 +1,48 @@
{
"To-do list and task manager": "Liste de tâches à faire et gestionnaire de tâches",
"Create Task": "Créer une tâche",
"Update Task": "Tâche de mise à jour",
"Find Task": "Trouver une tâche",
"Mark Task as Completed": "Marquer la tâche comme terminée",
"Custom API Call": "Appel d'API personnalisé",
"Create task": "Créer une tâche",
"Updates an existing task.": "Met à jour une tâche existante.",
"Finds a task by name.": "Trouve une tâche par nom.",
"Marks a task as being completed.": "Marque une tâche comme en cours d'exécution.",
"Make a custom API call to a specific endpoint": "Passer un appel API personnalisé à un endpoint spécifique",
"Project": "Projet",
"content": "contenu",
"Description": "Libellé",
"Labels": "Étiquettes",
"Priority": "Priorité",
"Due date": "Date d'échéance",
"Section": "Section",
"Task ID": "Task ID",
"Name": "Nom",
"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)",
"Task project ID. If not set, task is put to user's Inbox.": "ID du projet de tâche. Si non défini, la tâche est mise dans la boîte de réception de l'utilisateur.",
"The task's content. It may contain some markdown-formatted text and hyperlinks": "Le contenu de la tâche. Il peut contenir du texte et des hyperliens au format markdown",
"A description for the task. This value may contain some markdown-formatted text and hyperlinks.": "Une description pour la tâche. Cette valeur peut contenir du texte mis en forme par markdown et des hyperliens.",
"The task's labels (a list of names that may represent either personal or shared labels)": "Étiquettes de la tâche (une liste de noms qui peuvent représenter des étiquettes personnelles ou partagées)",
"Task priority from 1 (normal) to 4 (urgent)": "Priorité de la tâche de 1 (normal) à 4 (urgent)",
"Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time": "Peut être soit une date spécifique au format AAAA-MM-JJ par rapport au fuseau horaire de l'utilisateur une date et une heure spécifiques au format RFC3339, ou une date définie par l'être humain (e. . 'lundi prochain') en utilisant l'heure locale",
"The name of the task to search for.": "Le nom de la tâche à rechercher.",
"Search for tasks within the selected project. If left blank, then all projects are searched.": "Rechercher des tâches dans le projet sélectionné. Si laissé vide, alors tous les projets sont recherchés.",
"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.",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"Task Completed": "Tâche terminée",
"Triggers when a new task is completed": "Déclenche quand une nouvelle tâche est terminée",
"Leave it blank if you want to get completed tasks from all your projects.": "Laissez vide si vous voulez obtenir des tâches terminées de tous vos projets."
}

View File

@@ -0,0 +1,47 @@
{
"Todoist": "Todoist",
"To-do list and task manager": "To-do list and task manager",
"Create Task": "Create Task",
"Update Task": "Update Task",
"Find Task": "Find Task",
"Mark Task as Completed": "Mark Task as Completed",
"Custom API Call": "Custom API Call",
"Create task": "Create task",
"Updates an existing task.": "Updates an existing task.",
"Finds a task by name.": "Finds a task by name.",
"Marks a task as being completed.": "Marks a task as being completed.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Project": "Project",
"content": "content",
"Description": "Description",
"Labels": "Labels",
"Priority": "Priority",
"Due date": "Due date",
"Section": "Section",
"Task ID": "Task ID",
"Name": "Name",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Task project ID. If not set, task is put to user's Inbox.": "Task project ID. If not set, task is put to user's Inbox.",
"The task's content. It may contain some markdown-formatted text and hyperlinks": "The task's content. It may contain some markdown-formatted text and hyperlinks",
"A description for the task. This value may contain some markdown-formatted text and hyperlinks.": "A description for the task. This value may contain some markdown-formatted text and hyperlinks.",
"The task's labels (a list of names that may represent either personal or shared labels)": "The task's labels (a list of names that may represent either personal or shared labels)",
"Task priority from 1 (normal) to 4 (urgent)": "Task priority from 1 (normal) to 4 (urgent)",
"Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time": "Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time",
"The name of the task to search for.": "The name of the task to search for.",
"Search for tasks within the selected project. If left blank, then all projects are searched.": "Search for tasks within the selected project. If left blank, then all projects are searched.",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"Task Completed": "Task Completed",
"Triggers when a new task is completed": "Triggers when a new task is completed",
"Leave it blank if you want to get completed tasks from all your projects.": "Leave it blank if you want to get completed tasks from all your projects."
}

View File

@@ -0,0 +1,47 @@
{
"Todoist": "Todoist",
"To-do list and task manager": "To-do list and task manager",
"Create Task": "Create Task",
"Update Task": "Update Task",
"Find Task": "Find Task",
"Mark Task as Completed": "Mark Task as Completed",
"Custom API Call": "Custom API Call",
"Create task": "Create task",
"Updates an existing task.": "Updates an existing task.",
"Finds a task by name.": "Finds a task by name.",
"Marks a task as being completed.": "Marks a task as being completed.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Project": "Project",
"content": "content",
"Description": "Description",
"Labels": "Labels",
"Priority": "Priority",
"Due date": "Due date",
"Section": "Section",
"Task ID": "Task ID",
"Name": "Name",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Task project ID. If not set, task is put to user's Inbox.": "Task project ID. If not set, task is put to user's Inbox.",
"The task's content. It may contain some markdown-formatted text and hyperlinks": "The task's content. It may contain some markdown-formatted text and hyperlinks",
"A description for the task. This value may contain some markdown-formatted text and hyperlinks.": "A description for the task. This value may contain some markdown-formatted text and hyperlinks.",
"The task's labels (a list of names that may represent either personal or shared labels)": "The task's labels (a list of names that may represent either personal or shared labels)",
"Task priority from 1 (normal) to 4 (urgent)": "Task priority from 1 (normal) to 4 (urgent)",
"Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time": "Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time",
"The name of the task to search for.": "The name of the task to search for.",
"Search for tasks within the selected project. If left blank, then all projects are searched.": "Search for tasks within the selected project. If left blank, then all projects are searched.",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"Task Completed": "Task Completed",
"Triggers when a new task is completed": "Triggers when a new task is completed",
"Leave it blank if you want to get completed tasks from all your projects.": "Leave it blank if you want to get completed tasks from all your projects."
}

View File

@@ -0,0 +1,48 @@
{
"To-do list and task manager": "To-do リストとタスク マネージャー",
"Create Task": "タスクを作成",
"Update Task": "タスクの更新",
"Find Task": "タスクを検索",
"Mark Task as Completed": "タスクを完了としてマーク",
"Custom API Call": "カスタムAPI通話",
"Create task": "タスクを作成",
"Updates an existing task.": "既存のタスクを更新する。",
"Finds a task by name.": "タスクを名前で検索します。",
"Marks a task as being completed.": "タスクを完了としてマークします。",
"Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
"Project": "プロジェクト",
"content": "コンテンツ",
"Description": "説明",
"Labels": "ラベル",
"Priority": "優先度",
"Due date": "期限",
"Section": "セクション",
"Task ID": "Task ID",
"Name": "名前",
"Method": "方法",
"Headers": "ヘッダー",
"Query Parameters": "クエリパラメータ",
"Body": "本文",
"Response is Binary ?": "応答はバイナリですか?",
"No Error on Failure": "失敗時にエラーはありません",
"Timeout (in seconds)": "タイムアウト(秒)",
"Task project ID. If not set, task is put to user's Inbox.": "タスクプロジェクトID。設定されていない場合、タスクはユーザーの受信トレイに配置されます。",
"The task's content. It may contain some markdown-formatted text and hyperlinks": "タスクの内容。マークダウン形式のテキストとハイパーリンクが含まれている可能性があります。",
"A description for the task. This value may contain some markdown-formatted text and hyperlinks.": "タスクの説明です。この値には、マークダウン形式のテキストとハイパーリンクが含まれている場合があります。",
"The task's labels (a list of names that may represent either personal or shared labels)": "タスクのラベル (個人または共有ラベルのいずれかを示す名前のリスト)",
"Task priority from 1 (normal) to 4 (urgent)": "タスクの優先度 1 (通常) から 4 (緊急)",
"Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time": "ユーザーのタイムゾーンに対するYYYY-MM-DD形式の特定の日付を指定できます。 RFC3339 形式の特定の日付と時刻、または人間が定義した日付 (e. を選択します。",
"The name of the task to search for.": "検索するタスクの名前",
"Search for tasks within the selected project. If left blank, then all projects are searched.": "選択したプロジェクト内のタスクを検索します。空白の場合は、すべてのプロジェクトが検索されます。",
"Authorization headers are injected automatically from your connection.": "認証ヘッダは接続から自動的に注入されます。",
"Enable for files like PDFs, images, etc..": "PDF、画像などのファイルを有効にします。",
"GET": "取得",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "削除",
"HEAD": "頭",
"Task Completed": "タスクが完了しました",
"Triggers when a new task is completed": "新しいタスクが完了したときにトリガーします",
"Leave it blank if you want to get completed tasks from all your projects.": "すべてのプロジェクトから完了したタスクを取得したい場合は、空白のままにしてください。"
}

View File

@@ -0,0 +1,48 @@
{
"To-do list and task manager": "To-do lijst en taakbeheer",
"Create Task": "Taak maken",
"Update Task": "Taak bijwerken",
"Find Task": "Zoek Taak",
"Mark Task as Completed": "Markeer taak als voltooid",
"Custom API Call": "Custom API Call",
"Create task": "Taak aanmaken",
"Updates an existing task.": "Werkt een bestaande taak bij.",
"Finds a task by name.": "Vindt een taak op naam.",
"Marks a task as being completed.": "Markeer een taak als voltooid.",
"Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
"Project": "Project",
"content": "inhoud",
"Description": "Beschrijving",
"Labels": "Labels",
"Priority": "Prioriteit",
"Due date": "Vervaldatum",
"Section": "Sectie",
"Task ID": "Task ID",
"Name": "Naam",
"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)",
"Task project ID. If not set, task is put to user's Inbox.": "Taakproject ID. Als dit niet is ingesteld, wordt de taak in de Inbox van de gebruiker geplaatst.",
"The task's content. It may contain some markdown-formatted text and hyperlinks": "De inhoud van de opdracht. Deze kan markdown-geformatteerde tekst en hyperlinks bevatten",
"A description for the task. This value may contain some markdown-formatted text and hyperlinks.": "Een beschrijving van de taak. Deze waarde mag enkele markdown-opgemaakte tekst en hyperlinks bevatten.",
"The task's labels (a list of names that may represent either personal or shared labels)": "De labels van de taak (een lijst met namen die persoonlijke of gedeelde labels kunnen bevatten)",
"Task priority from 1 (normal) to 4 (urgent)": "Taak prioriteit van 1 (normaal) tot 4 (urgent)",
"Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time": "Kan een specifieke datum in YYYY-MM-DD formaat zijn ten opzichte van de tijdzone van de gebruiker een specifieke datum en tijd in RFC3339 formaat, of een menselijke gedefinieerd datum (bijv. . 'volgende maandag') gebruikt lokale tijd",
"The name of the task to search for.": "De naam van de taak waarnaar gezocht moet worden.",
"Search for tasks within the selected project. If left blank, then all projects are searched.": "Zoek naar taken binnen het geselecteerde project. Indien leeg worden alle projecten doorzocht.",
"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..",
"GET": "KRIJG",
"POST": "POSTE",
"PATCH": "BEKIJK",
"PUT": "PUT",
"DELETE": "VERWIJDEREN",
"HEAD": "HOOFD",
"Task Completed": "Taak voltooid",
"Triggers when a new task is completed": "Triggert wanneer een nieuwe taak is voltooid",
"Leave it blank if you want to get completed tasks from all your projects.": "Laat het leeg als je voltooide taken van al je projecten wilt krijgen."
}

View File

@@ -0,0 +1,48 @@
{
"To-do list and task manager": "Lista de tarefas e gerenciador de tarefas",
"Create Task": "Criar tarefa",
"Update Task": "Atualizar Tarefa",
"Find Task": "Procurar Tarefa",
"Mark Task as Completed": "Marcar Tarefa como concluída",
"Custom API Call": "Chamada de API personalizada",
"Create task": "Criar tarefa",
"Updates an existing task.": "Atualiza uma tarefa existente.",
"Finds a task by name.": "Encontra uma tarefa por nome.",
"Marks a task as being completed.": "Marcar uma tarefa como sendo concluída.",
"Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
"Project": "Projecto",
"content": "conteúdo",
"Description": "Descrição",
"Labels": "Marcadores",
"Priority": "Prioridade",
"Due date": "Data de vencimento",
"Section": "Turma",
"Task ID": "Task ID",
"Name": "Nome",
"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)",
"Task project ID. If not set, task is put to user's Inbox.": "ID do projeto de tarefa. Se não for definido, a tarefa será colocada na caixa de entrada do usuário.",
"The task's content. It may contain some markdown-formatted text and hyperlinks": "Conteúdo da tarefa. Pode conter alguns hiperlinks e texto formatados em markdown",
"A description for the task. This value may contain some markdown-formatted text and hyperlinks.": "Uma descrição para a tarefa. Esse valor pode conter alguns textos formatados em markdown-hyperlinks.",
"The task's labels (a list of names that may represent either personal or shared labels)": "As etiquetas das tarefas (uma lista de nomes que podem representar rótulos pessoais ou compartilhados)",
"Task priority from 1 (normal) to 4 (urgent)": "Prioridade da tarefa de 1 (normal) para 4 (urgente)",
"Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time": "Pode ser uma data específica em formato YYYY-MM-DD relativo ao fuso horário do usuário. uma data e hora específicas no formato RFC3339, ou uma data definida por humanos (e. . 'na próxima segunda') usando a hora local",
"The name of the task to search for.": "O nome da tarefa a procurar.",
"Search for tasks within the selected project. If left blank, then all projects are searched.": "Pesquisar por tarefas dentro do projeto selecionado. Se deixado em branco, então todos os projetos são pesquisados.",
"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..",
"GET": "OBTER",
"POST": "POSTAR",
"PATCH": "COMPRAR",
"PUT": "COLOCAR",
"DELETE": "EXCLUIR",
"HEAD": "CABEÇA",
"Task Completed": "Tarefa concluída",
"Triggers when a new task is completed": "Dispara quando uma nova tarefa for concluída",
"Leave it blank if you want to get completed tasks from all your projects.": "Deixe em branco se você quiser obter tarefas concluídas de todos os seus projetos."
}

View File

@@ -0,0 +1,47 @@
{
"Todoist": "Todoist",
"To-do list and task manager": "Список задач и диспетчер задач",
"Create Task": "Создать задачу",
"Update Task": "Обновить задачу",
"Find Task": "Найти задачу",
"Mark Task as Completed": "Пометить задачу как выполненную",
"Custom API Call": "Пользовательский вызов API",
"Create task": "Создать задачу",
"Updates an existing task.": "Обновляет существующую задачу.",
"Finds a task by name.": "Находит задание по имени.",
"Marks a task as being completed.": "Отмечает выполняемую задачу.",
"Make a custom API call to a specific endpoint": "Сделать пользовательский API вызов к определенной конечной точке",
"Project": "Проект",
"content": "контент",
"Description": "Описание",
"Labels": "Метки",
"Priority": "Приоритет",
"Due date": "Срок сдачи",
"Section": "1 С-4, 1 С-3, 1 ПС, 1 НС, 1 ДООН",
"Task ID": "Task ID",
"Name": "Наименование",
"Method": "Метод",
"Headers": "Заголовки",
"Query Parameters": "Параметры запроса",
"Body": "Тело",
"No Error on Failure": "Нет ошибок при ошибке",
"Timeout (in seconds)": "Таймаут (в секундах)",
"Task project ID. If not set, task is put to user's Inbox.": "ID проекта задания. Если не установлен, задача помещается во Вплывающие окна пользователя.",
"The task's content. It may contain some markdown-formatted text and hyperlinks": "Содержимое задачи. Может содержать текст и гиперссылки в формате markdown-формата",
"A description for the task. This value may contain some markdown-formatted text and hyperlinks.": "Описание задачи. Это значение может содержать текст и гиперссылки в формате markdown.",
"The task's labels (a list of names that may represent either personal or shared labels)": "Метки задачи (список имен, которые могут представлять либо персональные, либо общие метки)",
"Task priority from 1 (normal) to 4 (urgent)": "Приоритет задачи от 1 (нормальный) до 4 (срочный)",
"Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time": "Может быть определенной датой в формате YYYY-MM-DD относительно часового пояса пользователя, определенная дата и время в формате RFC3339 или определенная человеком дата (e. . 'следующий понедельник') с использованием локального времени",
"The name of the task to search for.": "Название задачи для поиска.",
"Search for tasks within the selected project. If left blank, then all projects are searched.": "Поиск задач в выбранном проекте. Если оставить пустым, то все проекты ищутся.",
"Authorization headers are injected automatically from your connection.": "Заголовки авторизации включаются автоматически из вашего соединения.",
"GET": "ПОЛУЧИТЬ",
"POST": "ПОСТ",
"PATCH": "ПАТЧ",
"PUT": "ПОКУПИТЬ",
"DELETE": "УДАЛИТЬ",
"HEAD": "HEAD",
"Task Completed": "Задача выполнена",
"Triggers when a new task is completed": "Срабатывает при выполнении новой задачи",
"Leave it blank if you want to get completed tasks from all your projects.": "Оставьте это пустым, если вы хотите получить завершенные задачи из всех ваших проектов."
}

View File

@@ -0,0 +1,48 @@
{
"To-do list and task manager": "To-do list and task manager",
"Create Task": "Create Task",
"Update Task": "Update Task",
"Find Task": "Find Task",
"Mark Task as Completed": "Mark Task as Completed",
"Custom API Call": "Custom API Call",
"Create task": "Create task",
"Updates an existing task.": "Updates an existing task.",
"Finds a task by name.": "Finds a task by name.",
"Marks a task as being completed.": "Marks a task as being completed.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Project": "Project",
"content": "content",
"Description": "Description",
"Labels": "Labels",
"Priority": "Priority",
"Due date": "Due date",
"Section": "Section",
"Task ID": "Task ID",
"Name": "Name",
"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)",
"Task project ID. If not set, task is put to user's Inbox.": "Task project ID. If not set, task is put to user's Inbox.",
"The task's content. It may contain some markdown-formatted text and hyperlinks": "The task's content. It may contain some markdown-formatted text and hyperlinks",
"A description for the task. This value may contain some markdown-formatted text and hyperlinks.": "A description for the task. This value may contain some markdown-formatted text and hyperlinks.",
"The task's labels (a list of names that may represent either personal or shared labels)": "The task's labels (a list of names that may represent either personal or shared labels)",
"Task priority from 1 (normal) to 4 (urgent)": "Task priority from 1 (normal) to 4 (urgent)",
"Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time": "Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time",
"The name of the task to search for.": "The name of the task to search for.",
"Search for tasks within the selected project. If left blank, then all projects are searched.": "Search for tasks within the selected project. If left blank, then all projects are searched.",
"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..",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"Task Completed": "Task Completed",
"Triggers when a new task is completed": "Triggers when a new task is completed",
"Leave it blank if you want to get completed tasks from all your projects.": "Leave it blank if you want to get completed tasks from all your projects."
}

View File

@@ -0,0 +1,47 @@
{
"Todoist": "Todoist",
"To-do list and task manager": "To-do list and task manager",
"Create Task": "Create Task",
"Update Task": "Update Task",
"Find Task": "Find Task",
"Mark Task as Completed": "Mark Task as Completed",
"Custom API Call": "Custom API Call",
"Create task": "Create task",
"Updates an existing task.": "Updates an existing task.",
"Finds a task by name.": "Finds a task by name.",
"Marks a task as being completed.": "Marks a task as being completed.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Project": "Project",
"content": "content",
"Description": "Description",
"Labels": "Labels",
"Priority": "Priority",
"Due date": "Due date",
"Section": "Section",
"Task ID": "Task ID",
"Name": "Name",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Task project ID. If not set, task is put to user's Inbox.": "Task project ID. If not set, task is put to user's Inbox.",
"The task's content. It may contain some markdown-formatted text and hyperlinks": "The task's content. It may contain some markdown-formatted text and hyperlinks",
"A description for the task. This value may contain some markdown-formatted text and hyperlinks.": "A description for the task. This value may contain some markdown-formatted text and hyperlinks.",
"The task's labels (a list of names that may represent either personal or shared labels)": "The task's labels (a list of names that may represent either personal or shared labels)",
"Task priority from 1 (normal) to 4 (urgent)": "Task priority from 1 (normal) to 4 (urgent)",
"Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time": "Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time",
"The name of the task to search for.": "The name of the task to search for.",
"Search for tasks within the selected project. If left blank, then all projects are searched.": "Search for tasks within the selected project. If left blank, then all projects are searched.",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"Task Completed": "Task Completed",
"Triggers when a new task is completed": "Triggers when a new task is completed",
"Leave it blank if you want to get completed tasks from all your projects.": "Leave it blank if you want to get completed tasks from all your projects."
}

View File

@@ -0,0 +1,48 @@
{
"To-do list and task manager": "To-do list and task manager",
"Create Task": "Create Task",
"Update Task": "Update Task",
"Find Task": "Find Task",
"Mark Task as Completed": "Mark Task as Completed",
"Custom API Call": "自定义 API 呼叫",
"Create task": "Create task",
"Updates an existing task.": "Updates an existing task.",
"Finds a task by name.": "Finds a task by name.",
"Marks a task as being completed.": "Marks a task as being completed.",
"Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
"Project": "项目",
"content": "content",
"Description": "描述",
"Labels": "Labels",
"Priority": "Priority",
"Due date": "Due date",
"Section": "Section",
"Task ID": "Task ID",
"Name": "名称",
"Method": "方法",
"Headers": "信头",
"Query Parameters": "查询参数",
"Body": "正文内容",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "失败时没有错误",
"Timeout (in seconds)": "超时(秒)",
"Task project ID. If not set, task is put to user's Inbox.": "Task project ID. If not set, task is put to user's Inbox.",
"The task's content. It may contain some markdown-formatted text and hyperlinks": "The task's content. It may contain some markdown-formatted text and hyperlinks",
"A description for the task. This value may contain some markdown-formatted text and hyperlinks.": "A description for the task. This value may contain some markdown-formatted text and hyperlinks.",
"The task's labels (a list of names that may represent either personal or shared labels)": "The task's labels (a list of names that may represent either personal or shared labels)",
"Task priority from 1 (normal) to 4 (urgent)": "Task priority from 1 (normal) to 4 (urgent)",
"Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time": "Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time",
"The name of the task to search for.": "The name of the task to search for.",
"Search for tasks within the selected project. If left blank, then all projects are searched.": "Search for tasks within the selected project. If left blank, then all projects are searched.",
"Authorization headers are injected automatically from your connection.": "授权头自动从您的连接中注入。",
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
"GET": "获取",
"POST": "帖子",
"PATCH": "PATCH",
"PUT": "弹出",
"DELETE": "删除",
"HEAD": "黑色",
"Task Completed": "Task Completed",
"Triggers when a new task is completed": "Triggers when a new task is completed",
"Leave it blank if you want to get completed tasks from all your projects.": "Leave it blank if you want to get completed tasks from all your projects."
}

View File

@@ -0,0 +1,39 @@
import { createCustomApiCallAction } from '@activepieces/pieces-common';
import { OAuth2PropertyValue, PieceAuth, createPiece } from '@activepieces/pieces-framework';
import { PieceCategory } from '@activepieces/shared';
import { todoistCreateTaskAction } from './lib/actions/create-task-action';
import { todoistTaskCompletedTrigger } from './lib/triggers/task-completed-trigger';
import { todoistUpdateTaskAction } from './lib/actions/update-task.action';
import { todoistFindTaskAction } from './lib/actions/find-task.action';
import { todoistMarkTaskCompletedAction } from './lib/actions/mark-task-completed.action';
export const todoistAuth = PieceAuth.OAuth2({
required: true,
authUrl: 'https://todoist.com/oauth/authorize',
tokenUrl: 'https://todoist.com/oauth/access_token',
scope: ['data:read_write'],
});
export const todoist = createPiece({
displayName: 'Todoist',
description: 'To-do list and task manager',
minimumSupportedRelease: '0.5.0',
logoUrl: 'https://cdn.activepieces.com/pieces/todoist.png',
authors: ['MyWay', 'kishanprmr', 'MoShizzle', 'khaledmashaly', 'abuaboud'],
categories: [PieceCategory.PRODUCTIVITY],
auth: todoistAuth,
actions: [
todoistCreateTaskAction,
todoistUpdateTaskAction,
todoistFindTaskAction,
todoistMarkTaskCompletedAction,
createCustomApiCallAction({
baseUrl: () => 'https://api.todoist.com/rest/v2',
auth: todoistAuth,
authMapping: async (auth) => ({
Authorization: `Bearer ${auth.access_token}`,
}),
}),
],
triggers: [todoistTaskCompletedTrigger],
});

View File

@@ -0,0 +1,77 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { assertNotNullOrUndefined } from '@activepieces/shared';
import { todoistRestClient } from '../common/client/rest-client';
import {
todoistProjectIdDropdown,
todoistSectionIdDropdown,
} from '../common/props';
import { TodoistCreateTaskRequest } from '../common/models';
import { todoistAuth } from '../..';
export const todoistCreateTaskAction = createAction({
auth: todoistAuth,
name: 'create_task',
displayName: 'Create Task',
description: 'Create task',
props: {
project_id: todoistProjectIdDropdown(
"Task project ID. If not set, task is put to user's Inbox."
),
content: Property.LongText({
displayName: 'content',
description:
"The task's content. It may contain some markdown-formatted text and hyperlinks",
required: true,
}),
description: Property.LongText({
displayName: 'Description',
description:
'A description for the task. This value may contain some markdown-formatted text and hyperlinks.',
required: false,
}),
labels: Property.Array({
displayName: 'Labels',
required: false,
description:
"The task's labels (a list of names that may represent either personal or shared labels)",
}),
priority: Property.Number({
displayName: 'Priority',
description: 'Task priority from 1 (normal) to 4 (urgent)',
required: false,
}),
due_date: Property.ShortText({
displayName: 'Due date',
description:
"Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time",
required: false,
}),
section_id: todoistSectionIdDropdown,
},
async run({ auth, propsValue }) {
const token = auth.access_token;
const {
project_id,
content,
description,
labels,
priority,
due_date,
section_id,
} = propsValue as TodoistCreateTaskRequest;
assertNotNullOrUndefined(token, 'token');
assertNotNullOrUndefined(content, 'content');
return await todoistRestClient.tasks.create({
token,
project_id,
content,
description,
labels,
priority,
due_date,
section_id,
});
},
});

View File

@@ -0,0 +1,36 @@
import { todoistAuth } from '../..';
import { createAction, Property } from '@activepieces/pieces-framework';
import { todoistProjectIdDropdown } from '../common/props';
import { todoistRestClient } from '../common/client/rest-client';
import { assertNotNullOrUndefined } from '@activepieces/shared';
export const todoistFindTaskAction = createAction({
auth: todoistAuth,
name: 'find_task',
displayName: 'Find Task',
description: 'Finds a task by name.',
props: {
name: Property.ShortText({
displayName: 'Name',
description: 'The name of the task to search for.',
required: true,
}),
project_id: todoistProjectIdDropdown(
'Search for tasks within the selected project. If left blank, then all projects are searched.',
),
},
async run(context) {
const token = context.auth.access_token;
const { name, project_id } = context.propsValue;
assertNotNullOrUndefined(token, 'token');
const tasks = await todoistRestClient.tasks.list({ token, project_id });
const matchedTask = tasks.find((task) => task.content == name);
if (!matchedTask) {
throw new Error('Task not found');
} else {
return matchedTask;
}
},
});

View File

@@ -0,0 +1,25 @@
import { assertNotNullOrUndefined } from '@activepieces/shared';
import { todoistAuth } from '../..';
import { createAction, Property } from '@activepieces/pieces-framework';
import { todoistRestClient } from '../common/client/rest-client';
export const todoistMarkTaskCompletedAction = createAction({
auth: todoistAuth,
name: 'mark_task_completed',
displayName: 'Mark Task as Completed',
description: 'Marks a task as being completed.',
props: {
task_id: Property.ShortText({
displayName: 'Task ID',
required: true,
}),
},
async run(context) {
const token = context.auth.access_token;
const { task_id } = context.propsValue;
assertNotNullOrUndefined(token, 'token');
return await todoistRestClient.tasks.close({ token, task_id });
},
});

View File

@@ -0,0 +1,63 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { assertNotNullOrUndefined } from '@activepieces/shared';
import { todoistRestClient } from '../common/client/rest-client';
import { todoistAuth } from '../..';
export const todoistUpdateTaskAction = createAction({
auth: todoistAuth,
name: 'update_task',
displayName: 'Update Task',
description: 'Updates an existing task.',
props: {
task_id: Property.ShortText({
displayName: 'Task ID',
required: true,
}),
content: Property.LongText({
displayName: 'content',
description:
"The task's content. It may contain some markdown-formatted text and hyperlinks",
required: false,
}),
description: Property.LongText({
displayName: 'Description',
description:
'A description for the task. This value may contain some markdown-formatted text and hyperlinks.',
required: false,
}),
labels: Property.Array({
displayName: 'Labels',
required: false,
description:
"The task's labels (a list of names that may represent either personal or shared labels)",
}),
priority: Property.Number({
displayName: 'Priority',
description: 'Task priority from 1 (normal) to 4 (urgent)',
required: false,
}),
due_date: Property.ShortText({
displayName: 'Due date',
description:
"Can be either a specific date in YYYY-MM-DD format relative to user's timezone, a specific date and time in RFC3339 format, or a human defined date (e.g. 'next Monday') using local time",
required: false,
}),
},
async run({ auth, propsValue }) {
const token = auth.access_token;
const { task_id, content, description, priority, due_date } = propsValue;
const labels = propsValue.labels as string[];
assertNotNullOrUndefined(token, 'token');
return await todoistRestClient.tasks.update({
token,
task_id,
content,
description,
labels,
priority,
due_date,
});
},
});

View File

@@ -0,0 +1,189 @@
import {
HttpRequest,
HttpMethod,
AuthenticationType,
httpClient,
} from '@activepieces/pieces-common';
import { isNotUndefined, pickBy } from '@activepieces/shared';
import {
TodoistCreateTaskRequest,
TodoistProject,
TodoistSection,
TodoistTask,
TodoistUpdateTaskRequest,
} from '../models';
const API = 'https://api.todoist.com/rest/v2';
export const todoistRestClient = {
projects: {
async list({ token }: ProjectsListParams): Promise<TodoistProject[]> {
const request: HttpRequest = {
method: HttpMethod.GET,
url: `${API}/projects`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token,
},
};
const response = await httpClient.sendRequest<TodoistProject[]>(request);
return response.body;
},
},
sections: {
async list(params: SectionsListPrams): Promise<TodoistSection[]> {
const qs: Record<string, any> = {};
if (params.project_id) qs['project_id'] = params.project_id;
const request: HttpRequest = {
method: HttpMethod.GET,
url: `${API}/sections`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: params.token,
},
queryParams: qs,
};
const response = await httpClient.sendRequest<TodoistSection[]>(request);
return response.body;
},
},
tasks: {
async create({
token,
project_id,
content,
description,
labels,
priority,
due_date,
section_id,
}: TasksCreateParams): Promise<TodoistTask> {
const body: TodoistCreateTaskRequest = {
content,
project_id,
description,
labels,
priority,
section_id,
...dueDateParams(due_date),
};
const request: HttpRequest<TodoistCreateTaskRequest> = {
method: HttpMethod.POST,
url: `${API}/tasks`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token,
},
body,
};
const response = await httpClient.sendRequest<TodoistTask>(request);
return response.body;
},
async update(params: TasksUpdateParams): Promise<TodoistTask> {
const body: TodoistUpdateTaskRequest = {
content: params.content,
description: params.description,
labels: params.labels?.length === 0 ? undefined : params.labels,
priority: params.priority,
...dueDateParams(params.due_date),
};
const request: HttpRequest<TodoistUpdateTaskRequest> = {
method: HttpMethod.POST,
url: `${API}/tasks/${params.task_id}`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: params.token,
},
body,
};
const response = await httpClient.sendRequest<TodoistTask>(request);
return response.body;
},
async list({
token,
project_id,
filter,
}: TasksListParams): Promise<TodoistTask[]> {
const queryParams = {
filter,
project_id,
};
const request: HttpRequest = {
method: HttpMethod.GET,
url: `${API}/tasks`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token,
},
queryParams: pickBy(queryParams, isNotUndefined),
};
const response = await httpClient.sendRequest<TodoistTask[]>(request);
return response.body;
},
async close({ token, task_id }: { token: string; task_id: string }) {
const request: HttpRequest = {
method: HttpMethod.POST,
url: `${API}/tasks/${task_id}/close`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token,
},
};
const response = await httpClient.sendRequest(request);
return response.body;
},
},
};
type ProjectsListParams = {
token: string;
};
type SectionsListPrams = {
token: string;
project_id?: string;
};
type TasksCreateParams = {
token: string;
} & TodoistCreateTaskRequest;
type TasksUpdateParams = {
token: string;
task_id: string;
} & TodoistUpdateTaskRequest;
type TasksListParams = {
token: string;
project_id?: string | undefined;
filter?: string | undefined;
};
const dueDateParams = (dueDate?: string) => {
if (dueDate) {
const parsedDate = Date.parse(dueDate);
if (isNaN(parsedDate)) {
return { due_string: dueDate };
} else if (/\d{4}-\d{2}-\d{2}/.test(dueDate)) {
return { due_date: dueDate };
} else {
return { due_datetime: new Date(parsedDate).toISOString() };
}
}
return {};
};

View File

@@ -0,0 +1,49 @@
import {
AuthenticationType,
httpClient,
HttpMethod,
HttpRequest,
} from '@activepieces/pieces-common';
import { isNotUndefined, pickBy } from '@activepieces/shared';
import { TodoistCompletedListResponse } from '../models';
const API = 'https://api.todoist.com/sync/v9';
export const todoistSyncClient = {
completed: {
async list({
token,
since,
project_id,
until,
}: CompletedListParams): Promise<TodoistCompletedListResponse> {
const queryParams = {
limit: '200',
since,
until,
project_id,
};
const request: HttpRequest = {
method: HttpMethod.GET,
url: `${API}/completed/get_all`,
queryParams: pickBy(queryParams, isNotUndefined),
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token,
},
};
const response =
await httpClient.sendRequest<TodoistCompletedListResponse>(request);
return response.body;
},
},
};
type CompletedListParams = {
token: string;
since: string;
until: string;
project_id: string | undefined;
};

View File

@@ -0,0 +1,76 @@
export type TodoistProject = {
id: string;
name: string;
};
export type TodoistSection = {
id: string;
name: string;
project_id: string;
order: number;
};
export type TodoistCreateTaskRequest = {
content: string;
project_id?: string | undefined;
description?: string | undefined;
labels?: Array<string> | undefined;
priority?: number | undefined;
due_date?: string | undefined;
due_string?: string | undefined;
due_datetime?: string | undefined;
section_id?: string | undefined;
};
export type TodoistUpdateTaskRequest = {
content?: string;
description?: string;
labels?: Array<string>;
priority?: number;
due_date?: string | undefined;
due_string?: string | undefined;
due_datetime?: string | undefined;
};
type TodoistTaskDue = {
string: string;
date: string;
is_recurring: boolean;
datetime?: string | undefined;
timezone?: string | undefined;
};
export type TodoistTask = {
id: string;
projectId: string | null;
sectionId: string | null;
content: string;
description?: string | undefined;
is_completed: boolean;
labels: string[];
parent_id: string | null;
order: number;
priority: number;
due: TodoistTaskDue | null;
url: string;
comment_count: number;
created_at: string;
creator_id: string;
assignee_id: string | null;
assigner_id: string | null;
};
export type TodoistCompletedTask = {
id: string;
task_id: string;
user_id: string;
project_id: string;
section_id: string;
content: string;
completed_at: string;
note_count: number;
};
export type TodoistCompletedListResponse = {
items: TodoistCompletedTask[];
};

View File

@@ -0,0 +1,80 @@
import { OAuth2PropertyValue, Property } from '@activepieces/pieces-framework';
import { todoistRestClient } from './client/rest-client';
import { todoistAuth } from '../..';
const buildEmptyList = ({ placeholder }: { placeholder: string }) => {
return {
disabled: true,
options: [],
placeholder,
};
};
export const todoistProjectIdDropdown = (description: string) =>
Property.Dropdown<string,false,typeof todoistAuth>({
auth: todoistAuth,
displayName: 'Project',
refreshers: [],
description,
required: false,
options: async ({ auth }) => {
if (!auth) {
return buildEmptyList({
placeholder: 'Please select an authentication',
});
}
const token = (auth as OAuth2PropertyValue).access_token;
const projects = await todoistRestClient.projects.list({ token });
if (projects.length === 0) {
return buildEmptyList({
placeholder: 'No projects found! Please create a project.',
});
}
const options = projects.map((p) => ({
label: p.name,
value: p.id,
}));
return {
disabled: false,
options,
};
},
});
export const todoistSectionIdDropdown = Property.Dropdown({
auth: todoistAuth,
displayName: 'Section',
refreshers: ['project_id'],
required: false,
options: async ({ auth, project_id }) => {
if (!auth) {
return buildEmptyList({
placeholder: 'Please select an authentication',
});
}
const token = (auth as OAuth2PropertyValue).access_token;
const projectId = project_id as string | undefined;
const sections = await todoistRestClient.sections.list({ token, project_id: projectId });
if (sections.length === 0) {
return buildEmptyList({
placeholder: 'No sections found! Please create a section.',
});
}
const options = sections.map((p) => ({
label: p.name,
value: p.id,
}));
return {
disabled: false,
options,
};
},
});

View File

@@ -0,0 +1,119 @@
import {
AppConnectionValueForAuthProperty,
createTrigger,
PiecePropValueSchema,
TriggerStrategy,
} from '@activepieces/pieces-framework';
import dayjs from 'dayjs';
import { TodoistCompletedListResponse, TodoistCompletedTask } from '../common/models';
import { todoistProjectIdDropdown } from '../common/props';
import { todoistAuth } from '../..';
import {
AuthenticationType,
DedupeStrategy,
httpClient,
HttpMethod,
Polling,
pollingHelper,
QueryParams,
} from '@activepieces/pieces-common';
const ISO_FORMAT = 'YYYY-MM-DDTHH:mm:ss';
const polling: Polling<AppConnectionValueForAuthProperty<typeof todoistAuth>, { project_id?: string }> = {
strategy: DedupeStrategy.TIMEBASED,
async items({ auth, propsValue, lastFetchEpochMS }) {
const lastUpdatedTime =
lastFetchEpochMS === 0
? dayjs().subtract(5, 'minutes').format(ISO_FORMAT)
: dayjs(lastFetchEpochMS).format(ISO_FORMAT);
const tasks: TodoistCompletedTask[] = [];
let hasMore = true;
let offset = 0;
const limit = 200;
do {
const qs: QueryParams = {
limit: limit.toString(),
offset: offset.toString(),
since: lastUpdatedTime,
};
if (propsValue.project_id) {
qs.project_id = propsValue.project_id;
}
const response = await httpClient.sendRequest<TodoistCompletedListResponse>({
method: HttpMethod.GET,
url: 'https://api.todoist.com/sync/v9/completed/get_all',
queryParams: qs,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: auth.access_token,
},
});
if (response.body.items.length > 0) {
tasks.push(...response.body.items);
offset += limit;
} else {
hasMore = false;
}
} while (hasMore);
return tasks.map((task) => {
return {
epochMilliSeconds: dayjs(task.completed_at).valueOf(),
data: task,
};
});
},
};
export const todoistTaskCompletedTrigger = createTrigger({
auth: todoistAuth,
name: 'task_completed',
displayName: 'Task Completed',
description: 'Triggers when a new task is completed',
type: TriggerStrategy.POLLING,
props: {
project_id: todoistProjectIdDropdown(
'Leave it blank if you want to get completed tasks from all your projects.',
),
},
async onEnable(context) {
await pollingHelper.onEnable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async onDisable(context) {
await pollingHelper.onDisable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async test(context) {
return await pollingHelper.test(polling, context);
},
async run(context) {
return await pollingHelper.poll(polling, context);
},
sampleData: {
content: 'Buy Milk',
meta_data: null,
user_id: '2671355',
task_id: '2995104339',
note_count: 0,
project_id: '2203306141',
section_id: '7025',
completed_at: '2015-02-17T15:40:41.000000Z',
id: '1899066186',
},
});

View File

@@ -0,0 +1,16 @@
{
"extends": "../../../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
],
"compilerOptions": {
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
}
}

View File

@@ -0,0 +1,11 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "../../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
"include": ["src/**/*.ts"]
}