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,100 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { makeRequest } from '../common';
|
||||
import { kommoAuth } from '../../index';
|
||||
import { userDropdown } from '../common/props';
|
||||
|
||||
interface KommoCustomFieldValue {
|
||||
field_id?: number;
|
||||
field_code?: string;
|
||||
values: Array<{ value: string | number; enum_id?: number }>;
|
||||
}
|
||||
|
||||
export const createContactAction = createAction({
|
||||
auth: kommoAuth,
|
||||
name: 'create_contact',
|
||||
displayName: 'Create New Contact',
|
||||
description: 'Add a new contact.',
|
||||
props: {
|
||||
name: Property.ShortText({
|
||||
displayName: 'Full Name',
|
||||
required: true,
|
||||
}),
|
||||
first_name: Property.ShortText({
|
||||
displayName: 'First Name',
|
||||
required: false,
|
||||
}),
|
||||
last_name: Property.ShortText({
|
||||
displayName: 'Last Name',
|
||||
required: false,
|
||||
}),
|
||||
email: Property.ShortText({
|
||||
displayName: 'Email',
|
||||
required: false,
|
||||
}),
|
||||
phone: Property.ShortText({
|
||||
displayName: 'Phone',
|
||||
required: false,
|
||||
}),
|
||||
responsible_user_id: userDropdown(),
|
||||
tags_to_add: Property.Array({
|
||||
displayName: 'Tags to Add',
|
||||
required: false,
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const {
|
||||
name,
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone,
|
||||
responsible_user_id,
|
||||
} = context.propsValue;
|
||||
const tagsToAdd = context.propsValue.tags_to_add ?? [];
|
||||
|
||||
|
||||
const { subdomain, apiToken } = context.auth.props
|
||||
|
||||
const customFields: KommoCustomFieldValue[] = [];
|
||||
|
||||
if (email) {
|
||||
customFields.push({
|
||||
field_code: 'EMAIL',
|
||||
values: [{ value: email }],
|
||||
});
|
||||
}
|
||||
|
||||
if (phone) {
|
||||
customFields.push({
|
||||
field_code: 'PHONE',
|
||||
values: [{ value: phone }],
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const contactPayload: Record<string, any> = {
|
||||
...(customFields.length > 0 ? { custom_fields_values: customFields } : {}),
|
||||
};
|
||||
|
||||
|
||||
if (name) contactPayload['name'] = name;
|
||||
if (first_name) contactPayload['first_name'] = first_name;
|
||||
if (last_name) contactPayload['last_name'] = last_name;
|
||||
if (responsible_user_id) contactPayload['responsible_user_id'] = responsible_user_id;
|
||||
|
||||
|
||||
if (tagsToAdd.length > 0) {
|
||||
contactPayload['tags_to_add'] = tagsToAdd.map((tag) => ({ name: tag }))
|
||||
}
|
||||
|
||||
const result = await makeRequest(
|
||||
{ apiToken, subdomain },
|
||||
HttpMethod.POST,
|
||||
`/contacts`,
|
||||
[contactPayload]
|
||||
);
|
||||
|
||||
return result;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { makeRequest } from '../common';
|
||||
import { kommoAuth } from '../../index';
|
||||
import {
|
||||
pipelineDropdown,
|
||||
statusDropdown,
|
||||
userDropdown,
|
||||
lossReasonDropdown,
|
||||
} from '../common/props';
|
||||
|
||||
export const createLeadAction = createAction({
|
||||
auth: kommoAuth,
|
||||
name: 'create_lead',
|
||||
displayName: 'Create New Lead',
|
||||
description: 'Creates a new lead.',
|
||||
props: {
|
||||
name: Property.ShortText({
|
||||
displayName: 'Lead Name',
|
||||
required: true,
|
||||
}),
|
||||
price: Property.Number({
|
||||
displayName: 'Price',
|
||||
required: false,
|
||||
}),
|
||||
pipelineId: pipelineDropdown(true),
|
||||
statusId: statusDropdown(true),
|
||||
responsible_user_id: userDropdown(),
|
||||
loss_reason_id: lossReasonDropdown(),
|
||||
tags_to_add: Property.Array({
|
||||
displayName: 'Tags to Add',
|
||||
description: 'List of tags to add.',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run(context) {
|
||||
const { name, price, statusId, pipelineId, loss_reason_id, responsible_user_id } =
|
||||
context.propsValue;
|
||||
|
||||
const tagsToAdd = context.propsValue.tags_to_add ?? [];
|
||||
|
||||
const { apiToken, subdomain } = context.auth.props;
|
||||
|
||||
const body: Record<string, unknown> = {
|
||||
name,
|
||||
};
|
||||
|
||||
if (price) body['price'] = price;
|
||||
if (statusId) body['status_id'] = statusId;
|
||||
if (pipelineId) body['pipeline_id'] = pipelineId;
|
||||
if (loss_reason_id) body['loss_reason_id'] = loss_reason_id;
|
||||
if (responsible_user_id) body['responsible_user_id'] = responsible_user_id;
|
||||
|
||||
if (tagsToAdd.length > 0) {
|
||||
body['tags_to_add'] = tagsToAdd.map((tag) => ({ name: tag }));
|
||||
}
|
||||
|
||||
const response = await makeRequest({ apiToken, subdomain }, HttpMethod.POST, '/leads', [body]);
|
||||
|
||||
return response;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { makeRequest } from '../common';
|
||||
import { kommoAuth } from '../../index';
|
||||
|
||||
export const findCompanyAction = createAction({
|
||||
auth: kommoAuth,
|
||||
name: 'find_company',
|
||||
displayName: 'Find Company',
|
||||
description: 'Find an existing company.',
|
||||
props: {
|
||||
query: Property.ShortText({
|
||||
displayName: 'Query',
|
||||
required: true,
|
||||
description: 'Search query (Searches through the filled fields of the company).'
|
||||
}),
|
||||
},
|
||||
async run(context) {
|
||||
const { query } = context.propsValue;
|
||||
const { subdomain, apiToken } = context.auth.props
|
||||
|
||||
const result = await makeRequest(
|
||||
{ apiToken, subdomain },
|
||||
HttpMethod.GET,
|
||||
`/companies?query=${encodeURIComponent(query || '')}`
|
||||
);
|
||||
|
||||
const companies = result?._embedded?.companies ?? [];
|
||||
|
||||
return {
|
||||
found: companies.length > 0,
|
||||
result: companies
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { kommoAuth } from '../../index';
|
||||
import { makeRequest } from '../common';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
|
||||
export const findContactAction = createAction({
|
||||
auth: kommoAuth,
|
||||
name: 'find_contact',
|
||||
displayName: 'Find Contact',
|
||||
description: 'Finds an existing contact.',
|
||||
props: {
|
||||
query: Property.ShortText({
|
||||
displayName: 'Query',
|
||||
required: true,
|
||||
description: 'Search query (Searches through the filled fields of the contact).'
|
||||
}),
|
||||
},
|
||||
async run(context) {
|
||||
const { query } = context.propsValue;
|
||||
const { subdomain, apiToken } = context.auth.props
|
||||
|
||||
const result = await makeRequest(
|
||||
{ apiToken, subdomain },
|
||||
HttpMethod.GET,
|
||||
`/contacts?query=${encodeURIComponent(query)}`
|
||||
);
|
||||
|
||||
const contacts = result?._embedded?.contacts ?? [];
|
||||
|
||||
return {
|
||||
found: contacts.length > 0,
|
||||
result: contacts
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { makeRequest } from '../common';
|
||||
import { kommoAuth } from '../../index';
|
||||
|
||||
export const findLeadAction = createAction({
|
||||
auth: kommoAuth,
|
||||
name: 'find_lead',
|
||||
displayName: 'Find Lead',
|
||||
description: "Finds an existing lead.",
|
||||
props: {
|
||||
query: Property.ShortText({
|
||||
displayName: 'Query',
|
||||
required: true,
|
||||
description: 'Search query (Searches through the filled fields of the lead).'
|
||||
}),
|
||||
},
|
||||
async run(context) {
|
||||
const { subdomain, apiToken } = context.auth.props
|
||||
|
||||
const result = await makeRequest(
|
||||
{ apiToken, subdomain },
|
||||
HttpMethod.GET,
|
||||
`/leads?query=${encodeURIComponent(context.propsValue.query)}`
|
||||
);
|
||||
|
||||
const leads = result?._embedded?.leads ?? [];
|
||||
|
||||
return {
|
||||
found: leads.length > 0,
|
||||
result: leads
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
import { findLeadAction } from './find-lead';
|
||||
import { updateContactAction } from './update-contact';
|
||||
import { createLeadAction } from './create-new-lead';
|
||||
import { createContactAction } from './create-new-contact';
|
||||
import { findContactAction } from './find-contact';
|
||||
import { findCompanyAction } from './find-company';
|
||||
import { updateLeadAction } from './update-lead'
|
||||
|
||||
export { findLeadAction, updateContactAction, createLeadAction, createContactAction, findContactAction, findCompanyAction, updateLeadAction };
|
||||
@@ -0,0 +1,110 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { kommoAuth } from '../../index';
|
||||
import { makeRequest } from '../common';
|
||||
import { contactDropdown, userDropdown } from '../common/props';
|
||||
|
||||
interface KommoCustomFieldValue {
|
||||
field_id?: number;
|
||||
field_code?: string;
|
||||
values: Array<{ value: string | number; enum_id?: number }>;
|
||||
}
|
||||
|
||||
export const updateContactAction = createAction({
|
||||
auth: kommoAuth,
|
||||
name: 'update_contact',
|
||||
displayName: 'Update Contact',
|
||||
description: 'Updates an existing contact.',
|
||||
props: {
|
||||
contactId: contactDropdown,
|
||||
name: Property.ShortText({
|
||||
displayName: 'Full Name',
|
||||
required: false,
|
||||
}),
|
||||
first_name: Property.ShortText({
|
||||
displayName: 'First Name',
|
||||
required: false,
|
||||
}),
|
||||
last_name: Property.ShortText({
|
||||
displayName: 'Last Name',
|
||||
required: false,
|
||||
}),
|
||||
email: Property.ShortText({
|
||||
displayName: 'Email',
|
||||
required: false,
|
||||
}),
|
||||
phone: Property.ShortText({
|
||||
displayName: 'Phone',
|
||||
required: false,
|
||||
}),
|
||||
responsible_user_id: userDropdown(),
|
||||
tags_to_add: Property.Array({
|
||||
displayName: 'Tags to Add',
|
||||
description: 'List of tag names or IDs to add.',
|
||||
required: false,
|
||||
}),
|
||||
tags_to_delete: Property.Array({
|
||||
displayName: 'Tags to Delete',
|
||||
description: 'List of tag names or IDs to remove.',
|
||||
required: false,
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const {
|
||||
contactId,
|
||||
name,
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone,
|
||||
responsible_user_id,
|
||||
} = context.propsValue;
|
||||
|
||||
const tagsToAdd = context.propsValue.tags_to_add ?? [];
|
||||
const tagsToDelete = context.propsValue.tags_to_delete ?? [];
|
||||
|
||||
const { subdomain, apiToken } = context.auth.props;
|
||||
|
||||
const customFields: KommoCustomFieldValue[] = [];
|
||||
|
||||
if (email) {
|
||||
customFields.push({
|
||||
field_code: 'EMAIL',
|
||||
values: [{ value: email }],
|
||||
});
|
||||
}
|
||||
|
||||
if (phone) {
|
||||
customFields.push({
|
||||
field_code: 'PHONE',
|
||||
values: [{ value: phone }],
|
||||
});
|
||||
}
|
||||
|
||||
const updatePayload: Record<string, any> = {
|
||||
...(customFields.length > 0 ? { custom_fields_values: customFields } : {}),
|
||||
};
|
||||
|
||||
if (name) updatePayload['name'] = name;
|
||||
if (first_name) updatePayload['first_name'] = first_name;
|
||||
if (last_name) updatePayload['last_name'] = last_name;
|
||||
if (responsible_user_id) updatePayload['responsible_user_id'] = responsible_user_id;
|
||||
|
||||
if (tagsToAdd.length > 0) {
|
||||
updatePayload['tags_to_add'] = tagsToAdd.map((tag) => ({ name: tag }))
|
||||
}
|
||||
|
||||
if (tagsToDelete.length > 0) {
|
||||
updatePayload['tags_to_delete'] = tagsToDelete.map((tag) => ({ name: tag }))
|
||||
}
|
||||
|
||||
const result = await makeRequest(
|
||||
{ subdomain, apiToken },
|
||||
HttpMethod.PATCH,
|
||||
`/contacts/${contactId}`,
|
||||
updatePayload
|
||||
);
|
||||
|
||||
return result;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,78 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { makeRequest } from '../common';
|
||||
import { kommoAuth } from '../../index';
|
||||
import { pipelineDropdown, statusDropdown, userDropdown, lossReasonDropdown, leadDropdown } from '../common/props';
|
||||
|
||||
export const updateLeadAction = createAction({
|
||||
auth: kommoAuth,
|
||||
name: 'update_lead',
|
||||
displayName: 'Update Lead',
|
||||
description: 'Update existing lead info.',
|
||||
props: {
|
||||
leadId: leadDropdown,
|
||||
name: Property.ShortText({
|
||||
displayName: 'Name',
|
||||
required: false,
|
||||
}),
|
||||
price: Property.Number({
|
||||
displayName: 'Price',
|
||||
required: false,
|
||||
}),
|
||||
pipelineId: pipelineDropdown(false),
|
||||
statusId: statusDropdown(false),
|
||||
responsible_user_id: userDropdown(false),
|
||||
loss_reason_id: lossReasonDropdown(false),
|
||||
tags_to_add: Property.Array({
|
||||
displayName: 'Tags to Add',
|
||||
required: false,
|
||||
}),
|
||||
tags_to_delete: Property.Array({
|
||||
displayName: 'Tags to Delete',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run(context) {
|
||||
const {
|
||||
leadId,
|
||||
name,
|
||||
price,
|
||||
statusId,
|
||||
pipelineId,
|
||||
responsible_user_id,
|
||||
loss_reason_id,
|
||||
} = context.propsValue;
|
||||
|
||||
const tagsToAdd = context.propsValue.tags_to_add ?? [];
|
||||
const tagsToDelete = context.propsValue.tags_to_delete ?? [];
|
||||
|
||||
|
||||
const { subdomain, apiToken } = context.auth.props;
|
||||
|
||||
const updatePayload: Record<string, any> = {};
|
||||
|
||||
if (name) updatePayload['name'] = name;
|
||||
if (price) updatePayload['price'] = price;
|
||||
if (statusId) updatePayload['status_id'] = statusId;
|
||||
if (pipelineId) updatePayload['pipeline_id'] = pipelineId;
|
||||
if (loss_reason_id) updatePayload['loss_reason_id'] = loss_reason_id;
|
||||
if (responsible_user_id) updatePayload['responsible_user_id'] = responsible_user_id;
|
||||
|
||||
if (tagsToAdd.length > 0) {
|
||||
updatePayload['tags_to_add'] = tagsToAdd.map((tag) => ({ name: tag }))
|
||||
}
|
||||
|
||||
if (tagsToDelete.length > 0) {
|
||||
updatePayload['tags_to_delete'] = tagsToDelete.map((tag) => ({ name: tag }))
|
||||
}
|
||||
|
||||
const result = await makeRequest(
|
||||
{ apiToken, subdomain },
|
||||
HttpMethod.PATCH,
|
||||
`/leads/${leadId}`,
|
||||
updatePayload
|
||||
);
|
||||
|
||||
return result;
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user