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,25 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { microsoft365PlannerAuth, microsoft365PlannerCommon } from '../common';
|
||||
import { OrderHintProperty, PlanDropdown } from '../common/properties';
|
||||
|
||||
export const createBucket = createAction({
|
||||
auth: microsoft365PlannerAuth,
|
||||
name: 'createBucket',
|
||||
displayName: 'Create Bucket',
|
||||
description: 'Create a bucket (category) under a plan.',
|
||||
props: {
|
||||
planId: PlanDropdown({ required: true }),
|
||||
name: Property.ShortText({
|
||||
displayName: 'Bucket Name',
|
||||
description: 'The name of the bucket to be created',
|
||||
required: true,
|
||||
}),
|
||||
orderHint: OrderHintProperty({ required: false }),
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
return await microsoft365PlannerCommon.createBucket({
|
||||
auth,
|
||||
...propsValue,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { microsoft365PlannerAuth, microsoft365PlannerCommon } from '../common';
|
||||
import { groupDropdown } from '../common/properties';
|
||||
|
||||
export const createPlan = createAction({
|
||||
auth: microsoft365PlannerAuth,
|
||||
name: 'createPlan',
|
||||
displayName: 'Create Plan',
|
||||
description: 'Create a new planner plan',
|
||||
props: {
|
||||
groupId: groupDropdown({ required: true }),
|
||||
title: Property.ShortText({
|
||||
displayName: 'Title',
|
||||
description: 'The title of the plan',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const planParams = {
|
||||
container: {
|
||||
url : `https://graph.microsoft.com/v1.0/groups/${propsValue.groupId}`,
|
||||
},
|
||||
title: propsValue.title,
|
||||
};
|
||||
return await microsoft365PlannerCommon.createPlan({ auth, ...planParams });
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,94 @@
|
||||
import {
|
||||
createAction,
|
||||
OAuth2PropertyValue,
|
||||
Property,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { microsoft365PlannerAuth, microsoft365PlannerCommon } from '../common';
|
||||
import { BucketDropdown, PlanDropdown } from '../common/properties';
|
||||
|
||||
export const createTask = createAction({
|
||||
auth: microsoft365PlannerAuth,
|
||||
name: 'createTask',
|
||||
displayName: 'Create Task',
|
||||
description:
|
||||
'Create a new planner task with title, assignments, due date, etc.',
|
||||
props: {
|
||||
planId: PlanDropdown({ required: true }),
|
||||
bucketId: BucketDropdown({ required: false }),
|
||||
title: Property.ShortText({
|
||||
displayName: 'Title',
|
||||
description: 'The title of the task to be created',
|
||||
required: true,
|
||||
}),
|
||||
assignments: Property.MultiSelectDropdown({
|
||||
displayName: 'Assignments',
|
||||
description:
|
||||
'Select users to assign the task to. If left empty, the task will be unassigned.',
|
||||
required: false,
|
||||
auth: microsoft365PlannerAuth,
|
||||
refreshers: ['auth'],
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
options: [],
|
||||
disabled: true,
|
||||
placeholder: 'Please select an authentication first',
|
||||
};
|
||||
}
|
||||
const users = await microsoft365PlannerCommon.listUsers({ auth: auth });
|
||||
return {
|
||||
options: users.map((user) => ({
|
||||
label: user.displayName || user.userPrincipalName || 'No Name',
|
||||
value: user.id || '',
|
||||
})),
|
||||
disabled: false,
|
||||
placeholder: 'Select users to assign the task to',
|
||||
};
|
||||
},
|
||||
}),
|
||||
dueDateTime: Property.DateTime({
|
||||
displayName: 'Due Date',
|
||||
description: 'The due date and time for the task',
|
||||
required: false,
|
||||
}),
|
||||
percentComplete: Property.Number({
|
||||
displayName: 'Percent Complete',
|
||||
description: 'The completion percentage of the task (0-100)',
|
||||
required: false,
|
||||
}),
|
||||
priority: Property.Number({
|
||||
displayName: 'Priority',
|
||||
description:
|
||||
'The priority of the task between 0 and 10, with the increasing value being lower priority (0 has the highest priority and 10 has the lowest priority).',
|
||||
required: false,
|
||||
}),
|
||||
startDateTime: Property.DateTime({
|
||||
displayName: 'Start Date',
|
||||
description: 'The start date and time for the task',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const taskParams = {
|
||||
...propsValue,
|
||||
assignments: propsValue.assignments
|
||||
? Object.fromEntries(
|
||||
propsValue.assignments.map((userId) => [
|
||||
userId,
|
||||
{ '@odata.type': 'microsoft.graph.plannerAssignment' },
|
||||
])
|
||||
)
|
||||
: undefined,
|
||||
dueDateTime: propsValue.dueDateTime
|
||||
? new Date(propsValue.dueDateTime).toISOString()
|
||||
: undefined,
|
||||
startDateTime: propsValue.startDateTime
|
||||
? new Date(propsValue.startDateTime).toISOString()
|
||||
: undefined,
|
||||
};
|
||||
return await microsoft365PlannerCommon.createTask({
|
||||
auth,
|
||||
...taskParams,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { microsoft365PlannerAuth, microsoft365PlannerCommon } from '../common';
|
||||
import { BucketDropdown, PlanDropdown } from '../common/properties';
|
||||
|
||||
export const deleteBucket = createAction({
|
||||
auth: microsoft365PlannerAuth,
|
||||
name: 'deleteBucket',
|
||||
displayName: 'Delete Bucket',
|
||||
description: 'Delete an existing bucket.',
|
||||
props: {
|
||||
planId: PlanDropdown({ required: true }),
|
||||
id: BucketDropdown({ required: true }),
|
||||
},
|
||||
async run({ auth, propsValue: { id } }) {
|
||||
if (!id) {
|
||||
throw new Error('Bucket id is required');
|
||||
}
|
||||
return await microsoft365PlannerCommon.deleteBucket({
|
||||
auth,
|
||||
id,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { microsoft365PlannerAuth, microsoft365PlannerCommon } from '../common';
|
||||
import { PlanDropdown, TaskDropdown } from '../common/properties';
|
||||
|
||||
export const deleteTask = createAction({
|
||||
auth: microsoft365PlannerAuth,
|
||||
name: 'deleteTask',
|
||||
displayName: 'Delete Task',
|
||||
description: 'Remove a specific task by ID.',
|
||||
props: {
|
||||
planId: PlanDropdown({ required: true }),
|
||||
id: TaskDropdown({ required: true }),
|
||||
},
|
||||
async run({ auth, propsValue: { id } }) {
|
||||
if (!id) {
|
||||
throw new Error('Task id is required');
|
||||
}
|
||||
return await microsoft365PlannerCommon.deleteTask({
|
||||
auth,
|
||||
id,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { microsoft365PlannerAuth, microsoft365PlannerCommon } from '../common';
|
||||
|
||||
export const findAPlan = createAction({
|
||||
auth: microsoft365PlannerAuth,
|
||||
name: 'findAPlan',
|
||||
displayName: 'Find a Plan',
|
||||
description: 'Finds a plan by field.',
|
||||
props: {
|
||||
title: Property.ShortText({
|
||||
displayName: 'Title',
|
||||
description: 'The title of the plan to search for',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
async run({ auth, propsValue: { title } }) {
|
||||
const plans = await microsoft365PlannerCommon.listPlans({ auth });
|
||||
return plans.filter(
|
||||
(plan) =>
|
||||
plan.title && plan.title.toLowerCase().includes(title.toLowerCase())
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { microsoft365PlannerAuth, microsoft365PlannerCommon } from '../common';
|
||||
import { PlanDropdown } from '../common/properties';
|
||||
|
||||
export const findTask = createAction({
|
||||
auth: microsoft365PlannerAuth,
|
||||
name: 'findTask',
|
||||
displayName: 'Find Task',
|
||||
description: 'Find task by fields.',
|
||||
props: {
|
||||
planId: PlanDropdown({ required: true }),
|
||||
title: Property.ShortText({
|
||||
displayName: 'Title',
|
||||
description: 'The title of the task to search for',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
async run({ auth, propsValue: { title, planId } }) {
|
||||
if (!planId) {
|
||||
throw new Error('Plan ID is required to fetch tasks.');
|
||||
}
|
||||
const tasks = await microsoft365PlannerCommon.listTasks({ auth, planId });
|
||||
return tasks.filter(
|
||||
(task) =>
|
||||
task.title && task.title.toLowerCase().includes(title.toLowerCase())
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { microsoft365PlannerAuth, microsoft365PlannerCommon } from '../common';
|
||||
import { BucketDropdown, PlanDropdown } from '../common/properties';
|
||||
|
||||
export const getABucket = createAction({
|
||||
auth: microsoft365PlannerAuth,
|
||||
name: 'getABucket',
|
||||
displayName: 'Get a Bucket',
|
||||
description: 'Retrieve details about a specific bucket.',
|
||||
props: {
|
||||
planId: PlanDropdown({ required: true }),
|
||||
bucketId: BucketDropdown({ required: true }),
|
||||
},
|
||||
async run({ auth, propsValue: { bucketId } }) {
|
||||
if (!bucketId) {
|
||||
throw new Error('Bucket ID is required to fetch bucket details.');
|
||||
}
|
||||
return await microsoft365PlannerCommon.getBucketDetails({
|
||||
auth,
|
||||
bucketId,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { microsoft365PlannerAuth, microsoft365PlannerCommon } from '../common';
|
||||
import {
|
||||
BucketDropdown,
|
||||
OrderHintProperty,
|
||||
PlanDropdown,
|
||||
} from '../common/properties';
|
||||
|
||||
export const updateBucket = createAction({
|
||||
auth: microsoft365PlannerAuth,
|
||||
name: 'updateBucket',
|
||||
displayName: 'Update Bucket',
|
||||
description: 'Modify bucket’s name or properties.',
|
||||
props: {
|
||||
planId: PlanDropdown({ required: true }),
|
||||
id: BucketDropdown({ required: true }),
|
||||
name: Property.ShortText({
|
||||
displayName: 'Name',
|
||||
description: 'The new name of the bucket',
|
||||
required: false,
|
||||
}),
|
||||
orderHint: OrderHintProperty({ required: false }),
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const { planId, id, ...updateParams } = propsValue;
|
||||
if (!id) {
|
||||
throw new Error('Bucket ID is required to update a bucket.');
|
||||
}
|
||||
return await microsoft365PlannerCommon.updateBucket({
|
||||
auth,
|
||||
id,
|
||||
...updateParams,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { microsoft365PlannerAuth, microsoft365PlannerCommon } from '../common';
|
||||
import { PlanDropdown } from '../common/properties';
|
||||
|
||||
export const updatePlan = createAction({
|
||||
auth: microsoft365PlannerAuth,
|
||||
name: 'updatePlan',
|
||||
displayName: 'Update Plan',
|
||||
description: 'modify metadata of a plan (e.g. title changes).',
|
||||
props: {
|
||||
id: PlanDropdown({ required: true }),
|
||||
title: Property.ShortText({
|
||||
displayName: 'Title',
|
||||
description: 'The new title of the plan',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
async run({ auth, propsValue: { id, title } }) {
|
||||
if (!id) {
|
||||
throw new Error('Plan id is required');
|
||||
}
|
||||
return await microsoft365PlannerCommon.updatePlan({
|
||||
auth,
|
||||
id,
|
||||
title,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
import {
|
||||
createAction,
|
||||
OAuth2PropertyValue,
|
||||
Property,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { microsoft365PlannerAuth, microsoft365PlannerCommon } from '../common';
|
||||
import { PlanDropdown, TaskDropdown } from '../common/properties';
|
||||
|
||||
export const updateTask = createAction({
|
||||
auth: microsoft365PlannerAuth,
|
||||
name: 'updateTask',
|
||||
displayName: 'Update Task',
|
||||
description:
|
||||
'Modify existing task fields: title, due date, assignments, descriptions.',
|
||||
props: {
|
||||
planId: PlanDropdown({ required: true }),
|
||||
id: TaskDropdown({ required: true }),
|
||||
title: Property.ShortText({
|
||||
displayName: 'Title',
|
||||
description: 'The new title of the task',
|
||||
required: false,
|
||||
}),
|
||||
assignments: Property.MultiSelectDropdown({
|
||||
displayName: 'Assignments',
|
||||
description:
|
||||
'Select users to assign the task to. If left empty, the task will be unassigned.',
|
||||
required: false,
|
||||
refreshers: ['auth'],
|
||||
auth: microsoft365PlannerAuth,
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
options: [],
|
||||
disabled: true,
|
||||
placeholder: 'Please select an authentication first',
|
||||
};
|
||||
}
|
||||
const users = await microsoft365PlannerCommon.listUsers({ auth: auth });
|
||||
return {
|
||||
options: users.map((user) => ({
|
||||
label: user.displayName || user.userPrincipalName || 'No Name',
|
||||
value: user.id || '',
|
||||
})),
|
||||
disabled: false,
|
||||
placeholder: 'Select users to assign the task to',
|
||||
};
|
||||
},
|
||||
}),
|
||||
dueDateTime: Property.DateTime({
|
||||
displayName: 'Due Date',
|
||||
description: 'The due date and time for the task',
|
||||
required: false,
|
||||
}),
|
||||
percentComplete: Property.Number({
|
||||
displayName: 'Percent Complete',
|
||||
description: 'The completion percentage of the task (0-100)',
|
||||
required: false,
|
||||
}),
|
||||
priority: Property.Number({
|
||||
displayName: 'Priority',
|
||||
description:
|
||||
'The priority of the task between 0 and 10, with the increasing value being lower priority (0 has the highest priority and 10 has the lowest priority).',
|
||||
required: false,
|
||||
}),
|
||||
startDateTime: Property.DateTime({
|
||||
displayName: 'Start Date',
|
||||
description: 'The start date and time for the task',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const { planId, id, ...updateParams } = propsValue;
|
||||
if (!id) {
|
||||
throw new Error('Task ID is required to update a task.');
|
||||
}
|
||||
const formattedParams = {
|
||||
...updateParams,
|
||||
assignments: updateParams.assignments
|
||||
? Object.fromEntries(
|
||||
updateParams.assignments.map((userId) => [
|
||||
userId,
|
||||
{ '@odata.type': 'microsoft.graph.plannerAssignment' },
|
||||
])
|
||||
)
|
||||
: undefined,
|
||||
};
|
||||
return await microsoft365PlannerCommon.updateTask({
|
||||
auth,
|
||||
id,
|
||||
...formattedParams,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,213 @@
|
||||
import { PieceAuth } from '@activepieces/pieces-framework';
|
||||
import { Client } from '@microsoft/microsoft-graph-client';
|
||||
import { PlannerBucket } from '@microsoft/microsoft-graph-types';
|
||||
import {
|
||||
AuthenticationParams,
|
||||
CreateBucketParams,
|
||||
CreateBucketResponse,
|
||||
CreatePlanParams,
|
||||
CreatePlanResponse,
|
||||
CreateTaskParams,
|
||||
CreateTaskResponse,
|
||||
DeleteBucketParams,
|
||||
DeleteTaskParams,
|
||||
GetBucketDetailsParams,
|
||||
GetUserResponse,
|
||||
ListBucketsParams,
|
||||
ListBucketsResponse,
|
||||
ListGroupsResponse,
|
||||
ListPlansResponse,
|
||||
ListTasksParams,
|
||||
ListTasksResponse,
|
||||
ListUserResponse,
|
||||
UpdateBucketParams,
|
||||
UpdatePlanParams,
|
||||
UpdateTaskParams,
|
||||
} from './types';
|
||||
|
||||
export const microsoft365PlannerAuth = PieceAuth.OAuth2({
|
||||
authUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
|
||||
tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
|
||||
required: true,
|
||||
scope: ['Tasks.ReadWrite', 'User.Read', 'Group.Read.All'],
|
||||
prompt: 'omit',
|
||||
});
|
||||
|
||||
export const microsoft365PlannerCommon = {
|
||||
endpoints: {
|
||||
createPlan: '/planner/plans',
|
||||
listPlans: '/me/planner/plans',
|
||||
listGroups: '/groups',
|
||||
planDetail: (id: string) => `/planner/plans/${id}`,
|
||||
listBuckets: (planId: string) => `/planner/plans/${planId}/buckets`,
|
||||
listPlanTasks: (planId: string) => `/planner/plans/${planId}/tasks`,
|
||||
createBucket: '/planner/buckets',
|
||||
bucketDetail: (id: string) => `/planner/buckets/${id}`,
|
||||
createTask: '/planner/tasks',
|
||||
deleteTask: (id: string) => `/planner/tasks/${id}`,
|
||||
},
|
||||
getClient: ({ auth }: AuthenticationParams) => {
|
||||
return Client.initWithMiddleware({
|
||||
authProvider: {
|
||||
getAccessToken: async () => {
|
||||
return auth.access_token;
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
getUser: async ({ auth }: AuthenticationParams) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
const user: GetUserResponse = await client.api('/me').get();
|
||||
return user;
|
||||
},
|
||||
getEtag: async ({
|
||||
auth,
|
||||
id,
|
||||
endpointType,
|
||||
}: AuthenticationParams & {
|
||||
id: string;
|
||||
endpointType:
|
||||
| 'planDetail'
|
||||
| 'listBuckets'
|
||||
| 'listPlanTasks'
|
||||
| 'bucketDetail'
|
||||
| 'deleteTask'
|
||||
| 'deleteTask';
|
||||
}) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
const endpointFn = microsoft365PlannerCommon.endpoints[endpointType] as (
|
||||
arg: string
|
||||
) => string;
|
||||
const endpoint = endpointFn(id);
|
||||
const response = await client.api(endpoint).get();
|
||||
return (response as any)['@odata.etag'] as string;
|
||||
},
|
||||
listUsers: async ({ auth }: AuthenticationParams) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
const response: ListUserResponse = await client.api('/users').get();
|
||||
return response.value;
|
||||
},
|
||||
listGroups: async ({ auth }: AuthenticationParams) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
const response: ListGroupsResponse = await client
|
||||
.api(microsoft365PlannerCommon.endpoints.listGroups)
|
||||
.get();
|
||||
return response.value;
|
||||
},
|
||||
listPlans: async ({ auth }: AuthenticationParams) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
const response: ListPlansResponse = await client
|
||||
.api(microsoft365PlannerCommon.endpoints.listPlans)
|
||||
.get();
|
||||
return response.value;
|
||||
},
|
||||
listBuckets: async ({ auth, planId }: ListBucketsParams) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
const response: ListBucketsResponse = await client
|
||||
.api(microsoft365PlannerCommon.endpoints.listBuckets(planId))
|
||||
.get();
|
||||
return response.value;
|
||||
},
|
||||
listTasks: async ({ auth, planId }: ListTasksParams) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
|
||||
const response: ListTasksResponse = await client
|
||||
.api(microsoft365PlannerCommon.endpoints.listPlanTasks(planId))
|
||||
.get();
|
||||
return response.value;
|
||||
},
|
||||
createPlan: async ({ auth, ...planParams }: CreatePlanParams) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
const response: CreatePlanResponse = await client
|
||||
.api(microsoft365PlannerCommon.endpoints.createPlan)
|
||||
.create(planParams);
|
||||
return response;
|
||||
},
|
||||
createBucket: async ({ auth, ...bucketParams }: CreateBucketParams) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
const response: CreateBucketResponse = await client
|
||||
.api(microsoft365PlannerCommon.endpoints.createBucket)
|
||||
.create(bucketParams);
|
||||
return response;
|
||||
},
|
||||
updateBucket: async ({ auth, id, name, orderHint }: UpdateBucketParams) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
const etag = await microsoft365PlannerCommon.getEtag({
|
||||
auth,
|
||||
id,
|
||||
endpointType: 'bucketDetail',
|
||||
});
|
||||
await client
|
||||
.api(microsoft365PlannerCommon.endpoints.bucketDetail(id))
|
||||
.header('If-Match', etag)
|
||||
.update({ name, orderHint });
|
||||
return { success: true };
|
||||
},
|
||||
deleteTask: async ({ auth, id }: DeleteTaskParams) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
const etag = await microsoft365PlannerCommon.getEtag({
|
||||
auth,
|
||||
id,
|
||||
endpointType: 'deleteTask',
|
||||
});
|
||||
await client
|
||||
.api(microsoft365PlannerCommon.endpoints.deleteTask(id))
|
||||
.header('If-Match', etag)
|
||||
.delete();
|
||||
return { success: true };
|
||||
},
|
||||
createTask: async ({ auth, ...taskParams }: CreateTaskParams) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
const response: CreateTaskResponse = await client
|
||||
.api(microsoft365PlannerCommon.endpoints.createTask)
|
||||
.create(taskParams);
|
||||
return response;
|
||||
},
|
||||
updateTask: async ({ auth, id, ...taskParams }: UpdateTaskParams) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
const etag = await microsoft365PlannerCommon.getEtag({
|
||||
auth,
|
||||
id,
|
||||
endpointType: 'deleteTask',
|
||||
});
|
||||
await client
|
||||
.api(microsoft365PlannerCommon.endpoints.deleteTask(id))
|
||||
.header('If-Match', etag)
|
||||
.update(taskParams);
|
||||
return { success: true };
|
||||
},
|
||||
deleteBucket: async ({ auth, id }: DeleteBucketParams) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
const etag = await microsoft365PlannerCommon.getEtag({
|
||||
auth,
|
||||
id,
|
||||
endpointType: 'bucketDetail',
|
||||
});
|
||||
await client
|
||||
.api(microsoft365PlannerCommon.endpoints.bucketDetail(id))
|
||||
.header('If-Match', etag)
|
||||
.delete();
|
||||
return { success: true };
|
||||
},
|
||||
|
||||
updatePlan: async ({ auth, id, title }: UpdatePlanParams) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
const etag = await microsoft365PlannerCommon.getEtag({
|
||||
auth,
|
||||
id,
|
||||
endpointType: 'planDetail',
|
||||
});
|
||||
await client
|
||||
.api(microsoft365PlannerCommon.endpoints.planDetail(id))
|
||||
.header('If-Match', etag)
|
||||
.update({ title });
|
||||
return { success: true };
|
||||
},
|
||||
getBucketDetails: async ({ auth, bucketId }: GetBucketDetailsParams) => {
|
||||
const client = microsoft365PlannerCommon.getClient({ auth });
|
||||
const response: PlannerBucket = await client
|
||||
.api(microsoft365PlannerCommon.endpoints.bucketDetail(bucketId))
|
||||
.get();
|
||||
return response;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,151 @@
|
||||
import { OAuth2PropertyValue, Property } from '@activepieces/pieces-framework';
|
||||
import { microsoft365PlannerAuth, microsoft365PlannerCommon } from '.';
|
||||
|
||||
export const groupDropdown = ({ required = true }) =>
|
||||
Property.Dropdown({
|
||||
auth: microsoft365PlannerAuth,
|
||||
displayName: 'Group',
|
||||
description: 'Select the Grroup',
|
||||
required: required,
|
||||
refreshers: ['auth'],
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
options: [],
|
||||
disabled: true,
|
||||
placeholder: 'Please select an authentication first',
|
||||
};
|
||||
}
|
||||
const groups = await microsoft365PlannerCommon.listGroups({ auth });
|
||||
return {
|
||||
options: groups.map((group) => ({
|
||||
label: group.displayName ?? '',
|
||||
value: group.id ?? '',
|
||||
})),
|
||||
disabled: false,
|
||||
placeholder: 'Select a group',
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const PlanDropdown = ({ required = true }) =>
|
||||
Property.Dropdown({
|
||||
auth: microsoft365PlannerAuth,
|
||||
displayName: 'Plan',
|
||||
description: 'Select the plan',
|
||||
required: required,
|
||||
refreshers: ['auth'],
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
options: [],
|
||||
disabled: true,
|
||||
placeholder: 'Please select an authentication first',
|
||||
};
|
||||
}
|
||||
const plans = await microsoft365PlannerCommon.listPlans({ auth });
|
||||
return {
|
||||
options: plans.map((plan) => ({
|
||||
label: plan.title ?? '',
|
||||
value: plan.id ?? '',
|
||||
})),
|
||||
disabled: false,
|
||||
placeholder: 'Select a plan',
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const BucketDropdown = ({ required = true }) =>
|
||||
Property.Dropdown({
|
||||
auth: microsoft365PlannerAuth,
|
||||
displayName: 'Bucket',
|
||||
description: 'Select the bucket',
|
||||
required: required,
|
||||
refreshers: ['auth', 'planId'],
|
||||
options: async ({
|
||||
auth,
|
||||
planId,
|
||||
}: {
|
||||
auth?: OAuth2PropertyValue | null;
|
||||
planId?: string;
|
||||
}) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
options: [],
|
||||
disabled: true,
|
||||
placeholder: 'Please select an authentication first',
|
||||
};
|
||||
}
|
||||
if (!planId) {
|
||||
return {
|
||||
options: [],
|
||||
disabled: true,
|
||||
placeholder: 'Please select a plan first',
|
||||
};
|
||||
}
|
||||
const buckets = await microsoft365PlannerCommon.listBuckets({
|
||||
auth,
|
||||
planId,
|
||||
});
|
||||
console.log("Buckets:", JSON.stringify(buckets));
|
||||
return {
|
||||
options: buckets.map((bucket) => ({
|
||||
label: bucket.name ?? '',
|
||||
value: bucket.id ?? '',
|
||||
})),
|
||||
disabled: false,
|
||||
placeholder: 'Select a bucket',
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const TaskDropdown = ({ required = true }) =>
|
||||
Property.Dropdown({
|
||||
auth: microsoft365PlannerAuth,
|
||||
displayName: 'Task',
|
||||
description: 'Select the task',
|
||||
required: required,
|
||||
refreshers: ['auth', 'planId'],
|
||||
options: async ({
|
||||
auth,
|
||||
planId,
|
||||
}: {
|
||||
auth?: OAuth2PropertyValue | null;
|
||||
planId?: string;
|
||||
}) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
options: [],
|
||||
disabled: true,
|
||||
placeholder: 'Please select an authentication first',
|
||||
};
|
||||
}
|
||||
if (!planId) {
|
||||
return {
|
||||
options: [],
|
||||
disabled: true,
|
||||
placeholder: 'Please select a plan first',
|
||||
};
|
||||
}
|
||||
const tasks = await microsoft365PlannerCommon.listTasks({
|
||||
auth,
|
||||
planId,
|
||||
});
|
||||
return {
|
||||
options: tasks.map((task) => ({
|
||||
label: task.title ?? '',
|
||||
value: task.id ?? '',
|
||||
})),
|
||||
disabled: false,
|
||||
placeholder: 'Select a task',
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const OrderHintProperty = ({ required = false }) =>
|
||||
Property.ShortText({
|
||||
displayName: 'Order Hint',
|
||||
description:
|
||||
'Hint used to order items of this type in a list. The format is defined as outlined here: https://learn.microsoft.com/en-us/graph/api/resources/planner-order-hint-format?view=graph-rest-1.0',
|
||||
required: required,
|
||||
});
|
||||
@@ -0,0 +1,108 @@
|
||||
import { OAuth2PropertyValue } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
Group,
|
||||
PlannerBucket,
|
||||
PlannerPlan,
|
||||
PlannerPlanContainer,
|
||||
PlannerTask,
|
||||
User
|
||||
} from '@microsoft/microsoft-graph-types';
|
||||
|
||||
export interface AuthenticationParams {
|
||||
auth: OAuth2PropertyValue;
|
||||
}
|
||||
|
||||
export interface GenericDetailParams extends AuthenticationParams {
|
||||
id: string;
|
||||
}
|
||||
|
||||
// API Types
|
||||
export interface ListPlansResponse {
|
||||
value: PlannerPlan[];
|
||||
}
|
||||
|
||||
export interface ListGroupsResponse {
|
||||
value: Group[];
|
||||
}
|
||||
|
||||
export interface ListBucketsParams extends AuthenticationParams {
|
||||
planId: string;
|
||||
}
|
||||
|
||||
export interface ListBucketsResponse {
|
||||
value: PlannerBucket[];
|
||||
}
|
||||
|
||||
export interface ListTasksParams extends AuthenticationParams {
|
||||
planId: string;
|
||||
}
|
||||
|
||||
export interface ListTasksResponse {
|
||||
value: PlannerTask[];
|
||||
}
|
||||
|
||||
export interface CreatePlanParams extends AuthenticationParams {
|
||||
title: string;
|
||||
container: PlannerPlanContainer;
|
||||
}
|
||||
|
||||
export type CreatePlanResponse = PlannerPlan;
|
||||
|
||||
export interface CreateBucketParams
|
||||
extends AuthenticationParams,
|
||||
Omit<PlannerBucket, 'id'> {}
|
||||
|
||||
export type CreateBucketResponse = PlannerBucket;
|
||||
|
||||
export interface CreateTaskParams
|
||||
extends AuthenticationParams,
|
||||
Omit<PlannerTask, 'id'> {}
|
||||
|
||||
export type CreateTaskResponse = PlannerTask;
|
||||
|
||||
export type DeleteBucketParams = GenericDetailParams;
|
||||
|
||||
export type DeleteTaskParams = GenericDetailParams;
|
||||
|
||||
export interface UpdatePlanParams extends AuthenticationParams {
|
||||
id: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export interface UpdateBucketParams extends AuthenticationParams {
|
||||
id: string;
|
||||
name?: string;
|
||||
orderHint?: string;
|
||||
}
|
||||
|
||||
export interface UpdateTaskParams
|
||||
extends AuthenticationParams,
|
||||
Omit<
|
||||
PlannerTask,
|
||||
| 'activeChecklistItemCount'
|
||||
| 'checklistItemCount'
|
||||
| 'completedBy'
|
||||
| 'completedDateTime'
|
||||
| 'createdBy'
|
||||
| 'createdDateTime'
|
||||
| 'hasDescription'
|
||||
| 'planId'
|
||||
| 'previewType'
|
||||
| 'referenceCount'
|
||||
| 'assignedToTaskBoardFormat'
|
||||
| 'bucketTaskBoardFormat'
|
||||
| 'details'
|
||||
| 'progressTaskBoardFormat'
|
||||
> {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface GetBucketDetailsParams extends AuthenticationParams {
|
||||
bucketId: string;
|
||||
}
|
||||
|
||||
export type GetUserResponse = User;
|
||||
|
||||
export interface ListUserResponse {
|
||||
value: User[];
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import {
|
||||
DedupeStrategy,
|
||||
Polling,
|
||||
pollingHelper,
|
||||
} from '@activepieces/pieces-common';
|
||||
import {
|
||||
AppConnectionValueForAuthProperty,
|
||||
createTrigger,
|
||||
PiecePropValueSchema,
|
||||
TriggerStrategy,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import dayjs from 'dayjs';
|
||||
import { microsoft365PlannerAuth, microsoft365PlannerCommon } from '../common';
|
||||
|
||||
const polling: Polling<
|
||||
AppConnectionValueForAuthProperty<typeof microsoft365PlannerAuth>,
|
||||
Record<string, never>
|
||||
> = {
|
||||
strategy: DedupeStrategy.TIMEBASED,
|
||||
items: async ({ auth }) => {
|
||||
const items = await microsoft365PlannerCommon.listPlans({
|
||||
auth,
|
||||
});
|
||||
return items.map((item) => ({
|
||||
epochMilliSeconds: dayjs(item.createdDateTime).valueOf(),
|
||||
data: item,
|
||||
}));
|
||||
},
|
||||
};
|
||||
|
||||
export const newPlanCreated = createTrigger({
|
||||
auth: microsoft365PlannerAuth,
|
||||
name: 'newPlanCreated',
|
||||
displayName: 'New Plan Created',
|
||||
description: 'Triggers when a new Plan is created in Microsoft 365 Planner.',
|
||||
props: {},
|
||||
sampleData: {},
|
||||
type: TriggerStrategy.POLLING,
|
||||
async test(context) {
|
||||
return await pollingHelper.test(polling, context);
|
||||
},
|
||||
async onEnable(context) {
|
||||
const { store, auth, propsValue } = context;
|
||||
await pollingHelper.onEnable(polling, { store, auth, propsValue });
|
||||
},
|
||||
|
||||
async onDisable(context) {
|
||||
const { store, auth, propsValue } = context;
|
||||
await pollingHelper.onDisable(polling, { store, auth, propsValue });
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
return await pollingHelper.poll(polling, context);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,75 @@
|
||||
import {
|
||||
DedupeStrategy,
|
||||
Polling,
|
||||
pollingHelper,
|
||||
} from '@activepieces/pieces-common';
|
||||
import {
|
||||
AppConnectionValueForAuthProperty,
|
||||
createTrigger,
|
||||
PiecePropValueSchema,
|
||||
StaticPropsValue,
|
||||
TriggerStrategy,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import dayjs from 'dayjs';
|
||||
import { microsoft365PlannerAuth, microsoft365PlannerCommon } from '../common';
|
||||
import { PlanDropdown } from '../common/properties';
|
||||
|
||||
const props = {
|
||||
planId: PlanDropdown({ required: true }),
|
||||
};
|
||||
|
||||
const polling: Polling<
|
||||
AppConnectionValueForAuthProperty<typeof microsoft365PlannerAuth>,
|
||||
StaticPropsValue<typeof props>
|
||||
> = {
|
||||
strategy: DedupeStrategy.TIMEBASED,
|
||||
items: async ({ auth, propsValue: { planId } }) => {
|
||||
if (!planId) {
|
||||
return [];
|
||||
}
|
||||
const user = await microsoft365PlannerCommon.getUser({ auth });
|
||||
if (!user || !user.id) {
|
||||
throw new Error('Unable to fetch authenticated user details.');
|
||||
}
|
||||
const items = await microsoft365PlannerCommon.listTasks({ auth, planId });
|
||||
return items
|
||||
.filter((item) => {
|
||||
const userId = String(user.id);
|
||||
return (
|
||||
item.assignments &&
|
||||
Object.prototype.hasOwnProperty.call(item.assignments, userId)
|
||||
);
|
||||
})
|
||||
.map((item) => ({
|
||||
epochMilliSeconds: dayjs(item.createdDateTime).valueOf(),
|
||||
data: item,
|
||||
}));
|
||||
},
|
||||
};
|
||||
|
||||
export const newTaskAssignedToUser = createTrigger({
|
||||
auth: microsoft365PlannerAuth,
|
||||
name: 'newTaskAssignedToUser',
|
||||
displayName: 'New Task Assigned to User',
|
||||
description:
|
||||
'Triggers when a Task is assigned to the authenticated user in Microsoft 365 Planner.',
|
||||
props,
|
||||
sampleData: {},
|
||||
type: TriggerStrategy.POLLING,
|
||||
async test(context) {
|
||||
return await pollingHelper.test(polling, context);
|
||||
},
|
||||
async onEnable(context) {
|
||||
const { store, auth, propsValue } = context;
|
||||
await pollingHelper.onEnable(polling, { store, auth, propsValue });
|
||||
},
|
||||
|
||||
async onDisable(context) {
|
||||
const { store, auth, propsValue } = context;
|
||||
await pollingHelper.onDisable(polling, { store, auth, propsValue });
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
return await pollingHelper.poll(polling, context);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,98 @@
|
||||
import {
|
||||
DedupeStrategy,
|
||||
Polling,
|
||||
pollingHelper,
|
||||
} from '@activepieces/pieces-common';
|
||||
import {
|
||||
AppConnectionValueForAuthProperty,
|
||||
createTrigger,
|
||||
PiecePropValueSchema,
|
||||
StaticPropsValue,
|
||||
TriggerStrategy,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import dayjs from 'dayjs';
|
||||
import { microsoft365PlannerAuth, microsoft365PlannerCommon } from '../common';
|
||||
import { PlanDropdown } from '../common/properties';
|
||||
|
||||
const props = {
|
||||
planId: PlanDropdown({ required: true }),
|
||||
};
|
||||
|
||||
const polling: Polling<
|
||||
AppConnectionValueForAuthProperty<typeof microsoft365PlannerAuth>,
|
||||
StaticPropsValue<typeof props>
|
||||
> = {
|
||||
strategy: DedupeStrategy.TIMEBASED,
|
||||
items: async ({ auth, propsValue: { planId } }) => {
|
||||
if (!planId) {
|
||||
return [];
|
||||
}
|
||||
const items = await microsoft365PlannerCommon.listTasks({
|
||||
auth,
|
||||
planId,
|
||||
});
|
||||
return items.map((item) => ({
|
||||
epochMilliSeconds: dayjs(item.createdDateTime).valueOf(),
|
||||
data: item,
|
||||
}));
|
||||
},
|
||||
};
|
||||
|
||||
export const newTaskCreated = createTrigger({
|
||||
auth: microsoft365PlannerAuth,
|
||||
name: 'newTaskCreated',
|
||||
displayName: 'New Task Created',
|
||||
description: 'Triggers when a new Task is created in Microsoft 365 Planner.',
|
||||
props,
|
||||
sampleData: {
|
||||
'@odata.etag': 'W/"JzEtVGFzayAgQEBAffEBAQEBAQEBARCc="',
|
||||
planId: 's58lztas2UyCXSffEjnlVRgWUAFMLw',
|
||||
bucketId: 'xZ2RCz88uE6BffffftN-0TKffPGUAB-pQ',
|
||||
title: 'test task 123',
|
||||
orderHint: '8584411578775238762',
|
||||
assigneePriority: '',
|
||||
percentComplete: 0,
|
||||
startDateTime: null,
|
||||
createdDateTime: '2025-10-14T13:36:47.953708Z',
|
||||
dueDateTime: null,
|
||||
hasDescription: false,
|
||||
previewType: 'automatic',
|
||||
completedDateTime: null,
|
||||
referenceCount: 0,
|
||||
checklistItemCount: 0,
|
||||
activeChecklistItemCount: 0,
|
||||
conversationThreadId: null,
|
||||
priority: 5,
|
||||
id: 'wvG9lNxhuUO2JuedF9-rimUAFsBA',
|
||||
completedBy: null,
|
||||
createdBy: {
|
||||
user: {
|
||||
displayName: null,
|
||||
id: '90b3720d-f459-42c1-a02e-6471a1ecb068',
|
||||
},
|
||||
application: {
|
||||
displayName: null,
|
||||
id: '5ea0744c-62fa-4a19-99be-99f0869d3182',
|
||||
},
|
||||
},
|
||||
appliedCategories: {},
|
||||
assignments: {},
|
||||
},
|
||||
type: TriggerStrategy.POLLING,
|
||||
async test(context) {
|
||||
return await pollingHelper.test(polling, context);
|
||||
},
|
||||
async onEnable(context) {
|
||||
const { store, auth, propsValue } = context;
|
||||
await pollingHelper.onEnable(polling, { store, auth, propsValue });
|
||||
},
|
||||
|
||||
async onDisable(context) {
|
||||
const { store, auth, propsValue } = context;
|
||||
await pollingHelper.onDisable(polling, { store, auth, propsValue });
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
return await pollingHelper.poll(polling, context);
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user