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,33 @@
{
"extends": [
"../../../../.eslintrc.base.json"
],
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts",
"*.tsx",
"*.js",
"*.jsx"
],
"rules": {}
},
{
"files": [
"*.ts",
"*.tsx"
],
"rules": {}
},
{
"files": [
"*.js",
"*.jsx"
],
"rules": {}
}
]
}

View File

@@ -0,0 +1,7 @@
# pieces-esignatures
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build pieces-esignatures` to build the library.

View File

@@ -0,0 +1,10 @@
{
"name": "@activepieces/piece-esignatures",
"version": "0.0.1",
"type": "commonjs",
"main": "./src/index.js",
"types": "./src/index.d.ts",
"dependencies": {
"tslib": "^2.3.0"
}
}

View File

@@ -0,0 +1,65 @@
{
"name": "pieces-esignatures",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/pieces/community/esignatures/src",
"projectType": "library",
"release": {
"version": {
"manifestRootsToUpdate": [
"dist/{projectRoot}"
],
"currentVersionResolver": "git-tag",
"fallbackCurrentVersionResolver": "disk"
}
},
"tags": [],
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/packages/pieces/community/esignatures",
"tsConfig": "packages/pieces/community/esignatures/tsconfig.lib.json",
"packageJson": "packages/pieces/community/esignatures/package.json",
"main": "packages/pieces/community/esignatures/src/index.ts",
"assets": [
"packages/pieces/community/esignatures/*.md",
{
"input": "packages/pieces/community/esignatures/src/i18n",
"output": "./src/i18n",
"glob": "**/!(i18n.json)"
}
],
"buildableProjectDepsInPackageJsonType": "dependencies",
"updateBuildableProjectDepsInPackageJson": true
},
"dependsOn": [
"prebuild",
"^build"
]
},
"nx-release-publish": {
"options": {
"packageRoot": "dist/{projectRoot}"
}
},
"prebuild": {
"dependsOn": [
"^build"
],
"executor": "nx:run-commands",
"options": {
"cwd": "packages/pieces/community/esignatures",
"command": "bun install --no-save --silent"
}
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": [
"{options.outputFile}"
]
}
}
}

View File

@@ -0,0 +1,28 @@
import { createPiece } from '@activepieces/pieces-framework';
import { esignaturesAuth } from './lib/common/auth';
import { PieceCategory } from '@activepieces/shared';
import { createContract } from './lib/actions/create-contract';
import { createCustomApiCallAction } from '@activepieces/pieces-common';
export const esignatures = createPiece({
displayName: 'eSignatures',
auth: esignaturesAuth,
minimumSupportedRelease: '0.36.1',
logoUrl: 'https://cdn.activepieces.com/pieces/esignatures.png',
authors: ['sanket-a11y'],
categories: [PieceCategory.SALES_AND_CRM],
actions: [
createContract,
createCustomApiCallAction({
baseUrl: () => `https://esignatures.com/api`,
authLocation: 'queryParams',
auth: esignaturesAuth,
authMapping: async (auth) => {
return {
token: `${auth.secret_text}`,
};
},
}),
],
triggers: [],
});

View File

@@ -0,0 +1,131 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { esignaturesAuth } from '../common/auth';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
export const createContract = createAction({
auth: esignaturesAuth,
name: 'createContract',
displayName: 'Create Contract',
description: 'Create a new contract from a template in eSignatures',
props: {
templateId: Property.ShortText({
displayName: 'Template ID',
description: 'The ID of the template to use for the contract',
required: true,
}),
title: Property.ShortText({
displayName: 'Contract Title',
description:
'Unique title for the contract (defaults to template title if not specified)',
required: false,
}),
locale: Property.StaticDropdown({
displayName: 'Language',
description: 'Language setting for the signer page and emails',
required: false,
options: {
disabled: false,
options: [
{ label: 'Czech', value: 'cz' },
{ label: 'Danish', value: 'da' },
{ label: 'German', value: 'de' },
{ label: 'Greek', value: 'el' },
{ label: 'English', value: 'en' },
{ label: 'English (UK)', value: 'en-GB' },
{ label: 'Spanish', value: 'es' },
{ label: 'Finnish', value: 'fi' },
{ label: 'French', value: 'fr' },
{ label: 'Croatian', value: 'hr' },
{ label: 'Hungarian', value: 'hu' },
{ label: 'Indonesian', value: 'id' },
{ label: 'Italian', value: 'it' },
{ label: 'Japanese', value: 'ja' },
{ label: 'Dutch', value: 'nl' },
{ label: 'Norwegian', value: 'no' },
{ label: 'Polish', value: 'pl' },
{ label: 'Portuguese', value: 'pt' },
{ label: 'Romanian', value: 'ro' },
{ label: 'Serbian', value: 'rs' },
{ label: 'Slovak', value: 'sk' },
{ label: 'Slovenian', value: 'sl' },
{ label: 'Swedish', value: 'sv' },
{ label: 'Vietnamese', value: 'vi' },
{ label: 'Chinese (Simplified)', value: 'zh-CN' },
],
},
}),
metadata: Property.ShortText({
displayName: 'Metadata',
description: 'Custom data to attach to the contract',
required: false,
}),
expiresInHours: Property.Number({
displayName: 'Expires In Hours',
description: 'Sets the expiry time (in hours) for the contract',
required: false,
}),
customWebhookUrl: Property.ShortText({
displayName: 'Custom Webhook URL',
description: 'Custom URL for webhook notifications',
required: false,
}),
assignedUserEmail: Property.ShortText({
displayName: 'Assigned User Email',
description: 'Email to assign management of the contract',
required: false,
}),
labels: Property.Array({
displayName: 'Labels',
description: 'Labels to assign to the contract (for grouping)',
required: false,
}),
test: Property.Checkbox({
displayName: 'Test Contract',
description: 'Mark as test/demo contract with no fees charged',
required: false,
}),
saveAsDraft: Property.Checkbox({
displayName: 'Save as Draft',
description: 'Save as draft instead of sending to signers',
required: false,
}),
signers: Property.Array({
displayName: 'Signers',
description:
'List of individuals required to sign (name, email, and/or mobile)',
required: true,
}),
},
async run({ auth, propsValue }) {
const payload: any = {
template_id: propsValue.templateId,
};
if (propsValue.title) payload.title = propsValue.title;
if (propsValue.locale) payload.locale = propsValue.locale;
if (propsValue.metadata) payload.metadata = propsValue.metadata;
if (propsValue.expiresInHours !== undefined)
payload.expires_in_hours = propsValue.expiresInHours.toString();
if (propsValue.customWebhookUrl)
payload.custom_webhook_url = propsValue.customWebhookUrl;
if (propsValue.assignedUserEmail)
payload.assigned_user_email = propsValue.assignedUserEmail;
if (propsValue.labels) payload.labels = propsValue.labels;
if (propsValue.test !== undefined)
payload.test = propsValue.test ? 'yes' : 'no';
if (propsValue.saveAsDraft !== undefined)
payload.save_as_draft = propsValue.saveAsDraft ? 'yes' : 'no';
if (propsValue.signers) payload.signers = propsValue.signers;
const response = await httpClient.sendRequest({
method: HttpMethod.POST,
url: `https://esignatures.com/api/contracts?token=${auth.secret_text}`,
headers: {
'Content-Type': 'application/json',
},
body: payload,
});
return response.body;
},
});

View File

@@ -0,0 +1,7 @@
import { PieceAuth } from '@activepieces/pieces-framework';
export const esignaturesAuth = PieceAuth.SecretText({
displayName: 'API Key',
description: 'Esignatures API Key',
required: true,
});

View File

@@ -0,0 +1,55 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { esignaturesAuth } from '../common/auth';
export const contractSentToASigner = createTrigger({
auth: esignaturesAuth,
name: 'contractSentToASigner',
displayName: 'Contract Sent to a Signer',
description: '',
props: {},
sampleData: {
status: 'contract-sent-to-signer',
data: {
signer: {
id: '386b8eb0-aac5-43ce-aa5e-500d5d548934',
name: 'test',
email: 'test@gmail.com',
mobile: null,
company_name: 'ss',
signing_order: '1',
auto_sign: 'no',
redirect_url: '',
events: [
{
event: 'email_contract_sent',
timestamp: '2025-12-16T10:30:15.390Z',
},
],
},
contract: {
id: '4efd01d4-d82b-438d-be3e-07099b35bebc',
status: 'sent',
title: 'Sample Consulting Agreement',
metadata: '',
labels: [],
source: 'ui',
test: 'yes',
expires_at: '2025-12-30T10:30:12Z',
assigned_user_email: 'test@gmail.com',
},
},
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
// implement webhook creation logic
},
async onDisable(context) {
// implement webhook deletion logic
},
async run(context) {
const body = context.payload.body as any;
if (body.status === 'contract-sent-to-signer') {
return [context.payload.body];
}
return [];
},
});

View File

@@ -0,0 +1,73 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { esignaturesAuth } from '../common/auth';
export const contractSigned = createTrigger({
auth: esignaturesAuth,
name: 'contractSigned',
displayName: 'Contract Signed',
description: 'Triggers when a contract is signed',
props: {},
sampleData: {
status: 'contract-signed',
data: {
contract: {
id: '4efd01d4-d82b-438d-be3e-07099b35bebc',
status: 'signed',
title: 'Sample Consulting Agreement',
metadata: '',
labels: [],
source: 'ui',
test: 'yes',
contract_pdf_url: '',
signers: [
{
id: '386b8eb0-aac5-43ce-aa5e-500d5d548934',
name: 'sanket',
email: 'sanketnannaware21@gmail.com',
mobile: null,
company_name: 'ss',
signing_order: '1',
auto_sign: 'no',
redirect_url: '',
events: [
{
event: 'email_contract_sent',
timestamp: '2025-12-16T10:30:15.390Z',
},
{
event: 'contract_viewed',
timestamp: '2025-12-16T10:30:33.362Z',
remote_ip: '152.59.8.216',
},
{
event: 'sign_contract',
timestamp: '2025-12-16T10:30:43.039Z',
remote_ip: '152.59.8.216',
},
{
event: 'email_final_contract_sent',
timestamp: '2025-12-16T10:30:44.116Z',
},
],
signer_field_values: { 'Signer field 1': '1' },
},
],
finalized_at: '2025-12-16T10:30:43Z',
assigned_user_email: 'test@gmail.com',
},
},
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
// implement webhook creation logic
},
async onDisable(context) {
// implement webhook deletion logic
},
async run(context) {
const body = context.payload.body as any;
if (body.status === 'contract-signed') {
return [context.payload.body];
}
return [];
},
});

View File

@@ -0,0 +1,49 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { esignaturesAuth } from '../common/auth';
export const signatureReceived = createTrigger({
auth: esignaturesAuth,
name: 'signatureReceived',
displayName: 'Signature Received',
description: 'Trigger when a singer has signed the contract',
props: {},
sampleData: {
status: 'signer-signed',
data: {
signer: {
id: '6signer6-9999',
name: 'Sam Signer',
email: 'sam@tenants.com',
mobile: '+12481234567',
company_name: 'ACME Corp',
signing_order: '1',
auto_sign: 'no',
redirect_url: '',
signer_field_values: {
city: 'Boston',
preferred_contact: 'Phone',
},
},
contract: {
id: '1contr11-2222',
title: 'Sample NDA',
metadata: 'ID0001',
source: 'api',
test: 'no',
},
},
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
// implement webhook creation logic
},
async onDisable(context) {
// implement webhook deletion logic
},
async run(context) {
const body = context.payload.body as any;
if (body.status === 'signer-signed') {
return [context.payload.body];
}
return [];
},
});

View File

@@ -0,0 +1,52 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { esignaturesAuth } from '../common/auth';
export const signerDeclined = createTrigger({
auth: esignaturesAuth,
name: 'signerDeclined',
displayName: 'Signer declined',
description: 'Trigger when a signer has declined to sign the contract',
props: {},
sampleData: {
status: 'signer-declined',
data: {
signer: {
id: '6signer6-9999',
name: 'Sam Signer',
email: 'sam@tenants.com',
mobile: '+12481234567',
company_name: 'ACME Corp',
signing_order: '1',
auto_sign: 'no',
redirect_url: '',
events: [
{
event: 'signature_declined',
reason_for_decline: 'Commencement date is 5th of June',
timestamp: '2015-10-22T18:19:35.979',
},
],
},
contract: {
id: '1contr11-2222',
title: 'Sample NDA',
metadata: 'ID0001',
source: 'api',
test: 'no',
},
},
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
// implement webhook creation logic
},
async onDisable(context) {
// implement webhook deletion logic
},
async run(context) {
const body = context.payload.body as any;
if (body.status === 'signer-declined') {
return [context.payload.body];
}
return [];
},
});

View File

@@ -0,0 +1,20 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"importHelpers": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noPropertyAccessFromIndexSignature": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}

View File

@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"include": ["src/**/*.ts"]
}