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,34 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { addAnnotation } from '../api';
import { matomoAuth } from '../auth';
export const addAnnotationAction = createAction({
name: 'add_annotation',
auth: matomoAuth,
displayName: 'Add Annotation',
description: 'Add an annotation to a Matomo site',
props: {
note: Property.ShortText({
displayName: 'Note',
description: 'The note to add',
required: true,
}),
date: Property.DateTime({
displayName: 'Date',
description: 'The date to add the note to. Format: YYYY-MM-DD',
required: true,
}),
starred: Property.Checkbox({
displayName: 'Starred',
description: 'Whether or not the note should be starred',
required: true,
}),
},
async run(context) {
return await addAnnotation(context.auth.props, {
note: context.propsValue.note,
date: context.propsValue.date,
starred: context.propsValue.starred ? '1' : '0',
});
},
});

View File

@@ -0,0 +1,54 @@
import {
httpClient,
HttpMethod,
HttpRequest,
QueryParams,
} from '@activepieces/pieces-common';
import { MatomoAuthType } from './auth';
const matomoAPI = async (
api : string,
auth : MatomoAuthType,
queryParams : QueryParams = {}
) => {
queryParams['module'] = 'API';
queryParams['format'] = 'JSON';
queryParams['method'] = api;
queryParams['idSite'] = auth.siteId;
const formData = new FormData();
formData.append('token_auth', auth.tokenAuth);
const request: HttpRequest = {
method : HttpMethod.POST,
url : `${auth.domain}`,
queryParams : queryParams,
body : formData,
headers : {
'Content-Type': 'multipart/form-data',
},
};
const response = await httpClient.sendRequest(request);
if (
response.status !== 200 ||
(response.body['result'] && response.body['result'] === 'error')
) {
throw new Error(`Matomo API request failed: ${response.body['message']}`);
}
return {
success: true,
data: response.body,
};
};
export async function getVersion(auth: MatomoAuthType) {
const api = 'API.getMatomoVersion';
return matomoAPI(api, auth);
}
export async function addAnnotation(auth: MatomoAuthType, data: QueryParams) {
const api = 'Annotations.add';
return matomoAPI(api, auth, data);
}

View File

@@ -0,0 +1,75 @@
import {
PieceAuth,
Property,
} from '@activepieces/pieces-framework';
import { z } from 'zod';
import { propsValidation } from '@activepieces/pieces-common';
import { getVersion } from './api';
export type MatomoAuthType = {
tokenAuth: string;
domain: string;
siteId: string;
};
const description = `
Authenticate with Matomo.
Your Matomo domain is the URL of your Matomo account, e.g. https://matomo.example.com
Your Token Auth key can be found in your Matomo account under Settings > API.
Your Site ID can be found in your Matomo account under Administration > Websites.
`;
export const matomoAuth = PieceAuth.CustomAuth({
description: description,
props: {
domain: Property.ShortText({
displayName: 'Matomo Domain',
description:
'The domain of your Matomo account: https://matomo.example.com',
required: true,
}),
tokenAuth: PieceAuth.SecretText({
displayName: 'Token Auth',
description: 'The Token Auth key from your Matomo account',
required: true,
}),
siteId: Property.ShortText({
displayName: 'Site ID',
description:
'The site ID that will be associated to this connection. Site IDs can be found on the main Websites page.',
required: true,
}),
},
validate: async ({ auth }) => {
try {
await validateAuth(auth);
return {
valid: true,
};
} catch (e) {
return {
valid: false,
error: (e as Error)?.message,
};
}
},
required: true,
});
const validateAuth = async (auth: MatomoAuthType) => {
await propsValidation.validateZod(auth, {
domain: z.string().url(),
tokenAuth: z.string().regex(/^[a-zA-Z0-9]+$/),
siteId: z.string().regex(/^[0-9]+$/),
});
const response = await getVersion(auth);
if (response.success !== true) {
throw new Error(
'Authentication failed. Please check your setup and try again.'
);
}
};