379 lines
17 KiB
Python
379 lines
17 KiB
Python
# Copyright (c) 2025 Patrick Motsch
|
||
# All rights reserved.
|
||
"""ClickUp workflow method — list/search/get/create/update tasks and upload attachments."""
|
||
|
||
import logging
|
||
|
||
from modules.datamodels.datamodelWorkflowActions import WorkflowActionDefinition, WorkflowActionParameter
|
||
from modules.shared.frontendTypes import FrontendType
|
||
from modules.workflows.methods.methodBase import MethodBase
|
||
|
||
from .helpers.connection import ClickupConnectionHelper
|
||
from .actions.list_tasks import list_tasks
|
||
from .actions.list_fields import list_fields
|
||
from .actions.search_tasks import search_tasks
|
||
from .actions.get_task import get_task
|
||
from .actions.create_task import create_task
|
||
from .actions.update_task import update_task
|
||
from .actions.upload_attachment import upload_attachment
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
class MethodClickup(MethodBase):
|
||
"""ClickUp API actions for automation2 (lists as tables)."""
|
||
|
||
def __init__(self, services):
|
||
super().__init__(services)
|
||
self.name = "clickup"
|
||
self.description = "ClickUp task and list operations"
|
||
self.connection = ClickupConnectionHelper(self)
|
||
|
||
self._actions = {
|
||
"listTasks": WorkflowActionDefinition(
|
||
actionId="clickup.listTasks",
|
||
description="List tasks in a ClickUp list (virtual path /team/{id}/list/{id})",
|
||
dynamicMode=True,
|
||
parameters={
|
||
"connectionReference": WorkflowActionParameter(
|
||
name="connectionReference",
|
||
type="str",
|
||
frontendType=FrontendType.USER_CONNECTION,
|
||
required=True,
|
||
description="ClickUp connection",
|
||
),
|
||
"pathQuery": WorkflowActionParameter(
|
||
name="pathQuery",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=True,
|
||
description="Virtual path to list: /team/{teamId}/list/{listId}",
|
||
),
|
||
"page": WorkflowActionParameter(
|
||
name="page",
|
||
type="int",
|
||
frontendType=FrontendType.NUMBER,
|
||
required=False,
|
||
default=0,
|
||
description="Page index",
|
||
),
|
||
"includeClosed": WorkflowActionParameter(
|
||
name="includeClosed",
|
||
type="bool",
|
||
frontendType=FrontendType.CHECKBOX,
|
||
required=False,
|
||
default=False,
|
||
description="Include closed tasks",
|
||
),
|
||
},
|
||
execute=list_tasks.__get__(self, self.__class__),
|
||
),
|
||
"listFields": WorkflowActionDefinition(
|
||
actionId="clickup.listFields",
|
||
description="List custom and built-in field definitions for a ClickUp list (names, types, ids)",
|
||
dynamicMode=True,
|
||
parameters={
|
||
"connectionReference": WorkflowActionParameter(
|
||
name="connectionReference",
|
||
type="str",
|
||
frontendType=FrontendType.USER_CONNECTION,
|
||
required=True,
|
||
description="ClickUp connection",
|
||
),
|
||
"listId": WorkflowActionParameter(
|
||
name="listId",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="ClickUp list ID (if set, pathQuery is optional)",
|
||
),
|
||
"pathQuery": WorkflowActionParameter(
|
||
name="pathQuery",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="Virtual path /team/{teamId}/list/{listId} (same as data source path)",
|
||
),
|
||
},
|
||
execute=list_fields.__get__(self, self.__class__),
|
||
),
|
||
"searchTasks": WorkflowActionDefinition(
|
||
actionId="clickup.searchTasks",
|
||
description="Search tasks in a ClickUp workspace (team)",
|
||
dynamicMode=True,
|
||
parameters={
|
||
"connectionReference": WorkflowActionParameter(
|
||
name="connectionReference",
|
||
type="str",
|
||
frontendType=FrontendType.USER_CONNECTION,
|
||
required=True,
|
||
description="ClickUp connection",
|
||
),
|
||
"teamId": WorkflowActionParameter(
|
||
name="teamId",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=True,
|
||
description="Workspace (team) ID",
|
||
),
|
||
"query": WorkflowActionParameter(
|
||
name="query",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=True,
|
||
description="Search query",
|
||
),
|
||
"page": WorkflowActionParameter(
|
||
name="page",
|
||
type="int",
|
||
frontendType=FrontendType.NUMBER,
|
||
required=False,
|
||
default=0,
|
||
description="Page index",
|
||
),
|
||
"listId": WorkflowActionParameter(
|
||
name="listId",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description=(
|
||
"If set, tasks are loaded from this list via the list API (not team search). "
|
||
"Use this to search the selected table."
|
||
),
|
||
),
|
||
"includeClosed": WorkflowActionParameter(
|
||
name="includeClosed",
|
||
type="bool",
|
||
frontendType=FrontendType.CHECKBOX,
|
||
required=False,
|
||
default=False,
|
||
description="When listId is set, include closed tasks in list pages.",
|
||
),
|
||
"fullTaskData": WorkflowActionParameter(
|
||
name="fullTaskData",
|
||
type="bool",
|
||
frontendType=FrontendType.CHECKBOX,
|
||
required=False,
|
||
default=False,
|
||
description="If true, return raw ClickUp API task objects (large). Default is a slim payload.",
|
||
),
|
||
"matchNameOnly": WorkflowActionParameter(
|
||
name="matchNameOnly",
|
||
type="bool",
|
||
frontendType=FrontendType.CHECKBOX,
|
||
required=False,
|
||
default=True,
|
||
description="If true, keep only tasks whose title contains the search query (default: true).",
|
||
),
|
||
},
|
||
execute=search_tasks.__get__(self, self.__class__),
|
||
),
|
||
"getTask": WorkflowActionDefinition(
|
||
actionId="clickup.getTask",
|
||
description="Get a single task by ID",
|
||
dynamicMode=True,
|
||
parameters={
|
||
"connectionReference": WorkflowActionParameter(
|
||
name="connectionReference",
|
||
type="str",
|
||
frontendType=FrontendType.USER_CONNECTION,
|
||
required=True,
|
||
description="ClickUp connection",
|
||
),
|
||
"taskId": WorkflowActionParameter(
|
||
name="taskId",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="Task ID",
|
||
),
|
||
"pathQuery": WorkflowActionParameter(
|
||
name="pathQuery",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="Optional virtual path ending in /task/{taskId}",
|
||
),
|
||
},
|
||
execute=get_task.__get__(self, self.__class__),
|
||
),
|
||
"createTask": WorkflowActionDefinition(
|
||
actionId="clickup.createTask",
|
||
description="Create a task in a list",
|
||
dynamicMode=True,
|
||
parameters={
|
||
"connectionReference": WorkflowActionParameter(
|
||
name="connectionReference",
|
||
type="str",
|
||
frontendType=FrontendType.USER_CONNECTION,
|
||
required=True,
|
||
description="ClickUp connection",
|
||
),
|
||
"listId": WorkflowActionParameter(
|
||
name="listId",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="List ID (if not using path)",
|
||
),
|
||
"pathQuery": WorkflowActionParameter(
|
||
name="pathQuery",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="Virtual path to list /team/{teamId}/list/{listId}",
|
||
),
|
||
"name": WorkflowActionParameter(
|
||
name="name",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=True,
|
||
description="Task name",
|
||
),
|
||
"description": WorkflowActionParameter(
|
||
name="description",
|
||
type="str",
|
||
frontendType=FrontendType.TEXTAREA,
|
||
required=False,
|
||
description="Task description",
|
||
),
|
||
"customFieldValues": WorkflowActionParameter(
|
||
name="customFieldValues",
|
||
type="str",
|
||
frontendType=FrontendType.TEXTAREA,
|
||
required=False,
|
||
description="Map of ClickUp custom field id to value (merged into custom_fields).",
|
||
),
|
||
"taskFields": WorkflowActionParameter(
|
||
name="taskFields",
|
||
type="str",
|
||
frontendType=FrontendType.TEXTAREA,
|
||
required=False,
|
||
description="Optional extra JSON object merged into create payload (overrides standard fields)",
|
||
),
|
||
"taskStatus": WorkflowActionParameter(
|
||
name="taskStatus",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="ClickUp status name for this list",
|
||
),
|
||
"taskPriority": WorkflowActionParameter(
|
||
name="taskPriority",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="Priority 1 (urgent)–4 (low), empty to omit",
|
||
),
|
||
"taskDueDateMs": WorkflowActionParameter(
|
||
name="taskDueDateMs",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="Due date as Unix ms timestamp",
|
||
),
|
||
"taskAssigneeIds": WorkflowActionParameter(
|
||
name="taskAssigneeIds",
|
||
type="str",
|
||
frontendType=FrontendType.TEXTAREA,
|
||
required=False,
|
||
description="JSON array of ClickUp user ids, e.g. [123,456]",
|
||
),
|
||
"taskTimeEstimateMs": WorkflowActionParameter(
|
||
name="taskTimeEstimateMs",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="Time estimate in milliseconds",
|
||
),
|
||
"taskTimeEstimateHours": WorkflowActionParameter(
|
||
name="taskTimeEstimateHours",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="Time estimate in hours (converted to ms; preferred over taskTimeEstimateMs)",
|
||
),
|
||
},
|
||
execute=create_task.__get__(self, self.__class__),
|
||
),
|
||
"updateTask": WorkflowActionDefinition(
|
||
actionId="clickup.updateTask",
|
||
description="Update a task (JSON body per ClickUp API)",
|
||
dynamicMode=True,
|
||
parameters={
|
||
"connectionReference": WorkflowActionParameter(
|
||
name="connectionReference",
|
||
type="str",
|
||
frontendType=FrontendType.USER_CONNECTION,
|
||
required=True,
|
||
description="ClickUp connection",
|
||
),
|
||
"taskId": WorkflowActionParameter(
|
||
name="taskId",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="Task ID",
|
||
),
|
||
"path": WorkflowActionParameter(
|
||
name="path",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="Optional path ending in /task/{taskId}",
|
||
),
|
||
"taskUpdate": WorkflowActionParameter(
|
||
name="taskUpdate",
|
||
type="str",
|
||
frontendType=FrontendType.TEXTAREA,
|
||
required=False,
|
||
description="JSON object for PUT /task/{id} (e.g. {\"name\":\"...\",\"status\":\"...\"}); built from editor rows if empty",
|
||
),
|
||
},
|
||
execute=update_task.__get__(self, self.__class__),
|
||
),
|
||
"uploadAttachment": WorkflowActionDefinition(
|
||
actionId="clickup.uploadAttachment",
|
||
description="Upload a file attachment to a task",
|
||
dynamicMode=True,
|
||
parameters={
|
||
"connectionReference": WorkflowActionParameter(
|
||
name="connectionReference",
|
||
type="str",
|
||
frontendType=FrontendType.USER_CONNECTION,
|
||
required=True,
|
||
description="ClickUp connection",
|
||
),
|
||
"taskId": WorkflowActionParameter(
|
||
name="taskId",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="Task ID",
|
||
),
|
||
"path": WorkflowActionParameter(
|
||
name="path",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="Optional path ending in /task/{taskId}",
|
||
),
|
||
"fileName": WorkflowActionParameter(
|
||
name="fileName",
|
||
type="str",
|
||
frontendType=FrontendType.TEXT,
|
||
required=False,
|
||
description="Attachment file name",
|
||
),
|
||
"content": WorkflowActionParameter(
|
||
name="content",
|
||
type="Any",
|
||
frontendType=FrontendType.DOCUMENT_REFERENCE,
|
||
required=True,
|
||
description="File from upstream node",
|
||
),
|
||
},
|
||
execute=upload_attachment.__get__(self, self.__class__),
|
||
),
|
||
}
|
||
self._validateActions()
|