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,393 @@
|
||||
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
|
||||
import { PieceAuth, Property } from '@activepieces/pieces-framework';
|
||||
import { OAuth2GrantType } from '@activepieces/shared';
|
||||
import * as properties from './properties';
|
||||
import * as schemas from './schemas';
|
||||
import {
|
||||
AddContactToMailingListParams,
|
||||
AddTagToContactParams,
|
||||
AddUpdateContactParams,
|
||||
AuthorizationParams,
|
||||
CloneCampaignParams,
|
||||
CreateCampaignParams,
|
||||
CreateCampaignResponse,
|
||||
CreateTagParams,
|
||||
ListCampaignParams,
|
||||
ListCampaignResponse,
|
||||
ListContactsParams,
|
||||
ListContactsResponse,
|
||||
ListMailingListsParams,
|
||||
ListMailingListsResponse,
|
||||
ListTagsResponse,
|
||||
ListTopicsResponse,
|
||||
RemoveTagParams,
|
||||
SendCampaignParams,
|
||||
UnsubscribeContactParams,
|
||||
} from './types';
|
||||
|
||||
export const zohoCampaignsAuth = PieceAuth.OAuth2({
|
||||
props: {
|
||||
location: Property.StaticDropdown({
|
||||
displayName: 'Data Center',
|
||||
description: 'The data center location of your Zoho Campaigns account',
|
||||
required: true,
|
||||
options: {
|
||||
options: [
|
||||
{
|
||||
label: 'zoho.com (United States)',
|
||||
value: 'zoho.com',
|
||||
},
|
||||
{
|
||||
label: 'zoho.eu (Europe)',
|
||||
value: 'zoho.eu',
|
||||
},
|
||||
{
|
||||
label: 'zoho.in (India)',
|
||||
value: 'zoho.in',
|
||||
},
|
||||
{
|
||||
label: 'zoho.com.au (Australia)',
|
||||
value: 'zoho.com.au',
|
||||
},
|
||||
{
|
||||
label: 'zoho.jp (Japan)',
|
||||
value: 'zoho.jp',
|
||||
},
|
||||
{
|
||||
label: 'zoho.com.cn (China)',
|
||||
value: 'zoho.com.cn',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
},
|
||||
description: 'Connect your Zoho Campaigns account using OAuth2',
|
||||
grantType: OAuth2GrantType.AUTHORIZATION_CODE,
|
||||
required: true,
|
||||
authUrl: 'https://accounts.{location}/oauth/v2/auth',
|
||||
tokenUrl: 'https://accounts.{location}/oauth/v2/token',
|
||||
scope: ['ZohoCampaigns.campaign.ALL', 'ZohoCampaigns.contact.ALL'],
|
||||
});
|
||||
|
||||
export const zohoCampaignsCommon = {
|
||||
baseUrl: (location = 'zoho.com') => {
|
||||
return `https://campaigns.${location}/api/v1.1`;
|
||||
},
|
||||
endpoints: {
|
||||
createCampaign: '/createCampaign',
|
||||
createTag: '/tag/add',
|
||||
cloneCampaign: '/json/clonecampaign',
|
||||
sendCampaign: '/sendcampaign',
|
||||
addUpdateContact: '/json/listsubscribe',
|
||||
addTagToContact: '/tag/associate',
|
||||
removeTag: '/tag/deassociate',
|
||||
unsubscribeContact: '/json/listunsubscribe',
|
||||
addContactToMailingList: '/addlistsubscribersinbulk',
|
||||
listContacts: '/getlistsubscribers',
|
||||
listCampaigns: '/recentcampaigns',
|
||||
listMailingLists: '/getmailinglists',
|
||||
listTopics: '/topics',
|
||||
listTags: '/tag/getalltags',
|
||||
},
|
||||
baseHeaders: (accessToken: string) => {
|
||||
return {
|
||||
Authorization: `Zoho-oauthtoken ${accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
},
|
||||
baseParams: {
|
||||
resfmt: 'JSON',
|
||||
},
|
||||
|
||||
// Properties
|
||||
createCampaignProperties: properties.createCampaign,
|
||||
cloneCampaignProperties: properties.cloneCampaign,
|
||||
sendCampaignProperties: properties.sendCampaign,
|
||||
addUpdateContactProperties: properties.addUpdateContact,
|
||||
addTagToContactProperties: properties.addTagToContact,
|
||||
removeTagProperties: properties.removeTag,
|
||||
unsubscribeContactProperties: properties.unsubscribeContact,
|
||||
addContactToMailingListProperties: properties.addContactToMailingList,
|
||||
findContactProperties: properties.findContact,
|
||||
findCampaignProperties: properties.findCampaign,
|
||||
newContactProperties: properties.newContact,
|
||||
unsubscribeProperties: properties.unsubscribe,
|
||||
|
||||
// Schemas
|
||||
createCampaignSchema: schemas.createCampaign,
|
||||
cloneCampaignSchema: schemas.cloneCampaign,
|
||||
sendCampaignSchema: schemas.sendCampaign,
|
||||
addUpdateContactSchema: schemas.addUpdateContact,
|
||||
addTagToContactSchema: schemas.addTagToContact,
|
||||
removeTagSchema: schemas.removeTag,
|
||||
unsubscribeContactSchema: schemas.unsubscribeContact,
|
||||
addContactToMailingListSchema: schemas.addContactToMailingList,
|
||||
findContactSchema: schemas.findContact,
|
||||
findCampaignSchema: schemas.findCampaign,
|
||||
|
||||
// Methods
|
||||
createCampaign: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
...campaignParams
|
||||
}: CreateCampaignParams & { location?: string }) => {
|
||||
const {
|
||||
list_details: listDetails,
|
||||
topicId,
|
||||
...restParams
|
||||
} = campaignParams;
|
||||
|
||||
const list_details = JSON.stringify(listDetails);
|
||||
const body = new URLSearchParams({
|
||||
resfmt: 'json',
|
||||
list_details,
|
||||
...restParams,
|
||||
...(topicId && { topicId }),
|
||||
}).toString();
|
||||
const response = await httpClient.sendRequest<CreateCampaignResponse>({
|
||||
method: HttpMethod.POST,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.createCampaign}`,
|
||||
headers: {
|
||||
...zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body,
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
createTag: async ({ accessToken, location = 'zoho.com', tagName }: CreateTagParams & { location?: string }) => {
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.createTag}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
tagName,
|
||||
},
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
cloneCampaign: async ({ accessToken, location = 'zoho.com', campaigninfo }: CloneCampaignParams & { location?: string }) => {
|
||||
const strCampaignInfo = JSON.stringify(campaigninfo);
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.cloneCampaign}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
campaigninfo: strCampaignInfo,
|
||||
},
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
sendCampaign: async ({ accessToken, location = 'zoho.com', campaignkey }: SendCampaignParams & { location?: string }) => {
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.sendCampaign}`,
|
||||
headers: {
|
||||
...zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
campaignkey,
|
||||
},
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
addUpdateContact: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
...contactParams
|
||||
}: AddUpdateContactParams & { location?: string }) => {
|
||||
const {
|
||||
listkey,
|
||||
contactinfo: contactInfoObj,
|
||||
source,
|
||||
topic_id,
|
||||
} = contactParams;
|
||||
const body = new URLSearchParams({
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
listkey,
|
||||
...(source && { source }),
|
||||
...(topic_id && { topic_id }),
|
||||
contactinfo: JSON.stringify(contactInfoObj),
|
||||
}).toString();
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.addUpdateContact}`,
|
||||
headers: {
|
||||
...zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body,
|
||||
});
|
||||
|
||||
return response.body;
|
||||
},
|
||||
addTagToContact: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
...tagParams
|
||||
}: AddTagToContactParams & { location?: string }) => {
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.addTagToContact}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
...tagParams,
|
||||
},
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
removeTag: async ({ accessToken, location = 'zoho.com', ...tagParams }: RemoveTagParams & { location?: string }) => {
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.removeTag}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
...tagParams,
|
||||
},
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
unsubscribeContact: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
...unsubscribeParams
|
||||
}: UnsubscribeContactParams & { location?: string }) => {
|
||||
const {
|
||||
contactinfo: contactInfoObj,
|
||||
listkey,
|
||||
topic_id,
|
||||
} = unsubscribeParams;
|
||||
const body = new URLSearchParams({
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
listkey,
|
||||
...(topic_id && { topic_id }),
|
||||
contactinfo: JSON.stringify(contactInfoObj),
|
||||
}).toString();
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.unsubscribeContact}`,
|
||||
headers: {
|
||||
...zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body,
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
addContactToMailingList: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
...mailingListParams
|
||||
}: AddContactToMailingListParams & { location?: string }) => {
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.addContactToMailingList}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
...mailingListParams,
|
||||
},
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
listContacts: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
listkey,
|
||||
...rest
|
||||
}: ListContactsParams & { location?: string }) => {
|
||||
const { fromindex, range, ...otherParams } = rest;
|
||||
const strFromIndex =
|
||||
typeof fromindex === 'number' ? String(fromindex) : undefined;
|
||||
const strRange = typeof range === 'number' ? String(range) : undefined;
|
||||
const queryParams = {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
listkey,
|
||||
...(fromindex && { fromindex: strFromIndex }),
|
||||
...(range && { range: strRange }),
|
||||
...otherParams,
|
||||
};
|
||||
const response = await httpClient.sendRequest<ListContactsResponse>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.listContacts}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams,
|
||||
});
|
||||
return response.body.list_of_details || [];
|
||||
},
|
||||
listCampaigns: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
...filterParams
|
||||
}: ListCampaignParams & { location?: string }) => {
|
||||
const { fromindex, range, ...otherParams } = filterParams;
|
||||
const strFromIndex =
|
||||
typeof fromindex === 'number' ? String(fromindex) : undefined;
|
||||
const strRange = typeof range === 'number' ? String(range) : undefined;
|
||||
const queryParams = {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
...(fromindex && { fromindex: strFromIndex }),
|
||||
...(range && { range: strRange }),
|
||||
...otherParams,
|
||||
};
|
||||
const response = await httpClient.sendRequest<ListCampaignResponse>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.listCampaigns}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams,
|
||||
});
|
||||
return response.body.recent_campaigns || [];
|
||||
},
|
||||
listMailingLists: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
...filterParams
|
||||
}: ListMailingListsParams & { location?: string }) => {
|
||||
const { fromindex, range, ...otherParams } = filterParams;
|
||||
const strFromIndex =
|
||||
typeof fromindex === 'number' ? String(fromindex) : undefined;
|
||||
const strRange = typeof range === 'number' ? String(range) : undefined;
|
||||
const queryParams = {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
...(fromindex && { fromindex: strFromIndex }),
|
||||
...(range && { range: strRange }),
|
||||
...otherParams,
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest<ListMailingListsResponse>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.listMailingLists}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams,
|
||||
});
|
||||
return response.body.list_of_details || [];
|
||||
},
|
||||
listTopics: async ({ accessToken, location = 'zoho.com' }: AuthorizationParams & { location?: string }) => {
|
||||
const response = await httpClient.sendRequest<ListTopicsResponse>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.listTopics}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
},
|
||||
});
|
||||
return response.body.topicDetails;
|
||||
},
|
||||
listTags: async ({ accessToken, location = 'zoho.com' }: AuthorizationParams & { location?: string }) => {
|
||||
const response = await httpClient.sendRequest<ListTagsResponse>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.listTags}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
},
|
||||
});
|
||||
return response.body.tags;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,471 @@
|
||||
import { PiecePropValueSchema, Property } from '@activepieces/pieces-framework';
|
||||
import { zohoCampaignsAuth, zohoCampaignsCommon } from '.';
|
||||
import { Tag } from './types';
|
||||
|
||||
// Custom Properties
|
||||
const campaignDropdown = () =>
|
||||
Property.Dropdown({
|
||||
auth: zohoCampaignsAuth,
|
||||
displayName: 'Campaign',
|
||||
description: 'Select the campaign',
|
||||
required: true,
|
||||
refreshers: ['auth'],
|
||||
options: async ({ auth }) => {
|
||||
const authValue = auth as PiecePropValueSchema<typeof zohoCampaignsAuth>;
|
||||
const location = authValue.props?.['location'] || 'zoho.com';
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Connect your Zoho Campaigns account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const campaigns = await zohoCampaignsCommon.listCampaigns({
|
||||
accessToken: authValue.access_token,
|
||||
location,
|
||||
});
|
||||
if (campaigns.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No campaigns found',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
options: campaigns.map((campaign) => ({
|
||||
label: campaign.campaign_name,
|
||||
value: campaign.campaign_key,
|
||||
})),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const tagDropdown = ({ required = true }: { required?: boolean }) =>
|
||||
Property.Dropdown({
|
||||
auth: zohoCampaignsAuth,
|
||||
displayName: 'Tag',
|
||||
description: 'Select the tag to associate with the contact',
|
||||
required: required,
|
||||
refreshers: ['auth'],
|
||||
options: async ({
|
||||
auth,
|
||||
}): Promise<{
|
||||
disabled?: boolean;
|
||||
placeholder?: string;
|
||||
options: Array<{ label: string; value: string }>;
|
||||
}> => {
|
||||
const authValue = auth as PiecePropValueSchema<typeof zohoCampaignsAuth>;
|
||||
const location = authValue.props?.['location'] || 'zoho.com';
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Connect your Zoho Campaigns account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const tags = await zohoCampaignsCommon.listTags({
|
||||
accessToken: authValue.access_token,
|
||||
location,
|
||||
});
|
||||
if (!tags || tags.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No tags found',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
const tagOptions = tags.flatMap((tagMap: Tag) =>
|
||||
Object.values(tagMap).map((tag: any) => ({
|
||||
label: tag.tag_name,
|
||||
value: tag.tag_name,
|
||||
}))
|
||||
);
|
||||
|
||||
return {
|
||||
options: tagOptions,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const mailingListDropdown = ({ required = true }) =>
|
||||
Property.Dropdown({
|
||||
auth: zohoCampaignsAuth,
|
||||
displayName: 'Mailing List',
|
||||
description: 'Select the mailing list',
|
||||
required: required,
|
||||
refreshers: ['auth'],
|
||||
options: async ({ auth }) => {
|
||||
const authValue = auth as PiecePropValueSchema<typeof zohoCampaignsAuth>;
|
||||
const location = authValue.props?.['location'] || 'zoho.com';
|
||||
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Connect your Zoho Campaigns account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const mailingLists = await zohoCampaignsCommon.listMailingLists({
|
||||
accessToken: authValue.access_token,
|
||||
location,
|
||||
});
|
||||
if (mailingLists.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No mailing lists found',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
return {
|
||||
options: mailingLists.map((list) => ({
|
||||
label: list.listname,
|
||||
value: list.listkey,
|
||||
})),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const mailingListMultiSelectDropdown = ({ required = true }) =>
|
||||
Property.MultiSelectDropdown({
|
||||
auth: zohoCampaignsAuth,
|
||||
displayName: 'Mailing Lists',
|
||||
description: 'Select the mailing lists',
|
||||
required: required,
|
||||
refreshers: ['auth'],
|
||||
options: async ({ auth }) => {
|
||||
const authValue = auth as PiecePropValueSchema<typeof zohoCampaignsAuth>;
|
||||
const location = authValue.props?.['location'] || 'zoho.com';
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Connect your Zoho Campaigns account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const mailingLists = await zohoCampaignsCommon.listMailingLists({
|
||||
accessToken: authValue.access_token,
|
||||
location,
|
||||
});
|
||||
if (mailingLists.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No mailing lists found',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
return {
|
||||
options: mailingLists.map((list) => ({
|
||||
label: list.listname,
|
||||
value: list.listkey,
|
||||
})),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const topicDropdown = ({ required = true }) =>
|
||||
Property.Dropdown({
|
||||
auth: zohoCampaignsAuth,
|
||||
displayName: 'Topic',
|
||||
description: 'Select the topic',
|
||||
required: required,
|
||||
refreshers: ['auth'],
|
||||
options: async ({ auth }) => {
|
||||
const authValue = auth as PiecePropValueSchema<typeof zohoCampaignsAuth>;
|
||||
const location = authValue.props?.['location'] || 'zoho.com';
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Connect your Zoho Campaigns account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const topics = await zohoCampaignsCommon.listTopics({
|
||||
accessToken: authValue.access_token,
|
||||
location,
|
||||
});
|
||||
if (topics.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No topics found',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
return {
|
||||
options: topics.map((topic) => ({
|
||||
label: topic.topicName,
|
||||
value: topic.topicId,
|
||||
})),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const contactInformation = Property.DynamicProperties({
|
||||
displayName: 'Contact Information',
|
||||
description: 'Information about the contact',
|
||||
required: true,
|
||||
auth: zohoCampaignsAuth,
|
||||
refreshers: ['auth'],
|
||||
props: async () => ({
|
||||
'Contact Email': Property.ShortText({
|
||||
displayName: 'Contact Email',
|
||||
description: 'Email address of the contact',
|
||||
required: true,
|
||||
}),
|
||||
'First Name': Property.ShortText({
|
||||
displayName: 'First Name',
|
||||
description: 'First name of the contact',
|
||||
required: false,
|
||||
}),
|
||||
'Last Name': Property.ShortText({
|
||||
displayName: 'Last Name',
|
||||
description: 'Last name of the contact',
|
||||
required: false,
|
||||
}),
|
||||
Phone: Property.ShortText({
|
||||
displayName: 'Phone',
|
||||
description: 'Phone number of the contact',
|
||||
required: false,
|
||||
}),
|
||||
'Company Name': Property.ShortText({
|
||||
displayName: 'Company Name',
|
||||
description: 'Company name of the contact',
|
||||
required: false,
|
||||
}),
|
||||
additionalFields: Property.Object({
|
||||
displayName: 'Additional Fields',
|
||||
description:
|
||||
'Additional fields for the contact in key-value pairs. For example, {"City": "New York", "State": "NY"}',
|
||||
required: false,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
// Action Properties
|
||||
export const createCampaign = () => ({
|
||||
campaignname: Property.ShortText({
|
||||
displayName: 'Campaign Name',
|
||||
description: 'A name to your campaign',
|
||||
required: true,
|
||||
}),
|
||||
from_email: Property.ShortText({
|
||||
displayName: 'From Email',
|
||||
description: 'Sender email address for the campaign',
|
||||
required: true,
|
||||
}),
|
||||
subject: Property.ShortText({
|
||||
displayName: 'Subject',
|
||||
description: 'The subject line of the campaign',
|
||||
required: true,
|
||||
}),
|
||||
list_details: mailingListMultiSelectDropdown({ required: true }),
|
||||
content_url: Property.ShortText({
|
||||
displayName: 'Content URL',
|
||||
description: 'Public URL containing the HTML content for your campaign',
|
||||
required: false,
|
||||
}),
|
||||
topicId: topicDropdown({ required: false }),
|
||||
});
|
||||
|
||||
export const cloneCampaign = () => ({
|
||||
campaignkey: campaignDropdown(),
|
||||
campaignname: Property.ShortText({
|
||||
displayName: 'Campaign Name',
|
||||
description: 'New name for the cloned campaign',
|
||||
required: false,
|
||||
}),
|
||||
subject: Property.ShortText({
|
||||
displayName: 'Subject',
|
||||
description: 'New subject line for the cloned campaign',
|
||||
required: false,
|
||||
}),
|
||||
from_name: Property.ShortText({
|
||||
displayName: 'From Name',
|
||||
description: 'Sender name for the cloned campaign',
|
||||
required: false,
|
||||
}),
|
||||
from_add: Property.ShortText({
|
||||
displayName: 'From Email',
|
||||
description: 'Sender email address for the cloned campaign',
|
||||
required: false,
|
||||
}),
|
||||
reply_to: Property.ShortText({
|
||||
displayName: 'Reply-To Email',
|
||||
description: 'Reply-to email address for the cloned campaign',
|
||||
required: false,
|
||||
}),
|
||||
encode_type: Property.ShortText({
|
||||
displayName: 'Encoding Type',
|
||||
description: 'Email encoding type (e.g., UTF-8)',
|
||||
required: false,
|
||||
}),
|
||||
});
|
||||
|
||||
export const sendCampaign = () => ({
|
||||
campaignkey: campaignDropdown(),
|
||||
});
|
||||
|
||||
export const addUpdateContact = () => ({
|
||||
listkey: mailingListDropdown({ required: true }),
|
||||
contactinfo: contactInformation,
|
||||
source: Property.ShortText({
|
||||
displayName: 'Source',
|
||||
description: 'Contact source can be added.',
|
||||
required: false,
|
||||
}),
|
||||
topic_id: topicDropdown({ required: false }),
|
||||
});
|
||||
|
||||
export const addTagToContact: {
|
||||
tagName: any;
|
||||
lead_email: any;
|
||||
} = {
|
||||
tagName: tagDropdown({ required: true }),
|
||||
lead_email: Property.ShortText({
|
||||
displayName: 'Contact Email',
|
||||
description: 'Email address of the contact to tag',
|
||||
required: true,
|
||||
}),
|
||||
};
|
||||
|
||||
export const removeTag: {
|
||||
tagName: any;
|
||||
lead_email: any;
|
||||
} = {
|
||||
tagName: tagDropdown({ required: true }),
|
||||
lead_email: Property.ShortText({
|
||||
displayName: 'Contact Email',
|
||||
description: 'Email address of the contact to remove the tag from',
|
||||
required: true,
|
||||
}),
|
||||
};
|
||||
|
||||
export const unsubscribeContact = () => ({
|
||||
listkey: mailingListDropdown({ required: true }),
|
||||
contactinfo: contactInformation,
|
||||
topic_id: topicDropdown({ required: false }),
|
||||
});
|
||||
|
||||
export const addContactToMailingList = () => ({
|
||||
listkey: mailingListDropdown({ required: true }),
|
||||
emails: Property.Array({
|
||||
displayName: 'Emails',
|
||||
description:
|
||||
'Contacts email addresses to be added to the mailing list (maximum 10 emails)',
|
||||
required: true,
|
||||
}),
|
||||
});
|
||||
|
||||
export const findContact = () => ({
|
||||
listkey: mailingListDropdown({ required: true }),
|
||||
contactEmail: Property.ShortText({
|
||||
displayName: 'Contact Email',
|
||||
description: 'Email of the contact to be found (partial matches supported)',
|
||||
required: true,
|
||||
}),
|
||||
status: Property.StaticDropdown({
|
||||
displayName: 'Contact Status',
|
||||
description: 'Filter contacts by status',
|
||||
required: true,
|
||||
options: {
|
||||
options: [
|
||||
{ label: 'Active', value: 'active' },
|
||||
{ label: 'Recent', value: 'recent' },
|
||||
{ label: 'Most Recent', value: 'most recent' },
|
||||
{ label: 'Unsubscribed', value: 'unsub' },
|
||||
{ label: 'Bounced', value: 'bounce' },
|
||||
],
|
||||
},
|
||||
}),
|
||||
sort: Property.StaticDropdown({
|
||||
displayName: 'Sort Order',
|
||||
description: 'Sort order for results',
|
||||
required: true,
|
||||
options: {
|
||||
options: [
|
||||
{ label: 'Ascending', value: 'asc' },
|
||||
{ label: 'Descending', value: 'desc' },
|
||||
],
|
||||
},
|
||||
}),
|
||||
fromindex: Property.Number({
|
||||
displayName: 'From Index',
|
||||
description: 'Starting index for pagination (optional, default: 1)',
|
||||
required: false,
|
||||
}),
|
||||
range: Property.Number({
|
||||
displayName: 'Range',
|
||||
description: 'Number of contacts to retrieve (optional, default: all)',
|
||||
required: false,
|
||||
}),
|
||||
});
|
||||
|
||||
export const findCampaign = () => ({
|
||||
campaignName: Property.ShortText({
|
||||
displayName: 'Campaign Name',
|
||||
description: 'Name of the campaign to be found (partial matches supported)',
|
||||
required: true,
|
||||
}),
|
||||
status: Property.StaticDropdown({
|
||||
displayName: 'Campaign Status',
|
||||
description: 'Filter campaigns by status (optional)',
|
||||
required: false,
|
||||
options: {
|
||||
options: [
|
||||
{ label: 'All', value: 'all' },
|
||||
{ label: 'All Campaigns', value: 'all campaigns' },
|
||||
{ label: 'Drafts', value: 'drafts' },
|
||||
{ label: 'Scheduled', value: 'scheduled' },
|
||||
{ label: 'In Progress', value: 'inprogress' },
|
||||
{ label: 'Sent', value: 'sent' },
|
||||
{ label: 'Stopped', value: 'stopped' },
|
||||
{ label: 'Canceled', value: 'canceled' },
|
||||
{ label: 'To Be Reviewed', value: 'tobereviewed' },
|
||||
{ label: 'Reviewed', value: 'reviewed' },
|
||||
{ label: 'Paused', value: 'paused' },
|
||||
{ label: 'In Testing', value: 'intesting' },
|
||||
],
|
||||
},
|
||||
}),
|
||||
sort: Property.StaticDropdown({
|
||||
displayName: 'Sort Order',
|
||||
description: 'Sort order for results (optional)',
|
||||
required: false,
|
||||
options: {
|
||||
options: [
|
||||
{ label: 'Ascending', value: 'asc' },
|
||||
{ label: 'Descending', value: 'desc' },
|
||||
],
|
||||
},
|
||||
}),
|
||||
fromindex: Property.Number({
|
||||
displayName: 'From Index',
|
||||
description: 'Starting index for pagination (optional, default: 1)',
|
||||
required: false,
|
||||
}),
|
||||
range: Property.Number({
|
||||
displayName: 'Range',
|
||||
description: 'Number of campaigns to retrieve (optional, default: 5)',
|
||||
required: false,
|
||||
}),
|
||||
});
|
||||
|
||||
export const newContact = () => ({
|
||||
listkey: mailingListDropdown({ required: true }),
|
||||
});
|
||||
|
||||
export const unsubscribe = () => ({
|
||||
listkey: mailingListDropdown({ required: true }),
|
||||
status: Property.StaticDropdown({
|
||||
displayName: 'Unsubscribe Type',
|
||||
description: 'Type of contact removal to monitor (default: unsubscribed)',
|
||||
required: false,
|
||||
options: {
|
||||
options: [
|
||||
{ label: 'Unsubscribed', value: 'unsub' },
|
||||
{ label: 'Bounced', value: 'bounce' },
|
||||
],
|
||||
},
|
||||
}),
|
||||
});
|
||||
@@ -0,0 +1,73 @@
|
||||
import z from 'zod';
|
||||
|
||||
export const createCampaign = {
|
||||
campaignname: z.string(),
|
||||
from_email: z.string().email(),
|
||||
subject: z.string(),
|
||||
content_url: z.string().url().optional(),
|
||||
list_details: z.array(z.string()),
|
||||
topicId: z.string().nullable().optional(),
|
||||
}
|
||||
|
||||
export const cloneCampaign = {
|
||||
campaignkey: z.string(),
|
||||
campaignname: z.string().optional(),
|
||||
subject: z.string().optional(),
|
||||
from_name: z.string().optional(),
|
||||
from_add: z.string().email().optional(),
|
||||
reply_to: z.string().email().optional(),
|
||||
encode_type: z.string().optional(),
|
||||
}
|
||||
|
||||
export const sendCampaign = {
|
||||
campaignkey: z.string(),
|
||||
}
|
||||
|
||||
export const addUpdateContact = {
|
||||
listkey: z.string(),
|
||||
contactinfo: z.object({
|
||||
'Contact Email': z.string().email(),
|
||||
}),
|
||||
source: z.string().optional(),
|
||||
topic_id: z.string().nullable().optional(),
|
||||
}
|
||||
|
||||
export const addTagToContact = {
|
||||
tagName: z.string(),
|
||||
lead_email: z.string().email(),
|
||||
}
|
||||
|
||||
export const removeTag = {
|
||||
tagName: z.string(),
|
||||
lead_email: z.string().email(),
|
||||
}
|
||||
|
||||
export const unsubscribeContact = {
|
||||
listkey: z.string(),
|
||||
contactinfo: z.object({
|
||||
'Contact Email': z.string().email(),
|
||||
}),
|
||||
topic_id: z.string().nullable().optional(),
|
||||
}
|
||||
|
||||
export const addContactToMailingList = {
|
||||
listkey: z.string(),
|
||||
emails: z.array(z.string().email()).min(1).max(10),
|
||||
}
|
||||
|
||||
export const findContact = {
|
||||
listkey: z.string(),
|
||||
contactEmail: z.string().email(),
|
||||
status: z.enum(['active', 'recent', 'most recent', 'unsub', 'bounce']).optional(),
|
||||
sort: z.enum(['asc', 'desc']).optional(),
|
||||
fromindex: z.number().min(1).optional(),
|
||||
range: z.number().min(1).optional(),
|
||||
}
|
||||
|
||||
export const findCampaign = {
|
||||
campaignName: z.string(),
|
||||
status: z.enum(['all', 'all campaigns', 'drafts', 'scheduled', 'inprogress', 'sent', 'stopped', 'canceled', 'tobereviewed', 'reviewed', 'paused', 'intesting']).optional(),
|
||||
sort: z.enum(['asc', 'desc']).optional(),
|
||||
fromindex: z.number().min(1).optional(),
|
||||
range: z.number().min(1).optional(),
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
export interface AuthorizationParams {
|
||||
accessToken: string;
|
||||
}
|
||||
|
||||
export interface BaseCampaignKeyParams {
|
||||
campaignkey: string;
|
||||
}
|
||||
|
||||
export interface CreateCampaignParams extends AuthorizationParams {
|
||||
campaignname: string;
|
||||
from_email: string;
|
||||
subject: string;
|
||||
content_url?: string;
|
||||
list_details: object;
|
||||
topicId?: string;
|
||||
}
|
||||
|
||||
export interface CreateTagParams extends AuthorizationParams {
|
||||
tagName: string;
|
||||
}
|
||||
|
||||
export interface CloneCampaignParams extends AuthorizationParams {
|
||||
campaigninfo: object;
|
||||
}
|
||||
|
||||
export interface SendCampaignParams
|
||||
extends AuthorizationParams,
|
||||
BaseCampaignKeyParams {}
|
||||
|
||||
export interface AddUpdateContactParams extends AuthorizationParams {
|
||||
listkey: string;
|
||||
contactinfo: object;
|
||||
source?: string;
|
||||
topic_id?: string;
|
||||
}
|
||||
|
||||
export interface AddTagToContactParams extends AuthorizationParams {
|
||||
tagName: string;
|
||||
lead_email: string;
|
||||
}
|
||||
|
||||
export interface RemoveTagParams extends AuthorizationParams {
|
||||
tagName: string;
|
||||
lead_email: string;
|
||||
}
|
||||
|
||||
export interface UnsubscribeContactParams extends AuthorizationParams {
|
||||
listkey: string;
|
||||
contactinfo: object;
|
||||
topic_id?: string;
|
||||
}
|
||||
|
||||
export interface AddContactToMailingListParams extends AuthorizationParams {
|
||||
listkey: string;
|
||||
emailids: string;
|
||||
}
|
||||
|
||||
export interface ListContactsParams extends AuthorizationParams {
|
||||
listkey: string;
|
||||
sort?: 'asc' | 'desc';
|
||||
fromindex?: number;
|
||||
range?: number;
|
||||
status?: 'active' | 'recent' | 'most recent' | 'unsub' | 'bounce';
|
||||
}
|
||||
|
||||
export interface ListCampaignParams extends AuthorizationParams {
|
||||
sort?: 'asc' | 'desc';
|
||||
fromindex?: number;
|
||||
range?: number;
|
||||
status?:
|
||||
| 'all'
|
||||
| 'all campaigns'
|
||||
| 'drafts'
|
||||
| 'scheduled'
|
||||
| 'inprogress'
|
||||
| 'sent'
|
||||
| 'stopped'
|
||||
| 'canceled'
|
||||
| 'tobereviewed'
|
||||
| 'reviewed'
|
||||
| 'paused'
|
||||
| 'intesting';
|
||||
}
|
||||
|
||||
export interface ListMailingListsParams extends AuthorizationParams {
|
||||
sort?: 'asc' | 'desc';
|
||||
fromindex?: number;
|
||||
range?: number;
|
||||
}
|
||||
|
||||
|
||||
// API Response types
|
||||
export type Campaign = {
|
||||
campaign_key: string;
|
||||
campaign_name: string;
|
||||
created_date_string: string;
|
||||
campaign_status: string;
|
||||
created_time: string;
|
||||
campaign_preview: string;
|
||||
};
|
||||
|
||||
export type Contact = {
|
||||
firstname: string;
|
||||
added_time: string;
|
||||
phone: string;
|
||||
companyname: string;
|
||||
contact_email: string;
|
||||
lastname: string;
|
||||
zuid: string;
|
||||
};
|
||||
|
||||
export type MailingList = {
|
||||
date: string;
|
||||
deletable: string;
|
||||
segments: object;
|
||||
updated_time_gmt: string;
|
||||
listdesc: string;
|
||||
created_time_gmt: string;
|
||||
list_created_time: string;
|
||||
noofunsubcnt: string;
|
||||
lockstatus: string;
|
||||
listkey: string;
|
||||
listtype: string;
|
||||
sentcnt: string;
|
||||
owner: string;
|
||||
list_campaigns_count: string;
|
||||
created_time: string;
|
||||
noofcontacts: string;
|
||||
editable: string;
|
||||
listname: string;
|
||||
listdgs: string;
|
||||
noofbouncecnt: string;
|
||||
issmart: string;
|
||||
list_created_date: string;
|
||||
listnotifications: string;
|
||||
listunino: string;
|
||||
zuid: string;
|
||||
servicetype: string;
|
||||
sno: string;
|
||||
is_public: string;
|
||||
otherslist: string;
|
||||
zx: string;
|
||||
};
|
||||
|
||||
export type Topic = {
|
||||
topicId: string;
|
||||
topicName: string;
|
||||
primaryList: number;
|
||||
};
|
||||
|
||||
export type Tag = {
|
||||
[key: string]: {
|
||||
tagowner: string;
|
||||
tag_created_time: string;
|
||||
tag_name: string;
|
||||
tag_color: string;
|
||||
tag_desc: string;
|
||||
tagged_contact_count: string;
|
||||
is_crm_tag: string;
|
||||
zuid: string;
|
||||
};
|
||||
};
|
||||
|
||||
export interface ListCampaignResponse {
|
||||
fromindex: string;
|
||||
total_record_count: string;
|
||||
code: string;
|
||||
recent_campaigns: Campaign[];
|
||||
range: string;
|
||||
campaign_count: string;
|
||||
uri: string;
|
||||
version: string;
|
||||
requestdetails: string;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface ListContactsResponse {
|
||||
code: string;
|
||||
uri: string;
|
||||
version: string;
|
||||
list_of_details: Contact[];
|
||||
requestdetails: {
|
||||
fromindex: number;
|
||||
range: number;
|
||||
sort: string;
|
||||
status: string;
|
||||
};
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface ListMailingListsResponse {
|
||||
code: string;
|
||||
uri: string;
|
||||
version: string;
|
||||
list_of_details: MailingList[];
|
||||
requestdetails: {
|
||||
fromindex: number;
|
||||
range: number;
|
||||
total_list_count: number;
|
||||
sort: string;
|
||||
};
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface ListTopicsResponse {
|
||||
topicDetails: Topic[];
|
||||
message: string;
|
||||
code: string;
|
||||
uri: string;
|
||||
}
|
||||
|
||||
export interface CreateCampaignResponse {
|
||||
message: string;
|
||||
campaignKey: string;
|
||||
code: string;
|
||||
uri: string;
|
||||
}
|
||||
|
||||
export interface ListTagsResponse {
|
||||
uri: string;
|
||||
version: string;
|
||||
requestdetails: string;
|
||||
tags?: Tag[];
|
||||
}
|
||||
Reference in New Issue
Block a user