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:
@@ -0,0 +1,41 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { linearAuth } from '../../..';
|
||||
import { props } from '../../common/props';
|
||||
import { makeClient } from '../../common/client';
|
||||
import { LinearDocument } from '@linear/sdk';
|
||||
|
||||
export const linearCreateComment = createAction({
|
||||
auth: linearAuth,
|
||||
name: 'linear_create_comment',
|
||||
displayName: 'Create Comment',
|
||||
description: 'Create a new comment on an issue in Linear workspace',
|
||||
props: {
|
||||
team_id: props.team_id(),
|
||||
user_id: props.assignee_id(),
|
||||
issue_id: props.issue_id(),
|
||||
body: Property.LongText({
|
||||
displayName: 'Comment Body',
|
||||
description: 'The content of the comment',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const comment: LinearDocument.CommentCreateInput = {
|
||||
issueId: propsValue.issue_id!,
|
||||
body: propsValue.body,
|
||||
};
|
||||
|
||||
const client = makeClient(auth);
|
||||
const result = await client.createComment(comment);
|
||||
if (result.success) {
|
||||
const createdComment = await result.comment;
|
||||
return {
|
||||
success: result.success,
|
||||
lastSyncId: result.lastSyncId,
|
||||
comment: createdComment,
|
||||
};
|
||||
} else {
|
||||
throw new Error(`Unexpected error: ${result}`)
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { linearAuth } from '../../..';
|
||||
import { props } from '../../common/props';
|
||||
import { makeClient } from '../../common/client';
|
||||
import { LinearDocument } from '@linear/sdk';
|
||||
|
||||
export const linearCreateIssue = createAction({
|
||||
auth: linearAuth,
|
||||
name: 'linear_create_issue',
|
||||
displayName: 'Create Issue',
|
||||
description: 'Create a new issue in Linear workspace',
|
||||
props: {
|
||||
team_id: props.team_id(),
|
||||
title: Property.ShortText({
|
||||
displayName: 'Title',
|
||||
required: true,
|
||||
}),
|
||||
description: Property.LongText({
|
||||
displayName: 'Description',
|
||||
required: false,
|
||||
}),
|
||||
state_id: props.status_id(),
|
||||
labels: props.labels(),
|
||||
assignee_id: props.assignee_id(),
|
||||
priority_id: props.priority_id(),
|
||||
template_id: props.template_id()
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const issue: LinearDocument.IssueCreateInput = {
|
||||
teamId: propsValue.team_id!,
|
||||
title: propsValue.title,
|
||||
description: propsValue.description,
|
||||
assigneeId: propsValue.assignee_id,
|
||||
stateId: propsValue.state_id,
|
||||
priority: propsValue.priority_id,
|
||||
labelIds: propsValue.labels,
|
||||
templateId: propsValue.template_id
|
||||
};
|
||||
const client = makeClient(auth);
|
||||
const result = await client.createIssue(issue);
|
||||
if (result.success) {
|
||||
const createdIssue = await result.issue;
|
||||
return {
|
||||
success: result.success,
|
||||
lastSyncId: result.lastSyncId,
|
||||
issue: createdIssue,
|
||||
};
|
||||
} else {
|
||||
throw new Error(`Unexpected error: ${result}`)
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { linearAuth } from '../../..';
|
||||
import { props } from '../../common/props';
|
||||
import { makeClient } from '../../common/client';
|
||||
import { LinearDocument } from '@linear/sdk';
|
||||
|
||||
export const linearUpdateIssue = createAction({
|
||||
auth: linearAuth,
|
||||
name: 'linear_update_issue',
|
||||
displayName: 'Update Issue',
|
||||
description: 'Update a issue in Linear Workspace',
|
||||
props: {
|
||||
team_id: props.team_id(),
|
||||
issue_id: props.issue_id(),
|
||||
title: Property.ShortText({
|
||||
displayName: 'Title',
|
||||
required: false,
|
||||
}),
|
||||
description: Property.LongText({
|
||||
displayName: 'Description',
|
||||
required: false,
|
||||
}),
|
||||
state_id: props.status_id(),
|
||||
labels: props.labels(),
|
||||
assignee_id: props.assignee_id(),
|
||||
priority_id: props.priority_id(),
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const issueId = propsValue.issue_id!;
|
||||
const issue: LinearDocument.IssueUpdateInput = {
|
||||
title: propsValue.title,
|
||||
description: propsValue.description,
|
||||
assigneeId: propsValue.assignee_id,
|
||||
stateId: propsValue.state_id,
|
||||
priority: propsValue.priority_id,
|
||||
labelIds: propsValue.labels,
|
||||
};
|
||||
const client = makeClient(auth);
|
||||
const result = await client.updateIssue(issueId, issue);
|
||||
if (result.success) {
|
||||
const updatedIssue = await result.issue;
|
||||
return {
|
||||
success: result.success,
|
||||
lastSyncId: result.lastSyncId,
|
||||
issue: updatedIssue,
|
||||
};
|
||||
} else {
|
||||
throw new Error(`Unexpected error: ${result}`)
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { linearAuth } from '../../..';
|
||||
import { props } from '../../common/props';
|
||||
import { makeClient } from '../../common/client';
|
||||
import { LinearDocument } from '@linear/sdk';
|
||||
|
||||
export const linearCreateProject = createAction({
|
||||
auth: linearAuth,
|
||||
name: 'linear_create_project',
|
||||
displayName: 'Create Project',
|
||||
description: 'Create a new project in Linear workspace',
|
||||
props: {
|
||||
team_id: props.team_id(),
|
||||
name: Property.ShortText({
|
||||
displayName: 'Project Name',
|
||||
required: true,
|
||||
}),
|
||||
description: Property.LongText({
|
||||
displayName: 'Description',
|
||||
required: false,
|
||||
}),
|
||||
icon: Property.ShortText({
|
||||
displayName: 'Icon',
|
||||
required: false,
|
||||
}),
|
||||
color: Property.ShortText({
|
||||
displayName: 'Color',
|
||||
required: false,
|
||||
}),
|
||||
startDate: Property.DateTime({
|
||||
displayName: 'Start Date',
|
||||
required: false,
|
||||
}),
|
||||
targetDate: Property.DateTime({
|
||||
displayName: 'Target Date',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const project: LinearDocument.ProjectCreateInput = {
|
||||
teamIds: [propsValue.team_id!],
|
||||
name: propsValue.name,
|
||||
description: propsValue.description,
|
||||
icon: propsValue.icon,
|
||||
color: propsValue.color,
|
||||
startDate: propsValue.startDate,
|
||||
targetDate: propsValue.targetDate,
|
||||
};
|
||||
|
||||
const client = makeClient(auth);
|
||||
const result = await client.createProject(project);
|
||||
if (result.success) {
|
||||
const createdProject = await result.project;
|
||||
return {
|
||||
success: result.success,
|
||||
lastSyncId: result.lastSyncId,
|
||||
project: createdProject,
|
||||
};
|
||||
} else {
|
||||
throw new Error(`Unexpected error: ${result}`)
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { linearAuth } from '../../..';
|
||||
import { props } from '../../common/props';
|
||||
import { makeClient } from '../../common/client';
|
||||
import { LinearDocument } from '@linear/sdk';
|
||||
|
||||
export const linearUpdateProject = createAction({
|
||||
auth: linearAuth,
|
||||
name: 'linear_update_project',
|
||||
displayName: 'Update Project',
|
||||
description: 'Update a existing project in Linear workspace',
|
||||
props: {
|
||||
team_id: props.team_id(),
|
||||
project_id: props.project_id(),
|
||||
name: Property.ShortText({
|
||||
displayName: 'Project Name',
|
||||
required: true,
|
||||
}),
|
||||
description: Property.LongText({
|
||||
displayName: 'Description',
|
||||
required: false,
|
||||
}),
|
||||
icon: Property.ShortText({
|
||||
displayName: 'Icon',
|
||||
required: false,
|
||||
}),
|
||||
color: Property.ShortText({
|
||||
displayName: 'Color',
|
||||
required: false,
|
||||
}),
|
||||
startDate: Property.DateTime({
|
||||
displayName: 'Start Date',
|
||||
required: false,
|
||||
}),
|
||||
targetDate: Property.DateTime({
|
||||
displayName: 'Target Date',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const project: LinearDocument.ProjectUpdateInput = {
|
||||
teamIds: [propsValue.team_id!],
|
||||
name: propsValue.name,
|
||||
description: propsValue.description,
|
||||
icon: propsValue.icon,
|
||||
color: propsValue.color,
|
||||
startDate: propsValue.startDate,
|
||||
targetDate: propsValue.targetDate,
|
||||
};
|
||||
|
||||
const client = makeClient(auth);
|
||||
const result = await client.updateProject(propsValue.project_id!, project);
|
||||
if (result.success) {
|
||||
const updatedProject = await result.project;
|
||||
return {
|
||||
success: result.success,
|
||||
lastSyncId: result.lastSyncId,
|
||||
project: updatedProject,
|
||||
};
|
||||
} else {
|
||||
throw new Error(`Unexpected error: ${result}`)
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { linearAuth } from '../..';
|
||||
import { makeClient } from '../common/client';
|
||||
|
||||
export const linearRawGraphqlQuery = createAction({
|
||||
name: 'rawGraphqlQuery',
|
||||
displayName: 'Raw GraphQL query',
|
||||
description: 'Perform a raw GraphQL query',
|
||||
auth: linearAuth,
|
||||
props: {
|
||||
query: Property.LongText({ displayName: 'Query', required: true }),
|
||||
variables: Property.Object({ displayName: 'Parameters', required: false }),
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const client = makeClient(auth);
|
||||
const result = await client.rawRequest(
|
||||
propsValue.query,
|
||||
propsValue.variables
|
||||
);
|
||||
return result;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,74 @@
|
||||
import { AppConnectionValueForAuthProperty } from '@activepieces/pieces-framework';
|
||||
import { LinearClient, LinearDocument } from '@linear/sdk';
|
||||
import { linearAuth } from '../..';
|
||||
|
||||
export class LinearClientWrapper {
|
||||
private client: LinearClient;
|
||||
constructor(apiKey: string) {
|
||||
this.client = new LinearClient({ apiKey: apiKey });
|
||||
}
|
||||
async createIssue(input: LinearDocument.IssueCreateInput) {
|
||||
return this.client.createIssue(input);
|
||||
}
|
||||
async listIssueStates(
|
||||
variables: LinearDocument.WorkflowStatesQueryVariables
|
||||
) {
|
||||
return this.client.workflowStates(variables);
|
||||
}
|
||||
async listIssuePriorities() {
|
||||
return this.client.issuePriorityValues;
|
||||
}
|
||||
async listUsers(variables: LinearDocument.UsersQueryVariables) {
|
||||
return this.client.users(variables);
|
||||
}
|
||||
async listIssueLabels(variables: LinearDocument.IssueLabelsQueryVariables) {
|
||||
return this.client.issueLabels(variables);
|
||||
}
|
||||
async listTeams(variables: LinearDocument.TeamsQueryVariables = {}) {
|
||||
return this.client.teams(variables);
|
||||
}
|
||||
async listIssues(variables: LinearDocument.IssuesQueryVariables = {}) {
|
||||
return this.client.issues(variables);
|
||||
}
|
||||
async updateIssue(issueId: string, input: LinearDocument.IssueUpdateInput) {
|
||||
return this.client.updateIssue(issueId, input);
|
||||
}
|
||||
async createProject(input: LinearDocument.ProjectCreateInput) {
|
||||
return this.client.createProject(input);
|
||||
}
|
||||
async listProjects(variables: LinearDocument.ProjectsQueryVariables = {}) {
|
||||
return this.client.projects(variables);
|
||||
}
|
||||
async updateProject(
|
||||
projectId: string,
|
||||
input: LinearDocument.ProjectUpdateInput
|
||||
) {
|
||||
return this.client.updateProject(projectId, input);
|
||||
}
|
||||
async createComment(input: LinearDocument.CommentCreateInput) {
|
||||
return this.client.createComment(input);
|
||||
}
|
||||
async createWebhook(input: LinearDocument.WebhookCreateInput) {
|
||||
return this.client.createWebhook(input);
|
||||
}
|
||||
async listWebhooks(variables: LinearDocument.WebhooksQueryVariables = {}) {
|
||||
return this.client.webhooks(variables);
|
||||
}
|
||||
async deleteWebhook(webhookId: string) {
|
||||
return this.client.deleteWebhook(webhookId);
|
||||
}
|
||||
async listTeamsTemplates(
|
||||
teamId: string,
|
||||
variables: Omit<LinearDocument.Team_TemplatesQueryVariables, 'id'>
|
||||
) {
|
||||
const team = await this.client.team(teamId);
|
||||
return team.templates(variables);
|
||||
}
|
||||
async rawRequest(query: string, variables?: Record<string, unknown>) {
|
||||
return this.client.client.rawRequest(query, variables);
|
||||
}
|
||||
}
|
||||
|
||||
export function makeClient(auth: AppConnectionValueForAuthProperty<typeof linearAuth>): LinearClientWrapper {
|
||||
return new LinearClientWrapper(auth.secret_text);
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
import { DropdownOption, Property } from '@activepieces/pieces-framework';
|
||||
import { makeClient } from './client';
|
||||
import { LinearDocument } from '@linear/sdk';
|
||||
import { linearAuth } from '../..';
|
||||
|
||||
export const props = {
|
||||
team_id: (required = true) =>
|
||||
Property.Dropdown({
|
||||
auth: linearAuth,
|
||||
description:
|
||||
'The team for which the issue, project or comment will be created',
|
||||
displayName: 'Team',
|
||||
required,
|
||||
refreshers: ['auth'],
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'connect your account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const client = makeClient(auth);
|
||||
const options: DropdownOption<string>[] = [];
|
||||
|
||||
let hasNextPage = false;
|
||||
let cursor;
|
||||
|
||||
do {
|
||||
const teams = await client.listTeams({
|
||||
orderBy: LinearDocument.PaginationOrderBy.UpdatedAt,
|
||||
first: 100,
|
||||
after: cursor,
|
||||
});
|
||||
|
||||
for (const team of teams.nodes) {
|
||||
options.push({ label: team.name, value: team.id });
|
||||
}
|
||||
|
||||
hasNextPage = teams.pageInfo.hasNextPage;
|
||||
cursor = teams.pageInfo.endCursor;
|
||||
} while (hasNextPage);
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options,
|
||||
};
|
||||
},
|
||||
}),
|
||||
status_id: (required = false) =>
|
||||
Property.Dropdown({
|
||||
auth: linearAuth,
|
||||
description: 'Status of the Issue',
|
||||
displayName: 'Status',
|
||||
required,
|
||||
refreshers: ['auth', 'team_id'],
|
||||
options: async ({ auth, team_id }) => {
|
||||
if (!auth || !team_id) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'connect your account first and select team',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const client = makeClient(auth);
|
||||
const options: DropdownOption<string>[] = [];
|
||||
|
||||
let hasNextPage = false;
|
||||
let cursor;
|
||||
|
||||
do {
|
||||
const filter: LinearDocument.WorkflowStatesQueryVariables = {
|
||||
filter: {
|
||||
team: {
|
||||
id: {
|
||||
eq: team_id as string,
|
||||
},
|
||||
},
|
||||
},
|
||||
first: 100,
|
||||
after: cursor,
|
||||
};
|
||||
const statusList = await client.listIssueStates(filter);
|
||||
|
||||
for (const status of statusList.nodes) {
|
||||
options.push({ label: status.name, value: status.id });
|
||||
}
|
||||
|
||||
hasNextPage = statusList.pageInfo.hasNextPage;
|
||||
cursor = statusList.pageInfo.endCursor;
|
||||
} while (hasNextPage);
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options,
|
||||
};
|
||||
},
|
||||
}),
|
||||
labels: (required = false) =>
|
||||
Property.MultiSelectDropdown({
|
||||
auth: linearAuth,
|
||||
description: 'Labels for the Issue',
|
||||
displayName: 'Labels',
|
||||
required,
|
||||
refreshers: ['auth', 'team_id'],
|
||||
options: async ({ auth, team_id }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'connect your account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
if (!team_id) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'select a team to load labels',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const client = makeClient(auth);
|
||||
const teamLabels: DropdownOption<string>[] = [];
|
||||
const workspaceLabels: DropdownOption<string>[] = [];
|
||||
|
||||
// Fetch team specific labels
|
||||
let hasNextPage = false;
|
||||
let cursor;
|
||||
|
||||
do {
|
||||
const labels = await client.listIssueLabels({
|
||||
filter: {
|
||||
team: {
|
||||
id: {
|
||||
eq: team_id as string,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: LinearDocument.PaginationOrderBy.UpdatedAt,
|
||||
first: 100,
|
||||
after: cursor,
|
||||
});
|
||||
|
||||
for (const label of labels.nodes) {
|
||||
teamLabels.push({ label: label.name, value: label.id });
|
||||
}
|
||||
|
||||
hasNextPage = labels.pageInfo.hasNextPage;
|
||||
cursor = labels.pageInfo.endCursor;
|
||||
} while (hasNextPage);
|
||||
|
||||
// Fetch all workspace labels that are common to all teams
|
||||
hasNextPage = false;
|
||||
cursor = undefined;
|
||||
|
||||
do {
|
||||
const labels = await client.listIssueLabels({
|
||||
filter: {
|
||||
team: {
|
||||
null: true,
|
||||
},
|
||||
},
|
||||
orderBy: LinearDocument.PaginationOrderBy.UpdatedAt,
|
||||
first: 100,
|
||||
after: cursor,
|
||||
});
|
||||
|
||||
for (const label of labels.nodes) {
|
||||
// Prefix workspace labels with [Workspace]
|
||||
workspaceLabels.push({ label: `[Workspace] ${label.name}`, value: label.id });
|
||||
}
|
||||
|
||||
hasNextPage = labels.pageInfo.hasNextPage;
|
||||
cursor = labels.pageInfo.endCursor;
|
||||
} while (hasNextPage);
|
||||
|
||||
// team labels are displayed first in alphabetical order
|
||||
teamLabels.sort((a, b) => a.label.localeCompare(b.label));
|
||||
|
||||
// followed by workspace labels in alphabetical order
|
||||
workspaceLabels.sort((a, b) => a.label.localeCompare(b.label));
|
||||
|
||||
const options = [...teamLabels, ...workspaceLabels];
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options,
|
||||
};
|
||||
},
|
||||
}),
|
||||
assignee_id: (required = false) =>
|
||||
Property.Dropdown({
|
||||
auth: linearAuth,
|
||||
description: 'Assignee of the Issue / Comment',
|
||||
displayName: 'Assignee',
|
||||
required,
|
||||
refreshers: ['auth'],
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'connect your account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const client = makeClient(auth);
|
||||
const options: DropdownOption<string>[] = [];
|
||||
|
||||
let hasNextPage = false;
|
||||
let cursor;
|
||||
|
||||
do {
|
||||
const users = await client.listUsers({
|
||||
orderBy: LinearDocument.PaginationOrderBy.UpdatedAt,
|
||||
first: 100,
|
||||
after: cursor,
|
||||
});
|
||||
|
||||
for (const user of users.nodes) {
|
||||
options.push({ label: user.name, value: user.id });
|
||||
}
|
||||
|
||||
hasNextPage = users.pageInfo.hasNextPage;
|
||||
cursor = users.pageInfo.endCursor;
|
||||
} while (hasNextPage);
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options,
|
||||
};
|
||||
},
|
||||
}),
|
||||
priority_id: (required = false) =>
|
||||
Property.Dropdown({
|
||||
auth: linearAuth,
|
||||
description: 'Priority of the Issue',
|
||||
displayName: 'Priority',
|
||||
required,
|
||||
refreshers: ['auth'],
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'connect your account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const client = makeClient(auth);
|
||||
const priorities = await client.listIssuePriorities();
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options: priorities.map((priority: { label: any; priority: any }) => {
|
||||
return {
|
||||
label: priority.label,
|
||||
value: priority.priority,
|
||||
};
|
||||
}),
|
||||
};
|
||||
},
|
||||
}),
|
||||
issue_id: (required = true) =>
|
||||
Property.Dropdown({
|
||||
auth: linearAuth,
|
||||
displayName: 'Issue',
|
||||
required,
|
||||
description: 'ID of Linear Issue',
|
||||
refreshers: ['team_id'],
|
||||
options: async ({ auth, team_id }) => {
|
||||
if (!auth || !team_id) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'connect your account first and select team',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const client = makeClient(auth);
|
||||
const filter: LinearDocument.IssuesQueryVariables = {
|
||||
first: 50,
|
||||
filter: {
|
||||
team: {
|
||||
id: {
|
||||
eq: team_id as string,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: LinearDocument.PaginationOrderBy.UpdatedAt,
|
||||
};
|
||||
const issues = await client.listIssues(filter);
|
||||
return {
|
||||
disabled: false,
|
||||
options: issues.nodes.map((issue: { title: any; id: any }) => {
|
||||
return {
|
||||
label: issue.title,
|
||||
value: issue.id,
|
||||
};
|
||||
}),
|
||||
};
|
||||
},
|
||||
}),
|
||||
|
||||
project_id: (required = true) =>
|
||||
Property.Dropdown({
|
||||
auth: linearAuth,
|
||||
displayName: 'Project',
|
||||
required,
|
||||
description: 'ID of Linear Project',
|
||||
refreshers: ['team_id'],
|
||||
options: async ({ auth, team_id }) => {
|
||||
if (!auth || !team_id) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'connect your account first and select team',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const client = makeClient(auth);
|
||||
const options: DropdownOption<string>[] = [];
|
||||
|
||||
let hasNextPage = false;
|
||||
let cursor;
|
||||
|
||||
do {
|
||||
const projects = await client.listProjects({
|
||||
orderBy: LinearDocument.PaginationOrderBy.UpdatedAt,
|
||||
first: 100,
|
||||
after: cursor,
|
||||
});
|
||||
|
||||
for (const project of projects.nodes) {
|
||||
options.push({ label: project.name, value: project.id });
|
||||
}
|
||||
|
||||
hasNextPage = projects.pageInfo.hasNextPage;
|
||||
cursor = projects.pageInfo.endCursor;
|
||||
} while (hasNextPage);
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options,
|
||||
};
|
||||
},
|
||||
}),
|
||||
template_id: (required = false) =>
|
||||
Property.Dropdown({
|
||||
auth: linearAuth,
|
||||
displayName: 'Template',
|
||||
required,
|
||||
description: 'ID of Template',
|
||||
refreshers: ['auth', 'team_id'],
|
||||
options: async ({ auth, team_id }) => {
|
||||
if (!auth || !team_id) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'connect your account first and select team',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const client = makeClient(auth);
|
||||
const options: DropdownOption<string>[] = [];
|
||||
|
||||
let hasNextPage = false;
|
||||
let cursor;
|
||||
|
||||
do {
|
||||
const filter: Omit<
|
||||
LinearDocument.Team_TemplatesQueryVariables,
|
||||
'id'
|
||||
> = {
|
||||
first: 100,
|
||||
after: cursor,
|
||||
orderBy: LinearDocument.PaginationOrderBy.UpdatedAt,
|
||||
};
|
||||
const templatesConnection = await client.listTeamsTemplates(
|
||||
team_id as string,
|
||||
filter
|
||||
);
|
||||
|
||||
const templates = await templatesConnection.nodes;
|
||||
|
||||
for (const template of templates) {
|
||||
options.push({ label: template.name, value: template.id });
|
||||
}
|
||||
|
||||
hasNextPage = templatesConnection.pageInfo.hasNextPage;
|
||||
cursor = templatesConnection.pageInfo.endCursor;
|
||||
} while (hasNextPage);
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options,
|
||||
};
|
||||
},
|
||||
}),
|
||||
};
|
||||
@@ -0,0 +1,101 @@
|
||||
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
|
||||
import { linearAuth } from '../..';
|
||||
import { makeClient } from '../common/client';
|
||||
import { props } from '../common/props';
|
||||
|
||||
export const linearNewIssue = createTrigger({
|
||||
auth: linearAuth,
|
||||
name: 'new_issue',
|
||||
displayName: 'New Issue',
|
||||
description: 'Triggers when Linear receives a new issue',
|
||||
props: {
|
||||
team_id: props.team_id(),
|
||||
},
|
||||
sampleData: {
|
||||
// Sample data structure based on Linear's webhook payload for issues
|
||||
action: 'create',
|
||||
data: {
|
||||
id: 'issue_1',
|
||||
identifier: '1',
|
||||
title: 'Test issue',
|
||||
description: 'This is a test issue',
|
||||
priority: 'priority_1',
|
||||
priorityLabel: 'High',
|
||||
state: 'state_1',
|
||||
stateLabel: 'In Progress',
|
||||
team: {
|
||||
id: 'team_1',
|
||||
name: 'Test team',
|
||||
key: 'test-team',
|
||||
description: 'This is a test team',
|
||||
archived: false,
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-05T12:00:00.000Z',
|
||||
},
|
||||
creator: {
|
||||
id: 'user_1',
|
||||
name: 'Test user',
|
||||
email: 'test@gmail.com',
|
||||
avatarUrl: 'https://avatars.githubusercontent.com/u/1?v=4',
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-05T12:00:00.000Z',
|
||||
},
|
||||
assignee: {
|
||||
id: 'user_1',
|
||||
name: 'Test user',
|
||||
email: 'test@gmail.com',
|
||||
avatarUrl: 'https://avatars.githubusercontent.com/u/1?v=4',
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-05T12:00:00.000Z',
|
||||
},
|
||||
labels: [
|
||||
{
|
||||
id: 'label_1',
|
||||
name: 'Test label',
|
||||
color: '#000000',
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-05T12:00:00.000Z',
|
||||
},
|
||||
],
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-05T12:00:00.000Z',
|
||||
},
|
||||
},
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
async onEnable(context) {
|
||||
const client = makeClient(context.auth);
|
||||
const webhook = await client.createWebhook({
|
||||
label: 'ActivePieces New Issue',
|
||||
url: context.webhookUrl,
|
||||
teamId: context.propsValue['team_id'],
|
||||
resourceTypes: ['Issue'],
|
||||
});
|
||||
if (webhook.success && webhook.webhook) {
|
||||
await context.store?.put<WebhookInformation>('_new_issue_trigger', {
|
||||
webhookId: (await webhook.webhook).id,
|
||||
});
|
||||
} else {
|
||||
console.error('Failed to create the webhook');
|
||||
}
|
||||
},
|
||||
async onDisable(context) {
|
||||
const client = makeClient(context.auth);
|
||||
const response = await context.store?.get<WebhookInformation>(
|
||||
'_new_issue_trigger'
|
||||
);
|
||||
if (response && response.webhookId) {
|
||||
await client.deleteWebhook(response.webhookId);
|
||||
}
|
||||
},
|
||||
async run(context) {
|
||||
const body = context.payload.body as { action: string; data: unknown };
|
||||
if (body.action === 'create') {
|
||||
return [body.data];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
});
|
||||
|
||||
interface WebhookInformation {
|
||||
webhookId: string;
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
|
||||
import { linearAuth } from '../..';
|
||||
import { makeClient } from '../common/client';
|
||||
import { props } from '../common/props';
|
||||
|
||||
export const linearRemovedIssue = createTrigger({
|
||||
auth: linearAuth,
|
||||
name: 'removed_issue',
|
||||
displayName: 'Removed Issue',
|
||||
description: 'Triggers when an existing Linear issue is removed',
|
||||
props: {
|
||||
team_id: props.team_id()
|
||||
},
|
||||
sampleData: {
|
||||
// Sample data structure based on Linear's webhook payload for issues
|
||||
action: 'remove',
|
||||
data: {
|
||||
id: 'issue_1',
|
||||
identifier: '1',
|
||||
title: 'Test issue',
|
||||
description: 'This is a test issue',
|
||||
priority: 'priority_1',
|
||||
priorityLabel: 'High',
|
||||
state: 'state_1',
|
||||
stateLabel: 'In Progress',
|
||||
team: {
|
||||
id: 'team_1',
|
||||
name: 'Test team',
|
||||
key: 'test-team',
|
||||
description: 'This is a test team',
|
||||
archived: false,
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-05T12:00:00.000Z',
|
||||
},
|
||||
creator: {
|
||||
id: 'user_1',
|
||||
name: 'Test user',
|
||||
email: 'test@gmail.com',
|
||||
avatarUrl: 'https://avatars.githubusercontent.com/u/1?v=4',
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-05T12:00:00.000Z',
|
||||
},
|
||||
assignee: {
|
||||
id: 'user_1',
|
||||
name: 'Test user',
|
||||
email: 'test@gmail.com',
|
||||
avatarUrl: 'https://avatars.githubusercontent.com/u/1?v=4',
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-05T12:00:00.000Z',
|
||||
},
|
||||
labels: [
|
||||
{
|
||||
id: 'label_1',
|
||||
name: 'Test label',
|
||||
color: '#000000',
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-05T12:00:00.000Z',
|
||||
},
|
||||
],
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-05T12:00:00.000Z',
|
||||
},
|
||||
},
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
async onEnable(context) {
|
||||
const client = makeClient(context.auth);
|
||||
const webhook = await client.createWebhook({
|
||||
label: 'ActivePieces Updated Issue',
|
||||
url: context.webhookUrl,
|
||||
teamId: context.propsValue['team_id'],
|
||||
resourceTypes: ['Issue']
|
||||
});
|
||||
if (webhook.success && webhook.webhook) {
|
||||
await context.store?.put<WebhookInformation>('_removed_issue_trigger', {
|
||||
webhookId: (await webhook.webhook).id
|
||||
});
|
||||
} else {
|
||||
console.error('Failed to create the webhook');
|
||||
}
|
||||
},
|
||||
async onDisable(context) {
|
||||
const client = makeClient(context.auth);
|
||||
const response = await context.store?.get<WebhookInformation>(
|
||||
'_removed_issue_trigger'
|
||||
);
|
||||
if (response && response.webhookId) {
|
||||
await client.deleteWebhook(response.webhookId);
|
||||
}
|
||||
},
|
||||
async run(context) {
|
||||
const body = context.payload.body as { action: string; data: unknown};
|
||||
if (body.action === 'remove') {
|
||||
return [body.data];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
interface WebhookInformation {
|
||||
webhookId: string;
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
|
||||
import { linearAuth } from '../..';
|
||||
import { makeClient } from '../common/client';
|
||||
import { props } from '../common/props';
|
||||
|
||||
export const linearUpdatedIssue = createTrigger({
|
||||
auth: linearAuth,
|
||||
name: 'updated_issue',
|
||||
displayName: 'Updated Issue',
|
||||
description: 'Triggers when an existing Linear issue is updated',
|
||||
props: {
|
||||
team_id: props.team_id(false)
|
||||
},
|
||||
sampleData: {
|
||||
// Sample data structure based on Linear's webhook payload for issues
|
||||
action: 'update',
|
||||
data: {
|
||||
id: 'issue_1',
|
||||
identifier: '1',
|
||||
title: 'Test issue updated',
|
||||
description: 'This is a test issue (updated)',
|
||||
priority: 'priority_1',
|
||||
priorityLabel: 'High',
|
||||
state: 'state_2',
|
||||
stateLabel: 'In Review',
|
||||
team: {
|
||||
id: 'team_2',
|
||||
name: 'Test team',
|
||||
key: 'test-team',
|
||||
description: 'This is another test team',
|
||||
archived: false,
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-06T12:00:00.000Z'
|
||||
},
|
||||
creator: {
|
||||
id: 'user_1',
|
||||
name: 'Test user',
|
||||
email: 'test@gmail.com',
|
||||
avatarUrl: 'https://avatars.githubusercontent.com/u/1?v=4',
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-06T12:00:00.000Z'
|
||||
},
|
||||
assignee: {
|
||||
id: 'user_1',
|
||||
name: 'Test user',
|
||||
email: 'test@gmail.com',
|
||||
avatarUrl: 'https://avatars.githubusercontent.com/u/1?v=4',
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-05T12:00:00.000Z'
|
||||
},
|
||||
labels: [
|
||||
{
|
||||
id: 'label_1',
|
||||
name: 'Test label',
|
||||
color: '#000000',
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-05T12:00:00.000Z'
|
||||
},
|
||||
{
|
||||
id: 'label_1',
|
||||
name: 'Test label 2',
|
||||
color: '#000000',
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-06T12:00:00.000Z'
|
||||
}
|
||||
],
|
||||
createdAt: '2023-09-05T12:00:00.000Z',
|
||||
updatedAt: '2023-09-06T12:00:00.000Z'
|
||||
},
|
||||
updatedFrom: {
|
||||
'updatedAt': '2023-09-06T12:00:00.000Z',
|
||||
'sortOrder': -14.61,
|
||||
'startedAt': null,
|
||||
'stateId': 'state_1'
|
||||
}
|
||||
},
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
async onEnable(context) {
|
||||
const client = makeClient(context.auth);
|
||||
|
||||
// Create webhook configuration
|
||||
const webhookConfig: any = {
|
||||
label: 'ActivePieces Updated Issue',
|
||||
url: context.webhookUrl,
|
||||
allPublicTeams: true,
|
||||
resourceTypes: ['Issue']
|
||||
};
|
||||
|
||||
// Only add teamId if it's provided
|
||||
if (context.propsValue['team_id']) {
|
||||
webhookConfig.teamId = context.propsValue['team_id'];
|
||||
}
|
||||
|
||||
const webhook = await client.createWebhook(webhookConfig);
|
||||
|
||||
if (webhook.success && webhook.webhook) {
|
||||
await context.store?.put<WebhookInformation>('_updated_issue_trigger', {
|
||||
webhookId: (await webhook.webhook).id
|
||||
});
|
||||
} else {
|
||||
console.error('Failed to create the webhook');
|
||||
}
|
||||
},
|
||||
async onDisable(context) {
|
||||
const client = makeClient(context.auth);
|
||||
const response = await context.store?.get<WebhookInformation>(
|
||||
'_updated_issue_trigger'
|
||||
);
|
||||
if (response && response.webhookId) {
|
||||
await client.deleteWebhook(response.webhookId);
|
||||
}
|
||||
},
|
||||
async run(context) {
|
||||
const body = context.payload.body as { action: string; data: unknown};
|
||||
if (body.action === 'update') {
|
||||
return [body.data];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
interface WebhookInformation {
|
||||
webhookId: string;
|
||||
}
|
||||
Reference in New Issue
Block a user