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,71 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
import {
CAPTAIN_DATA_BASE_URL,
captainDataAuth,
CaptainDataAuthType,
} from '../..';
import { workflowProp } from '../common';
export const getJobResults = createAction({
// auth: check https://www.activepieces.com/docs/developers/piece-reference/authentication,
name: 'getJobResults',
displayName: 'Get job results',
description: 'Get all results for a specific job',
auth: captainDataAuth,
props: {
workflow: workflowProp,
job: Property.Dropdown({
auth: captainDataAuth,
displayName: 'Job',
required: true,
refreshers: ['workflow'],
options: async ({ auth, workflow }) => {
if (!auth || !workflow) {
return {
disabled: true,
options: [],
};
}
const response = await httpClient.sendRequest({
url: `${CAPTAIN_DATA_BASE_URL}/workflows/${workflow}/jobs`,
method: HttpMethod.GET,
headers: {
Authorization: `x-api-key ${auth.props.apiKey}`,
'x-project-id': auth.props.projectId,
},
});
return {
disabled: false,
options: response.body.map(
(job: {
uid: string;
name: string;
workflow_name: string;
status: string;
start_time: string;
}) => {
return {
value: job.uid,
label: job.start_time,
};
}
),
};
},
}),
},
async run({ auth, propsValue }) {
// We don't do pagination because Captain Data's API doc does provide details nor even examples :shrug:
const response = await httpClient.sendRequest({
url: `${CAPTAIN_DATA_BASE_URL}/jobs/${propsValue.job}/results`,
method: HttpMethod.GET,
headers: {
Authorization: `x-api-key ${auth.props.apiKey}`,
'x-project-id': auth.props.projectId,
},
});
return response.body;
},
});

View File

@@ -0,0 +1,60 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
import { CAPTAIN_DATA_BASE_URL, captainDataAuth } from '../..';
import { workflowProp } from '../common';
export const launchWorkflow = createAction({
// auth: check https://www.activepieces.com/docs/developers/piece-reference/authentication,
name: 'launchWorkflow',
displayName: 'Launch a workflow',
description: '',
auth: captainDataAuth,
props: {
workflow: workflowProp,
jobName: Property.ShortText({
displayName: 'Job name',
required: false,
}),
inputs: Property.Json({
displayName: 'Inputs',
description: 'Inputs are the starting point of your workflow.',
defaultValue: [],
required: false,
}),
steps: Property.Json({
displayName: 'Steps',
description:
'You need to configure each steps with:\n' +
'- accounts : The identifiers of the accounts you want to use for this step. The accounts indicated must match the integration used in the step (e.g A Linkedin account for a Search Linkedin People Profile step). You can find the UIDs in the "Integrations\' tab on the platform by clicking on a specific account "Action" button (copy account UID).\n' +
'- accounts_rotation_enabled: (Optional) Whether or not you want to enable the Accounts Rotation feature for this step (only certain Linkedin & Outlook automations are applicable for this feature).\n' +
'- parameters: The specific parameters for this given step - (Can be empty but is required)\n' +
'- step_uid: The UID of the step to configure. You can find it in the API Playground, on Captain Data\'s platform by clicking on "view body to schedule".\n.' +
'See https://docs.captaindata.co/#36e905b6-3a31-4bcd-8c6f-0eb6093b5a8a for details',
defaultValue: [],
required: false,
}),
delay: Property.Number({
displayName: 'Delay (seconds)',
required: false,
}),
},
async run({ auth, propsValue }) {
const payload = {
job_name: propsValue.jobName,
inputs: propsValue.inputs,
steps: propsValue.steps,
delay: propsValue.delay,
};
const response = await httpClient.sendRequest({
url: `${CAPTAIN_DATA_BASE_URL}/workflows/${propsValue.workflow}/schedule`,
method: HttpMethod.POST,
headers: {
'Content-Type': 'application/json',
Authorization: `x-api-key ${auth.props.apiKey}`,
'x-project-id': auth.props.projectId,
},
body: JSON.stringify(payload),
});
return response.body;
},
});

View File

@@ -0,0 +1,32 @@
import { Property } from '@activepieces/pieces-framework';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
import { CAPTAIN_DATA_BASE_URL, captainDataAuth } from '..';
export const workflowProp = Property.Dropdown({
auth: captainDataAuth,
displayName: 'Workflow',
required: true,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
};
}
const response = await httpClient.sendRequest({
url: `${CAPTAIN_DATA_BASE_URL}/workflows`,
method: HttpMethod.GET,
headers: {
Authorization: `x-api-key ${auth.props.apiKey}`,
'x-project-id': auth.props.projectId,
},
});
return {
disabled: false,
options: response.body.map((workflow: { uid: string; name: string }) => {
return { label: workflow.name, value: workflow.uid };
}),
};
},
});