diff --git a/components/clockify/actions/add-members-to-project/add-members-to-project.mjs b/components/clockify/actions/add-members-to-project/add-members-to-project.mjs index 183911b421cb9..e512d03e06d4f 100644 --- a/components/clockify/actions/add-members-to-project/add-members-to-project.mjs +++ b/components/clockify/actions/add-members-to-project/add-members-to-project.mjs @@ -4,7 +4,7 @@ export default { key: "clockify-add-members-to-project", name: "Add Members To Project", description: "Adds member(s) to a project in Clockify. [See the documentation](https://docs.clockify.me/#tag/Project/operation/updateMemberships)", - version: "0.0.2", + version: "0.0.3", annotations: { destructiveHint: true, openWorldHint: true, diff --git a/components/clockify/actions/add-task-to-project/add-task-to-project.mjs b/components/clockify/actions/add-task-to-project/add-task-to-project.mjs index eb6e3f0a43458..cbf24110f0657 100644 --- a/components/clockify/actions/add-task-to-project/add-task-to-project.mjs +++ b/components/clockify/actions/add-task-to-project/add-task-to-project.mjs @@ -4,7 +4,7 @@ export default { key: "clockify-add-task-to-project", name: "Add Task To Project", description: "Adds a task to a project in Clockify. [See the documentation](https://docs.clockify.me/#tag/Task/operation/create_7)", - version: "0.0.2", + version: "0.0.3", annotations: { destructiveHint: false, openWorldHint: true, diff --git a/components/clockify/actions/create-project/create-project.mjs b/components/clockify/actions/create-project/create-project.mjs index ff6fa18a08eca..b296b4940b9f9 100644 --- a/components/clockify/actions/create-project/create-project.mjs +++ b/components/clockify/actions/create-project/create-project.mjs @@ -4,7 +4,7 @@ export default { key: "clockify-create-project", name: "Create Project", description: "Creates a new project in Clockify. [See the documentation](https://docs.clockify.me/#tag/Project/operation/create_6)", - version: "0.0.2", + version: "0.0.3", annotations: { destructiveHint: false, openWorldHint: true, diff --git a/components/clockify/actions/get-time-entry-report/get-time-entry-report.mjs b/components/clockify/actions/get-time-entry-report/get-time-entry-report.mjs new file mode 100644 index 0000000000000..9caf7cc4cb2ab --- /dev/null +++ b/components/clockify/actions/get-time-entry-report/get-time-entry-report.mjs @@ -0,0 +1,145 @@ +import clockify from "../../clockify.app.mjs"; + +export default { + name: "Get Time Entry Report", + description: "Get a time entry report. [See the documentation](https://docs.clockify.me/#tag/Time-Entry-Report/operation/generateDetailedReport)", + key: "clockify-get-time-entry-report", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + clockify, + workspaceId: { + propDefinition: [ + clockify, + "workspaceId", + ], + }, + dateRangeStart: { + type: "string", + label: "Date Range Start", + description: "The start date of the date range. Format: YYYY-MM-DDTHH:MM:SS.ssssssZ", + }, + dateRangeEnd: { + type: "string", + label: "Date Range End", + description: "The end date of the date range. Format: YYYY-MM-DDTHH:MM:SS.ssssssZ", + }, + clientIds: { + propDefinition: [ + clockify, + "clientId", + (c) => ({ + workspaceId: c.workspaceId, + }), + ], + type: "string[]", + label: "Client IDs", + description: "Array of client identifiers", + }, + projectId: { + propDefinition: [ + clockify, + "projectId", + (c) => ({ + workspaceId: c.workspaceId, + }), + ], + optional: true, + }, + taskIds: { + propDefinition: [ + clockify, + "taskId", + (c) => ({ + workspaceId: c.workspaceId, + projectId: c.projectId, + }), + ], + type: "string[]", + label: "Task IDs", + description: "Array of task identifiers", + optional: true, + }, + tagIds: { + propDefinition: [ + clockify, + "tagIds", + (c) => ({ + workspaceId: c.workspaceId, + }), + ], + optional: true, + }, + userIds: { + propDefinition: [ + clockify, + "memberIds", + (c) => ({ + workspaceId: c.workspaceId, + }), + ], + optional: true, + }, + }, + async run({ $ }) { + const response = await this.clockify.getTimeEntryReport({ + $, + workspaceId: this.workspaceId, + data: { + dateRangeStart: this.dateRangeStart, + dateRangeEnd: this.dateRangeEnd, + detailedFilter: { + options: { + totals: "CALCULATE", + }, + }, + clients: this.clientIds + ? { + contains: "CONTAINS", + ids: this.clientIds, + status: "ALL", + } + : undefined, + projects: this.projectId + ? { + contains: "CONTAINS", + ids: [ + this.projectId, + ], + status: "ALL", + } + : undefined, + tasks: this.taskIds + ? { + contains: "CONTAINS", + ids: this.taskIds, + status: "ALL", + } + : undefined, + tags: this.tagIds + ? { + contains: "CONTAINS", + ids: this.tagIds, + status: "ALL", + } + : undefined, + users: this.userIds + ? { + contains: "CONTAINS", + ids: this.userIds, + status: "ALL", + } + : undefined, + }, + }); + + $.export("$summary", "Successfully retrieved time entry report"); + + return response; + }, +}; diff --git a/components/clockify/actions/list-projects/list-projects.mjs b/components/clockify/actions/list-projects/list-projects.mjs new file mode 100644 index 0000000000000..7d74433c03507 --- /dev/null +++ b/components/clockify/actions/list-projects/list-projects.mjs @@ -0,0 +1,190 @@ +import clockify from "../../clockify.app.mjs"; + +export default { + key: "clockify-list-projects", + name: "List Projects", + description: "List all projects in a Clockify workspace. [See the documentation](https://docs.clockify.me/#tag/Project/operation/getProjects)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + clockify, + workspaceId: { + propDefinition: [ + clockify, + "workspaceId", + ], + }, + name: { + type: "string", + label: "Name", + description: "If provided, you'll get a filtered list of projects that contains the provided string in the project name", + optional: true, + }, + strictNameSearch: { + propDefinition: [ + clockify, + "strictNameSearch", + ], + }, + archived: { + type: "boolean", + label: "Archived", + description: "If set to `true`, you'll only get archived projects", + optional: true, + }, + billable: { + type: "boolean", + label: "Billable", + description: "If set to `true`, you'll only get billable projects", + optional: true, + }, + clients: { + propDefinition: [ + clockify, + "clientId", + (c) => ({ + workspaceId: c.workspaceId, + }), + ], + type: "string[]", + label: "Clients", + description: "Array of client identifiers", + }, + containsClient: { + type: "boolean", + label: "Contains Client", + description: "If set to `true`, you'll get a filtered list of projects that contain clients which match the provided id(s) in 'clients' field. If set to `false`, you'll get a filtered list of projects which do NOT contain clients that match the provided id(s) in 'clients' field.", + optional: true, + }, + clientStatus: { + type: "string", + label: "Client Status", + description: "Filters projects based on client status provided", + optional: true, + options: [ + "ACTIVE", + "ARCHIVED", + "ALL", + ], + }, + users: { + propDefinition: [ + clockify, + "memberIds", + (c) => ({ + workspaceId: c.workspaceId, + }), + ], + label: "Users", + description: "Array of member/user identifiers", + optional: true, + }, + containsUser: { + type: "boolean", + label: "Contains User", + description: "If set to `true`, you'll get a filtered list of projects that contain users which match the provided id(s) in 'users' field. If set to `false`, you'll get a filtered list of projects which do NOT contain users that match the provided id(s) in 'users' field.", + optional: true, + }, + userStatus: { + type: "string", + label: "User Status", + description: "Filters projects based on user status provided", + optional: true, + options: [ + "PENDING", + "ACTIVE", + "DECLINED", + "INACTIVE", + "ALL", + ], + }, + isTemplate: { + type: "boolean", + label: "Is Template", + description: "Filters projects based on whether they are used as a template or not", + optional: true, + }, + sortColumn: { + type: "string", + label: "Sort Column", + description: "The column to sort the projects by", + optional: true, + options: [ + "ID", + "NAME", + "CLIENT_NAME", + "DURATION", + "BUDGET", + "PROGRESS", + ], + }, + sortOrder: { + propDefinition: [ + clockify, + "sortOrder", + ], + }, + hydrated: { + propDefinition: [ + clockify, + "hydrated", + ], + }, + access: { + type: "string", + label: "Access", + description: "If provided, you'll get a filtered list of projects that matches the provided access", + optional: true, + options: [ + "PUBLIC", + "PRIVATE", + ], + }, + page: { + propDefinition: [ + clockify, + "page", + ], + }, + pageSize: { + propDefinition: [ + clockify, + "pageSize", + ], + }, + }, + async run({ $ }) { + const response = await this.clockify.listProjects({ + $, + workspaceId: this.workspaceId, + params: { + "name": this.name, + "strict-name-search": this.strictNameSearch, + "archived": this.archived, + "billable": this.billable, + "clients": this.clients, + "contains-client": this.containsClient, + "client-status": this.clientStatus, + "users": this.users, + "contains-user": this.containsUser, + "user-status": this.userStatus, + "is-template": this.isTemplate, + "sort-column": this.sortColumn, + "sort-order": this.sortOrder, + "hydrated": this.hydrated, + "access": this.access, + "page": this.page, + "page-size": this.pageSize, + }, + }); + + $.export("$summary", `Successfully listed ${response.length} projects in the workspace`); + + return response; + }, +}; diff --git a/components/clockify/actions/list-tasks/list-tasks.mjs b/components/clockify/actions/list-tasks/list-tasks.mjs new file mode 100644 index 0000000000000..c5dc85efc2437 --- /dev/null +++ b/components/clockify/actions/list-tasks/list-tasks.mjs @@ -0,0 +1,98 @@ +import clockify from "../../clockify.app.mjs"; + +export default { + key: "clockify-list-tasks", + name: "List Tasks", + description: "List all tasks in a Clockify project. [See the documentation](https://docs.clockify.me/#tag/Task/operation/getTasks)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + clockify, + workspaceId: { + propDefinition: [ + clockify, + "workspaceId", + ], + }, + projectId: { + propDefinition: [ + clockify, + "projectId", + (c) => ({ + workspaceId: c.workspaceId, + }), + ], + }, + name: { + type: "string", + label: "Name", + description: "If provided, you'll get a filtered list of tasks that contains the provided string in the task name", + optional: true, + }, + strictNameSearch: { + propDefinition: [ + clockify, + "strictNameSearch", + ], + }, + isActive: { + type: "boolean", + label: "Is Active", + description: "Filters search results whether task is active or not", + optional: true, + }, + sortColumn: { + type: "string", + label: "Sort Column", + description: "The column to sort the tasks by", + optional: true, + options: [ + "ID", + "NAME", + ], + }, + sortOrder: { + propDefinition: [ + clockify, + "sortOrder", + ], + }, + page: { + propDefinition: [ + clockify, + "page", + ], + }, + pageSize: { + propDefinition: [ + clockify, + "pageSize", + ], + }, + }, + async run({ $ }) { + const response = await this.clockify.listTasks({ + $, + workspaceId: this.workspaceId, + projectId: this.projectId, + params: { + "name": this.name, + "strict-name-search": this.strictNameSearch, + "is-active": this.isActive, + "sort-column": this.sortColumn, + "sort-order": this.sortOrder, + "page": this.page, + "page-size": this.pageSize, + }, + }); + + $.export("$summary", `Successfully listed ${response.length} tasks in the project`); + + return response; + }, +}; diff --git a/components/clockify/actions/list-time-entries/list-time-entries.mjs b/components/clockify/actions/list-time-entries/list-time-entries.mjs new file mode 100644 index 0000000000000..a3a0871bd5235 --- /dev/null +++ b/components/clockify/actions/list-time-entries/list-time-entries.mjs @@ -0,0 +1,145 @@ +import clockify from "../../clockify.app.mjs"; + +export default { + key: "clockify-list-time-entries", + name: "List Time Entries", + description: "List all time entries in a Clockify workspace. [See the documentation](https://docs.clockify.me/#tag/Time-entry/operation/getTimeEntries)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + clockify, + workspaceId: { + propDefinition: [ + clockify, + "workspaceId", + ], + }, + userId: { + propDefinition: [ + clockify, + "memberIds", + (c) => ({ + workspaceId: c.workspaceId, + }), + ], + type: "string", + label: "User", + description: "Identifier of a user", + }, + description: { + type: "string", + label: "Description", + description: "Represents term for searching time entries by description", + optional: true, + }, + start: { + type: "string", + label: "Start", + description: "Represents start date in yyyy-MM-ddThh:mm:ssZ format. Example: `2020-01-01T00:00:00Z`", + optional: true, + }, + end: { + type: "string", + label: "End", + description: "Represents end date in yyyy-MM-ddThh:mm:ssZ format. Example: `2020-01-01T00:00:00Z`", + optional: true, + }, + projectId: { + propDefinition: [ + clockify, + "projectId", + (c) => ({ + workspaceId: c.workspaceId, + }), + ], + optional: true, + }, + taskId: { + propDefinition: [ + clockify, + "taskId", + (c) => ({ + workspaceId: c.workspaceId, + projectId: c.projectId, + }), + ], + optional: true, + }, + tagIds: { + propDefinition: [ + clockify, + "tagIds", + (c) => ({ + workspaceId: c.workspaceId, + }), + ], + optional: true, + }, + projectRequired: { + type: "boolean", + label: "Project Required", + description: "Flag to set whether to only get time entries which have a project", + optional: true, + }, + taskRequired: { + type: "boolean", + label: "Task Required", + description: "Flag to set whether to only get time entries which have a task", + optional: true, + }, + hydrated: { + propDefinition: [ + clockify, + "hydrated", + ], + }, + inProgress: { + type: "boolean", + label: "In Progress", + description: "Flag to set whether to filter only in progress time entries", + optional: true, + }, + page: { + propDefinition: [ + clockify, + "page", + ], + }, + pageSize: { + propDefinition: [ + clockify, + "pageSize", + ], + }, + }, + async run({ $ }) { + const response = await this.clockify.listTimeEntries({ + $, + workspaceId: this.workspaceId, + userId: this.userId, + params: { + "description": this.description, + "start": this.start, + "end": this.end, + "project": this.projectId, + "task": this.taskId, + "tags": this.tagIds, + "project-required": this.projectRequired, + "task-required": this.taskRequired, + "hydrated": this.hydrated, + "in-progress": this.inProgress, + "page": this.page, + "page-size": this.pageSize, + }, + }); + + $.export("$summary", `Successfully listed ${response.length} time entries`); + + return response; + }, +}; diff --git a/components/clockify/clockify.app.mjs b/components/clockify/clockify.app.mjs index a3d98a6d5f9ce..c54675740a1ad 100644 --- a/components/clockify/clockify.app.mjs +++ b/components/clockify/clockify.app.mjs @@ -82,6 +82,88 @@ export default { })) || []; }, }, + taskId: { + type: "string", + label: "Task", + description: "Identifier of a task", + async options({ + workspaceId, projectId, page, + }) { + if (!workspaceId || !projectId) { + return []; + } + const tasks = await this.listTasks({ + workspaceId, + projectId, + params: { + page: page + 1, + }, + }); + return tasks?.map(({ + id: value, name: label, + }) => ({ + value, + label, + })) || []; + }, + }, + tagIds: { + type: "string[]", + label: "Tags", + description: "Array of tag identifiers", + async options({ + workspaceId, page, + }) { + const tags = await this.listTags({ + workspaceId, + params: { + page: page + 1, + }, + }); + return tags?.map(({ + id: value, name: label, + }) => ({ + value, + label, + })) || []; + }, + }, + hydrated: { + type: "boolean", + label: "Hydrated", + description: "If set to `true`, you'll get a hydrated response with additional information", + optional: true, + }, + strictNameSearch: { + type: "boolean", + label: "Strict Name Search", + description: "Flag to toggle on/off strict search mode", + optional: true, + }, + sortOrder: { + type: "string", + label: "Sort Order", + description: "The order to sort the results by", + optional: true, + options: [ + "ASCENDING", + "DESCENDING", + ], + }, + page: { + type: "integer", + label: "Page", + description: "The page number to return. Default is `1`", + optional: true, + default: 1, + }, + pageSize: { + type: "integer", + label: "Page Size", + description: "The number of results to return. Default is `100`", + optional: true, + default: 100, + }, }, methods: { _baseUrl() { @@ -97,11 +179,12 @@ export default { }, _makeRequest({ $ = this, + url, path, ...args }) { return axios($, { - url: `${this._baseUrl()}${path}`, + url: url || `${this._baseUrl()}${path}`, headers: this._headers(), ...args, }); @@ -136,6 +219,39 @@ export default { ...args, }); }, + listTasks({ + workspaceId, projectId, ...args + }) { + return this._makeRequest({ + path: `/workspaces/${workspaceId}/projects/${projectId}/tasks`, + ...args, + }); + }, + listTimeEntries({ + workspaceId, userId, ...args + }) { + return this._makeRequest({ + path: `/workspaces/${workspaceId}/user/${userId}/time-entries`, + ...args, + }); + }, + listTags({ + workspaceId, ...args + }) { + return this._makeRequest({ + path: `/workspaces/${workspaceId}/tags`, + ...args, + }); + }, + getTimeEntryReport({ + workspaceId, ...args + }) { + return this._makeRequest({ + method: "POST", + url: `https://reports.api.clockify.me/v1/workspaces/${workspaceId}/reports/detailed`, + ...args, + }); + }, createProject({ workspaceId, ...args }) { diff --git a/components/clockify/package.json b/components/clockify/package.json index 639228bdfe565..86238e6bf9a9f 100644 --- a/components/clockify/package.json +++ b/components/clockify/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/clockify", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Clockify Components", "main": "clockify.app.mjs", "keywords": [ @@ -13,6 +13,6 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^1.6.8" + "@pipedream/platform": "^3.1.0" } } diff --git a/components/embedapi/embedapi.app.mjs b/components/embedapi/embedapi.app.mjs index 0d45837d3b8da..a3ed75b60c177 100644 --- a/components/embedapi/embedapi.app.mjs +++ b/components/embedapi/embedapi.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/mallabe/mallabe.app.mjs b/components/mallabe/mallabe.app.mjs index 5ef42359d504e..01fd2efd4e20a 100644 --- a/components/mallabe/mallabe.app.mjs +++ b/components/mallabe/mallabe.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/meetgeek/meetgeek.app.mjs b/components/meetgeek/meetgeek.app.mjs index 27d216dc58a05..8b925cbc312ea 100644 --- a/components/meetgeek/meetgeek.app.mjs +++ b/components/meetgeek/meetgeek.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/microsoft_azure_monitor/microsoft_azure_monitor.app.mjs b/components/microsoft_azure_monitor/microsoft_azure_monitor.app.mjs index 17e82a31af5c4..5127f45bda86e 100644 --- a/components/microsoft_azure_monitor/microsoft_azure_monitor.app.mjs +++ b/components/microsoft_azure_monitor/microsoft_azure_monitor.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/nele_ai/nele_ai.app.mjs b/components/nele_ai/nele_ai.app.mjs index b42004b0862a7..2de15e4012a22 100644 --- a/components/nele_ai/nele_ai.app.mjs +++ b/components/nele_ai/nele_ai.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/octave/octave.app.mjs b/components/octave/octave.app.mjs index c3b7165562982..b975b70d481c7 100644 --- a/components/octave/octave.app.mjs +++ b/components/octave/octave.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/olostep/olostep.app.mjs b/components/olostep/olostep.app.mjs index c0909a866dcd9..28e3236bf609f 100644 --- a/components/olostep/olostep.app.mjs +++ b/components/olostep/olostep.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/opencti/opencti.app.mjs b/components/opencti/opencti.app.mjs index 0d4a9cd757665..82f69a4353bc7 100644 --- a/components/opencti/opencti.app.mjs +++ b/components/opencti/opencti.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/orq_ai/orq_ai.app.mjs b/components/orq_ai/orq_ai.app.mjs index 72e17774008d6..433582d952155 100644 --- a/components/orq_ai/orq_ai.app.mjs +++ b/components/orq_ai/orq_ai.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/progress_agentic_rag/progress_agentic_rag.app.mjs b/components/progress_agentic_rag/progress_agentic_rag.app.mjs index 3108ca5de7ba3..e957baf846b40 100644 --- a/components/progress_agentic_rag/progress_agentic_rag.app.mjs +++ b/components/progress_agentic_rag/progress_agentic_rag.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d0187bab4b03d..2c1d6f2035759 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2898,8 +2898,8 @@ importers: components/clockify: dependencies: '@pipedream/platform': - specifier: ^1.6.8 - version: 1.6.8 + specifier: ^3.1.0 + version: 3.1.1 components/clockwork_recruiting: dependencies: