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:
poduck
2025-12-18 22:59:37 -05:00
parent 9848268d34
commit 3aa7199503
16292 changed files with 1284892 additions and 4708 deletions

View File

@@ -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,
});
},
});

View File

@@ -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 });
},
});

View File

@@ -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,
});
},
});

View File

@@ -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,
});
},
});

View File

@@ -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,
});
},
});

View File

@@ -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())
);
},
});

View File

@@ -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())
);
},
});

View File

@@ -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,
});
},
});

View File

@@ -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 buckets 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,
});
},
});

View File

@@ -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,
});
},
});

View File

@@ -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,
});
},
});

View File

@@ -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;
},
};

View File

@@ -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,
});

View File

@@ -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[];
}

View File

@@ -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);
},
});

View File

@@ -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);
},
});

View File

@@ -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);
},
});