diff --git a/packages/backend/src/apps/google-tasks/actions/create-task-list/index.js b/packages/backend/src/apps/google-tasks/actions/create-task-list/index.js
new file mode 100644
index 00000000..0d2571bd
--- /dev/null
+++ b/packages/backend/src/apps/google-tasks/actions/create-task-list/index.js
@@ -0,0 +1,31 @@
+import defineAction from '../../../../helpers/define-action.js';
+
+export default defineAction({
+ name: 'Create task list',
+ key: 'createTaskList',
+ description: 'Creates a new task list.',
+ arguments: [
+ {
+ label: 'List Title',
+ key: 'listTitle',
+ type: 'string',
+ required: true,
+ description: '',
+ variables: true,
+ },
+ ],
+
+ async run($) {
+ const listTitle = $.step.parameters.listTitle;
+
+ const body = {
+ title: listTitle,
+ };
+
+ const { data } = await $.http.post('/tasks/v1/users/@me/lists', body);
+
+ $.setActionItem({
+ raw: data,
+ });
+ },
+});
diff --git a/packages/backend/src/apps/google-tasks/actions/create-task/index.js b/packages/backend/src/apps/google-tasks/actions/create-task/index.js
new file mode 100644
index 00000000..2b03a20e
--- /dev/null
+++ b/packages/backend/src/apps/google-tasks/actions/create-task/index.js
@@ -0,0 +1,70 @@
+import defineAction from '../../../../helpers/define-action.js';
+
+export default defineAction({
+ name: 'Create task',
+ key: 'createTask',
+ description: 'Creates a new task.',
+ arguments: [
+ {
+ label: 'Task List',
+ key: 'taskListId',
+ type: 'dropdown',
+ required: true,
+ description: '',
+ variables: true,
+ source: {
+ type: 'query',
+ name: 'getDynamicData',
+ arguments: [
+ {
+ name: 'key',
+ value: 'listTaskLists',
+ },
+ ],
+ },
+ },
+ {
+ label: 'Title',
+ key: 'title',
+ type: 'string',
+ required: true,
+ description: '',
+ variables: true,
+ },
+ {
+ label: 'Notes',
+ key: 'notes',
+ type: 'string',
+ required: false,
+ description: '',
+ variables: true,
+ },
+ {
+ label: 'Due Date',
+ key: 'due',
+ type: 'string',
+ required: false,
+ description: 'RFC 3339 timestamp.',
+ variables: true,
+ },
+ ],
+
+ async run($) {
+ const { taskListId, title, notes, due } = $.step.parameters;
+
+ const body = {
+ title,
+ notes,
+ due,
+ };
+
+ const { data } = await $.http.post(
+ `/tasks/v1/lists/${taskListId}/tasks`,
+ body
+ );
+
+ $.setActionItem({
+ raw: data,
+ });
+ },
+});
diff --git a/packages/backend/src/apps/google-tasks/actions/find-task/index.js b/packages/backend/src/apps/google-tasks/actions/find-task/index.js
new file mode 100644
index 00000000..d7e8e2a6
--- /dev/null
+++ b/packages/backend/src/apps/google-tasks/actions/find-task/index.js
@@ -0,0 +1,50 @@
+import defineAction from '../../../../helpers/define-action.js';
+
+export default defineAction({
+ name: 'Find task',
+ key: 'findTask',
+ description: 'Looking for an incomplete task.',
+ arguments: [
+ {
+ label: 'Task List',
+ key: 'taskListId',
+ type: 'dropdown',
+ required: true,
+ description: 'The list to be searched.',
+ variables: true,
+ source: {
+ type: 'query',
+ name: 'getDynamicData',
+ arguments: [
+ {
+ name: 'key',
+ value: 'listTaskLists',
+ },
+ ],
+ },
+ },
+ {
+ label: 'Title',
+ key: 'title',
+ type: 'string',
+ required: true,
+ description: '',
+ variables: true,
+ },
+ ],
+
+ async run($) {
+ const taskListId = $.step.parameters.taskListId;
+ const title = $.step.parameters.title;
+
+ const { data } = await $.http.get(`/tasks/v1/lists/${taskListId}/tasks`);
+
+ const filteredTask = data.items?.filter((task) =>
+ task.title.includes(title)
+ );
+
+ $.setActionItem({
+ raw: filteredTask[0],
+ });
+ },
+});
diff --git a/packages/backend/src/apps/google-tasks/actions/index.js b/packages/backend/src/apps/google-tasks/actions/index.js
new file mode 100644
index 00000000..ed71df70
--- /dev/null
+++ b/packages/backend/src/apps/google-tasks/actions/index.js
@@ -0,0 +1,6 @@
+import createTask from './create-task/index.js';
+import createTaskList from './create-task-list/index.js';
+import findTask from './find-task/index.js';
+import updateTask from './update-task/index.js';
+
+export default [createTask, createTaskList, findTask, updateTask];
diff --git a/packages/backend/src/apps/google-tasks/actions/update-task/index.js b/packages/backend/src/apps/google-tasks/actions/update-task/index.js
new file mode 100644
index 00000000..e38aefaf
--- /dev/null
+++ b/packages/backend/src/apps/google-tasks/actions/update-task/index.js
@@ -0,0 +1,108 @@
+import defineAction from '../../../../helpers/define-action.js';
+
+export default defineAction({
+ name: 'Update task',
+ key: 'updateTask',
+ description: 'Updates an existing task.',
+ arguments: [
+ {
+ label: 'Task List',
+ key: 'taskListId',
+ type: 'dropdown',
+ required: true,
+ description: '',
+ variables: true,
+ source: {
+ type: 'query',
+ name: 'getDynamicData',
+ arguments: [
+ {
+ name: 'key',
+ value: 'listTaskLists',
+ },
+ ],
+ },
+ },
+ {
+ label: 'Task',
+ key: 'taskId',
+ type: 'dropdown',
+ required: true,
+ description: 'Ensure that you choose a list before proceeding.',
+ variables: true,
+ dependsOn: ['parameters.taskListId'],
+ source: {
+ type: 'query',
+ name: 'getDynamicData',
+ arguments: [
+ {
+ name: 'key',
+ value: 'listTasks',
+ },
+ {
+ name: 'parameters.taskListId',
+ value: '{parameters.taskListId}',
+ },
+ ],
+ },
+ },
+ {
+ label: 'Title',
+ key: 'title',
+ type: 'string',
+ required: false,
+ description: 'Provide a new title for the revised task.',
+ variables: true,
+ },
+ {
+ label: 'Status',
+ key: 'status',
+ type: 'dropdown',
+ required: false,
+ description:
+ 'Specify the status of the updated task. If you opt for a custom value, enter either "needsAttention" or "completed."',
+ variables: true,
+ options: [
+ { label: 'Incomplete', value: 'needsAction' },
+ { label: 'Complete', value: 'completed' },
+ ],
+ },
+ {
+ label: 'Notes',
+ key: 'notes',
+ type: 'string',
+ required: false,
+ description: 'Provide a note for the revised task.',
+ variables: true,
+ },
+ {
+ label: 'Due Date',
+ key: 'due',
+ type: 'string',
+ required: false,
+ description:
+ 'Specify the deadline for the task (as a RFC 3339 timestamp).',
+ variables: true,
+ },
+ ],
+
+ async run($) {
+ const { taskListId, taskId, title, status, notes, due } = $.step.parameters;
+
+ const body = {
+ title,
+ status,
+ notes,
+ due,
+ };
+
+ const { data } = await $.http.patch(
+ `/tasks/v1/lists/${taskListId}/tasks/${taskId}`,
+ body
+ );
+
+ $.setActionItem({
+ raw: data,
+ });
+ },
+});
diff --git a/packages/backend/src/apps/google-tasks/dynamic-data/index.js b/packages/backend/src/apps/google-tasks/dynamic-data/index.js
new file mode 100644
index 00000000..71940ffd
--- /dev/null
+++ b/packages/backend/src/apps/google-tasks/dynamic-data/index.js
@@ -0,0 +1,4 @@
+import listTaskLists from './list-task-lists/index.js';
+import listTasks from './list-tasks/index.js';
+
+export default [listTaskLists, listTasks];
diff --git a/packages/backend/src/apps/google-tasks/dynamic-data/list-task-lists/index.js b/packages/backend/src/apps/google-tasks/dynamic-data/list-task-lists/index.js
new file mode 100644
index 00000000..a430a48e
--- /dev/null
+++ b/packages/backend/src/apps/google-tasks/dynamic-data/list-task-lists/index.js
@@ -0,0 +1,33 @@
+export default {
+ name: 'List task lists',
+ key: 'listTaskLists',
+
+ async run($) {
+ const taskLists = {
+ data: [],
+ };
+
+ const params = {
+ maxResults: 100,
+ pageToken: undefined,
+ };
+
+ do {
+ const { data } = await $.http.get('/tasks/v1/users/@me/lists', {
+ params,
+ });
+ params.pageToken = data.nextPageToken;
+
+ if (data.items) {
+ for (const taskList of data.items) {
+ taskLists.data.push({
+ value: taskList.id,
+ name: taskList.title,
+ });
+ }
+ }
+ } while (params.pageToken);
+
+ return taskLists;
+ },
+};
diff --git a/packages/backend/src/apps/google-tasks/dynamic-data/list-tasks/index.js b/packages/backend/src/apps/google-tasks/dynamic-data/list-tasks/index.js
new file mode 100644
index 00000000..534dbdbb
--- /dev/null
+++ b/packages/backend/src/apps/google-tasks/dynamic-data/list-tasks/index.js
@@ -0,0 +1,40 @@
+export default {
+ name: 'List tasks',
+ key: 'listTasks',
+
+ async run($) {
+ const tasks = {
+ data: [],
+ };
+ const taskListId = $.step.parameters.taskListId;
+
+ const params = {
+ maxResults: 100,
+ pageToken: undefined,
+ };
+
+ if (!taskListId) {
+ return tasks;
+ }
+
+ do {
+ const { data } = await $.http.get(`/tasks/v1/lists/${taskListId}/tasks`, {
+ params,
+ });
+ params.pageToken = data.nextPageToken;
+
+ if (data.items) {
+ for (const task of data.items) {
+ if (task.title !== '') {
+ tasks.data.push({
+ value: task.id,
+ name: task.title,
+ });
+ }
+ }
+ }
+ } while (params.pageToken);
+
+ return tasks;
+ },
+};
diff --git a/packages/backend/src/apps/google-tasks/index.js b/packages/backend/src/apps/google-tasks/index.js
index 9b23d099..6474f86e 100644
--- a/packages/backend/src/apps/google-tasks/index.js
+++ b/packages/backend/src/apps/google-tasks/index.js
@@ -1,6 +1,8 @@
import defineApp from '../../helpers/define-app.js';
import addAuthHeader from './common/add-auth-header.js';
import auth from './auth/index.js';
+import actions from './actions/index.js';
+import dynamicData from './dynamic-data/index.js';
export default defineApp({
name: 'Google Tasks',
@@ -13,4 +15,6 @@ export default defineApp({
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,
+ actions,
+ dynamicData,
});
diff --git a/packages/backend/src/apps/google-tasks/triggers/index.js b/packages/backend/src/apps/google-tasks/triggers/index.js
new file mode 100644
index 00000000..3677b97c
--- /dev/null
+++ b/packages/backend/src/apps/google-tasks/triggers/index.js
@@ -0,0 +1,5 @@
+import newCompletedTasks from './new-completed-tasks/index.js';
+import newTaskLists from './new-task-lists/index.js';
+import newTasks from './new-tasks/index.js';
+
+export default [newCompletedTasks, newTaskLists, newTasks];
diff --git a/packages/backend/src/apps/google-tasks/triggers/new-completed-tasks/index.js b/packages/backend/src/apps/google-tasks/triggers/new-completed-tasks/index.js
new file mode 100644
index 00000000..155d353b
--- /dev/null
+++ b/packages/backend/src/apps/google-tasks/triggers/new-completed-tasks/index.js
@@ -0,0 +1,59 @@
+import defineTrigger from '../../../../helpers/define-trigger.js';
+
+export default defineTrigger({
+ name: 'New completed tasks',
+ key: 'newTasks',
+ pollInterval: 15,
+ description: 'Triggers when a task is finished within a specified task list.',
+ arguments: [
+ {
+ label: 'Task List',
+ key: 'taskListId',
+ type: 'dropdown',
+ required: true,
+ description: '',
+ variables: true,
+ source: {
+ type: 'query',
+ name: 'getDynamicData',
+ arguments: [
+ {
+ name: 'key',
+ value: 'listTaskLists',
+ },
+ ],
+ },
+ },
+ ],
+
+ async run($) {
+ const taskListId = $.step.parameters.taskListId;
+
+ const params = {
+ maxResults: 100,
+ showCompleted: true,
+ showHidden: true,
+ pageToken: undefined,
+ };
+
+ do {
+ const { data } = await $.http.get(`/tasks/v1/lists/${taskListId}/tasks`, {
+ params,
+ });
+ params.pageToken = data.nextPageToken;
+
+ if (data.items?.length) {
+ for (const task of data.items) {
+ if (task.status === 'completed') {
+ $.pushTriggerItem({
+ raw: task,
+ meta: {
+ internalId: task.etag,
+ },
+ });
+ }
+ }
+ }
+ } while (params.pageToken);
+ },
+});
diff --git a/packages/backend/src/apps/google-tasks/triggers/new-task-lists/index.js b/packages/backend/src/apps/google-tasks/triggers/new-task-lists/index.js
new file mode 100644
index 00000000..3835f28f
--- /dev/null
+++ b/packages/backend/src/apps/google-tasks/triggers/new-task-lists/index.js
@@ -0,0 +1,31 @@
+import defineTrigger from '../../../../helpers/define-trigger.js';
+
+export default defineTrigger({
+ name: 'New task lists',
+ key: 'newTaskLists',
+ pollInterval: 15,
+ description: 'Triggers when a new task list is created.',
+
+ async run($) {
+ const params = {
+ maxResults: 100,
+ pageToken: undefined,
+ };
+
+ do {
+ const { data } = await $.http.get('/tasks/v1/users/@me/lists');
+ params.pageToken = data.nextPageToken;
+
+ if (data.items?.length) {
+ for (const taskList of data.items.reverse()) {
+ $.pushTriggerItem({
+ raw: taskList,
+ meta: {
+ internalId: taskList.etag,
+ },
+ });
+ }
+ }
+ } while (params.pageToken);
+ },
+});
diff --git a/packages/backend/src/apps/google-tasks/triggers/new-tasks/index.js b/packages/backend/src/apps/google-tasks/triggers/new-tasks/index.js
new file mode 100644
index 00000000..0b88b330
--- /dev/null
+++ b/packages/backend/src/apps/google-tasks/triggers/new-tasks/index.js
@@ -0,0 +1,53 @@
+import defineTrigger from '../../../../helpers/define-trigger.js';
+
+export default defineTrigger({
+ name: 'New tasks',
+ key: 'newTasks',
+ pollInterval: 15,
+ description: 'Triggers when a new task is created.',
+ arguments: [
+ {
+ label: 'Task List',
+ key: 'taskListId',
+ type: 'dropdown',
+ required: true,
+ description: '',
+ variables: true,
+ source: {
+ type: 'query',
+ name: 'getDynamicData',
+ arguments: [
+ {
+ name: 'key',
+ value: 'listTaskLists',
+ },
+ ],
+ },
+ },
+ ],
+
+ async run($) {
+ const taskListId = $.step.parameters.taskListId;
+
+ const params = {
+ maxResults: 100,
+ pageToken: undefined,
+ };
+
+ do {
+ const { data } = await $.http.get(`/tasks/v1/lists/${taskListId}/tasks`);
+ params.pageToken = data.nextPageToken;
+
+ if (data.items?.length) {
+ for (const task of data.items) {
+ $.pushTriggerItem({
+ raw: task,
+ meta: {
+ internalId: task.etag,
+ },
+ });
+ }
+ }
+ } while (params.pageToken);
+ },
+});
diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js
index 15dfc3fd..a37c1ddd 100644
--- a/packages/docs/pages/.vitepress/config.js
+++ b/packages/docs/pages/.vitepress/config.js
@@ -174,6 +174,8 @@ export default defineConfig({
collapsible: true,
collapsed: true,
items: [
+ { text: 'Triggers', link: '/apps/google-tasks/triggers' },
+ { text: 'Actions', link: '/apps/google-tasks/actions' },
{ text: 'Connection', link: '/apps/google-tasks/connection' },
],
},
diff --git a/packages/docs/pages/apps/google-tasks/actions.md b/packages/docs/pages/apps/google-tasks/actions.md
new file mode 100644
index 00000000..30446b0d
--- /dev/null
+++ b/packages/docs/pages/apps/google-tasks/actions.md
@@ -0,0 +1,18 @@
+---
+favicon: /favicons/google-tasks.svg
+items:
+ - name: Create task
+ desc: Creates a new task.
+ - name: Create task list
+ desc: Creates a new task list.
+ - name: Find task
+ desc: Looking for an incomplete task.
+ - name: Update task
+ desc: Updates an existing task.
+---
+
+
+
+
diff --git a/packages/docs/pages/apps/google-tasks/triggers.md b/packages/docs/pages/apps/google-tasks/triggers.md
new file mode 100644
index 00000000..3c6bf3b2
--- /dev/null
+++ b/packages/docs/pages/apps/google-tasks/triggers.md
@@ -0,0 +1,16 @@
+---
+favicon: /favicons/google-tasks.svg
+items:
+ - name: New completed tasks
+ desc: Triggers when a task is finished within a specified task list.
+ - name: New task lists
+ desc: Triggers when a new task list is created.
+ - name: New tasks
+ desc: Triggers when a new task is created.
+---
+
+
+
+
diff --git a/packages/docs/pages/guide/available-apps.md b/packages/docs/pages/guide/available-apps.md
index 90f8ba0a..75be1bcc 100644
--- a/packages/docs/pages/guide/available-apps.md
+++ b/packages/docs/pages/guide/available-apps.md
@@ -17,6 +17,7 @@ The following integrations are currently supported by Automatisch.
- [Google Drive](/apps/google-drive/triggers)
- [Google Forms](/apps/google-forms/triggers)
- [Google Sheets](/apps/google-sheets/triggers)
+- [Google Tasks](/apps/google-tasks/actions)
- [HTTP Request](/apps/http-request/actions)
- [HubSpot](/apps/hubspot/actions)
- [Invoice Ninja](/apps/invoice-ninja/triggers)