diff --git a/packages/nodes-base/credentials/MonicaCrmApi.credentials.ts b/packages/nodes-base/credentials/MonicaCrmApi.credentials.ts new file mode 100644 index 0000000000..45d400a7df --- /dev/null +++ b/packages/nodes-base/credentials/MonicaCrmApi.credentials.ts @@ -0,0 +1,48 @@ +import { + ICredentialType, + INodeProperties, +} from 'n8n-workflow'; + +export class MonicaCrmApi implements ICredentialType { + name = 'monicaCrmApi'; + displayName = 'Monica CRM API'; + documentationUrl = 'monicaCrm'; + properties: INodeProperties[] = [ + { + displayName: 'Environment', + name: 'environment', + type: 'options', + default: 'cloudHosted', + options: [ + { + name: 'Cloud-hosted', + value: 'cloudHosted', + }, + { + name: 'Self-hosted', + value: 'selfHosted', + }, + ], + }, + { + displayName: 'Self-hosted domain', + name: 'domain', + type: 'string', + default: '', + placeholder: 'https://www.mydomain.com', + displayOptions: { + show: { + environment: [ + 'selfHosted', + ], + }, + }, + }, + { + displayName: 'API Token', + name: 'apiToken', + type: 'string', + default: '', + }, + ]; +} diff --git a/packages/nodes-base/nodes/MonicaCrm/GenericFunctions.ts b/packages/nodes-base/nodes/MonicaCrm/GenericFunctions.ts new file mode 100644 index 0000000000..9adee57d2b --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/GenericFunctions.ts @@ -0,0 +1,103 @@ +import { + Credentials, + IExecuteFunctions, +} from 'n8n-core'; + +import { + IDataObject, + ILoadOptionsFunctions, + NodeApiError, + NodeOperationError, +} from 'n8n-workflow'; + +import { + OptionsWithUri, +} from 'request'; + +import { + LoaderGetResponse, +} from './types'; + +export async function monicaCrmApiRequest( + this: IExecuteFunctions | ILoadOptionsFunctions, + method: string, + endpoint: string, + body: IDataObject = {}, + qs: IDataObject = {}, +) { + const credentials = this.getCredentials('monicaCrmApi') as { apiToken: string, environment: string, domain: string }; + + if (credentials === undefined) { + throw new NodeOperationError(this.getNode(), 'No credentials got returned!'); + } + + let baseUrl = `https://app.monicahq.com`; + + if (credentials.environment === 'selfHosted') { + baseUrl = credentials.domain; + } + + const options: OptionsWithUri = { + headers: { + Authorization: `Bearer ${credentials.apiToken}`, + }, + method, + body, + qs, + uri: `${baseUrl}/api${endpoint}`, + json: true, + }; + + if (!Object.keys(body).length) { + delete options.body; + } + + if (!Object.keys(qs).length) { + delete options.qs; + } + + try { + return await this.helpers.request!(options); + } catch (error) { + throw new NodeApiError(this.getNode(), error); + } +} + +export async function monicaCrmApiRequestAllItems( + this: IExecuteFunctions | ILoadOptionsFunctions, + method: string, + endpoint: string, + body: IDataObject = {}, + qs: IDataObject = {}, + { forLoader }: { forLoader: boolean } = { forLoader: false }, +) { + const returnAll = this.getNodeParameter('returnAll', 0, false) as boolean; + const limit = this.getNodeParameter('limit', 0, 0) as number; + + let totalItems = 0; + + let responseData; + const returnData: IDataObject[] = []; + + do { + responseData = await monicaCrmApiRequest.call(this, method, endpoint, body, qs); + returnData.push(...responseData.data); + + if (!forLoader && !returnAll && returnData.length > limit) { + return returnData.slice(0, limit); + } + + totalItems = responseData.meta.total; + } while (totalItems > returnData.length); + + return returnData; +} + +/** + * Get day, month, and year from the n8n UI datepicker. + */ +export const getDateParts = (date: string) => + date.split('T')[0].split('-').map(Number).reverse(); + +export const toOptions = (response: LoaderGetResponse) => + response.data.map(({ id, name }) => ({ value: id, name })); diff --git a/packages/nodes-base/nodes/MonicaCrm/MonicaCrm.node.ts b/packages/nodes-base/nodes/MonicaCrm/MonicaCrm.node.ts new file mode 100644 index 0000000000..47e4d57e8a --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/MonicaCrm.node.ts @@ -0,0 +1,1268 @@ +import { + IExecuteFunctions, +} from 'n8n-core'; + +import { + IDataObject, + ILoadOptionsFunctions, + INodeExecutionData, + INodeType, + INodeTypeDescription, +} from 'n8n-workflow'; + +import { + getDateParts, + monicaCrmApiRequest, + monicaCrmApiRequestAllItems, + toOptions, +} from './GenericFunctions'; + +import { + activityFields, + activityOperations, + callFields, + callOperations, + contactFieldFields, + contactFieldOperations, + contactFields, + contactOperations, + contactTagFields, + contactTagOperations, + conversationFields, + conversationMessageFields, + conversationMessageOperations, + conversationOperations, + journalEntryFields, + journalEntryOperations, + noteFields, + noteOperations, + reminderFields, + reminderOperations, + tagFields, + tagOperations, + taskFields, + taskOperations, +} from './descriptions'; + +import { + LoaderGetResponse, + Option, +} from './types'; + +export class MonicaCrm implements INodeType { + description: INodeTypeDescription = { + displayName: 'Monica CRM', + name: 'monicaCrm', + icon: 'file:monicaCrm.png', + group: ['transform'], + version: 1, + subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', + description: 'Consume the Monica CRM API', + defaults: { + name: 'Monica CRM', + color: '#3cb371', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'monicaCrmApi', + required: true, + }, + ], + properties: [ + { + displayName: 'Resource', + name: 'resource', + type: 'options', + options: [ + { + name: 'Activity', + value: 'activity', + }, + { + name: 'Call', + value: 'call', + }, + { + name: 'Contact', + value: 'contact', + }, + { + name: 'Contact Field', + value: 'contactField', + }, + { + name: 'Contact Tag', + value: 'contactTag', + }, + { + name: 'Conversation', + value: 'conversation', + }, + { + name: 'Conversation Message', + value: 'conversationMessage', + }, + { + name: 'Journal Entry', + value: 'journalEntry', + }, + { + name: 'Note', + value: 'note', + }, + { + name: 'Reminder', + value: 'reminder', + }, + { + name: 'Tag', + value: 'tag', + }, + { + name: 'Task', + value: 'task', + }, + ], + default: 'contact', + }, + ...activityOperations, + ...activityFields, + ...callOperations, + ...callFields, + ...contactOperations, + ...contactFields, + ...contactFieldOperations, + ...contactFieldFields, + ...contactTagOperations, + ...contactTagFields, + ...conversationOperations, + ...conversationFields, + ...conversationMessageOperations, + ...conversationMessageFields, + ...journalEntryOperations, + ...journalEntryFields, + ...noteOperations, + ...noteFields, + ...reminderOperations, + ...reminderFields, + ...tagOperations, + ...tagFields, + ...taskOperations, + ...taskFields, + ], + }; + + methods = { + loadOptions: { + async getActivityTypes(this: ILoadOptionsFunctions) { + const responseData = await monicaCrmApiRequest.call(this, 'GET', '/activitytypes') as LoaderGetResponse; + return toOptions(responseData); + }, + + async getTagsToAdd(this: ILoadOptionsFunctions) { + const responseData = await monicaCrmApiRequestAllItems.call( + this, 'GET', '/tags', {}, {}, { forLoader: true }, + ); + + // intentional, name required when adding + return responseData.map(({ name }) => ({ value: name, name })) as Option[]; + }, + + async getTagsToRemove(this: ILoadOptionsFunctions) { + const responseData = await monicaCrmApiRequestAllItems.call( + this, 'GET', '/tags', {}, {}, { forLoader: true }, + ); + return responseData.map(({ id, name }) => ({ value: id, name })) as Option[]; + }, + + async getContactFieldTypes(this: ILoadOptionsFunctions) { + const responseData = await monicaCrmApiRequest.call(this, 'GET', '/contactfieldtypes') as LoaderGetResponse; + return toOptions(responseData); + }, + + async getGenders(this: ILoadOptionsFunctions) { + const responseData = await monicaCrmApiRequest.call(this, 'GET', '/genders') as LoaderGetResponse; + return toOptions(responseData); + }, + }, + }; + + async execute(this: IExecuteFunctions): Promise { + const items = this.getInputData(); + const returnData: IDataObject[] = []; + + const resource = this.getNodeParameter('resource', 0) as string; + const operation = this.getNodeParameter('operation', 0) as string; + + let responseData; + + for (let i = 0; i < items.length; i++) { + + try { + + if (resource === 'activity') { + + // ********************************************************************** + // activity + // ********************************************************************** + + if (operation === 'create') { + + // ---------------------------------------- + // activity: create + // ---------------------------------------- + + // https://www.monicahq.com/api/activities#create-an-activity + + const contacts = this.getNodeParameter('contacts', i) as string; + const happenedAt = this.getNodeParameter('happenedAt', i) as string; + + const body = { + activity_type_id: this.getNodeParameter('activityTypeId', i), + contacts: contacts.split(','), + happened_at: happenedAt.split('T')[0], + summary: this.getNodeParameter('summary', i), + } as IDataObject; + + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + + if (Object.keys(additionalFields).length) { + Object.assign(body, additionalFields); + } + + responseData = await monicaCrmApiRequest.call(this, 'POST', '/activities', body); + + } else if (operation === 'delete') { + + // ---------------------------------------- + // activity: delete + // ---------------------------------------- + + // https://www.monicahq.com/api/activities#delete-an-activity + + const activityId = this.getNodeParameter('activityId', i); + + const endpoint = `/activities/${activityId}`; + await monicaCrmApiRequest.call(this, 'DELETE', endpoint); + responseData = { success: true }; + + } else if (operation === 'get') { + + // ---------------------------------------- + // activity: get + // ---------------------------------------- + + // https://www.monicahq.com/api/activities#get-a-specific-activity + + const activityId = this.getNodeParameter('activityId', i); + + const endpoint = `/activities/${activityId}`; + responseData = await monicaCrmApiRequest.call(this, 'GET', endpoint); + + } else if (operation === 'getAll') { + + // ---------------------------------------- + // activity: getAll + // ---------------------------------------- + + // https://www.monicahq.com/api/activities#list-all-the-activities-in-your-account + + const endpoint = `/activities`; + responseData = await monicaCrmApiRequestAllItems.call(this, 'GET', endpoint); + + } else if (operation === 'update') { + + // ---------------------------------------- + // activity: update + // ---------------------------------------- + + // https://www.monicahq.com/api/activities#update-an-activity + + const activityId = this.getNodeParameter('activityId', i); + + const { data } = await monicaCrmApiRequest.call(this, 'GET', `/activities/${activityId}`); + + const body = { + activity_type_id: data.activity_type.id, + contacts: data.attendees.contacts.map((contact: IDataObject) => contact.id), + happened_at: data.happened_at, + summary: data.summary, + } as IDataObject; + + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + + if (Object.keys(updateFields).length) { + Object.assign(body, updateFields); + } + + body.happened_at = (body.happened_at as string).split('T')[0]; + + if (typeof body.contacts === 'string') { + body.contacts = (body.contacts as string).split(','); + } + + const endpoint = `/activities/${activityId}`; + responseData = await monicaCrmApiRequest.call(this, 'PUT', endpoint, body); + + } + + } else if (resource === 'call') { + + // ********************************************************************** + // call + // ********************************************************************** + + if (operation === 'create') { + + // ---------------------------------------- + // call: create + // ---------------------------------------- + + // https://www.monicahq.com/api/calls#create-a-call + + const body = { + called_at: this.getNodeParameter('calledAt', i), + contact_id: this.getNodeParameter('contactId', i), + content: this.getNodeParameter('content', i), + } as IDataObject; + + responseData = await monicaCrmApiRequest.call(this, 'POST', '/calls', body); + + } else if (operation === 'delete') { + + // ---------------------------------------- + // call: delete + // ---------------------------------------- + + // https://www.monicahq.com/api/contactfields#delete-a-call + + const callId = this.getNodeParameter('callId', i); + + responseData = await monicaCrmApiRequest.call(this, 'DELETE', `/calls/${callId}`); + responseData = { success: true }; + + } else if (operation === 'get') { + + // ---------------------------------------- + // call: get + // ---------------------------------------- + + // https://www.monicahq.com/api/calls#get-a-specific-call + + const callId = this.getNodeParameter('callId', i); + + responseData = await monicaCrmApiRequest.call(this, 'GET', `/calls/${callId}`); + + } else if (operation === 'getAll') { + + // ---------------------------------------- + // call: getAll + // ---------------------------------------- + + // https://www.monicahq.com/api/calls#list-all-the-calls-in-your-account + + const endpoint = `/calls`; + responseData = await monicaCrmApiRequestAllItems.call(this, 'GET', endpoint); + + } else if (operation === 'update') { + + // ---------------------------------------- + // call: update + // ---------------------------------------- + + // https://www.monicahq.com/api/calls#update-a-call + + const callId = this.getNodeParameter('callId', i); + + const { data } = await monicaCrmApiRequest.call(this, 'GET', `/calls/${callId}`); + + const body = { + called_at: data.called_at, + } as IDataObject; + + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + + if (Object.keys(updateFields).length) { + Object.assign(body, updateFields); + } + + responseData = await monicaCrmApiRequest.call(this, 'PUT', `/calls/${callId}`, body); + + } + + } else if (resource === 'contact') { + + // ********************************************************************** + // contact + // ********************************************************************** + + if (operation === 'create') { + + // ---------------------------------------- + // contact: create + // ---------------------------------------- + + // https://www.monicahq.com/api/contacts#create-a-contact + + const body = { + first_name: this.getNodeParameter('firstName', i), + gender_id: this.getNodeParameter('genderId', i), + } as IDataObject; + + const { + isDeceased = false, + deceasedDate, + birthdate, + ...rest + } = this.getNodeParameter('additionalFields', i) as { + isDeceased?: boolean; + deceasedDate?: string; + birthdate?: string; + } & IDataObject; + + body.is_birthdate_known = false; + body.is_deceased = isDeceased; + body.is_deceased_date_known = false; + + if (birthdate) { + body.is_birthdate_known = true; + + const [day, month, year] = getDateParts(birthdate); + body.birthdate_day = day; + body.birthdate_month = month; + body.birthdate_year = year; + } + + if (deceasedDate) { + body.is_deceased = true; + body.is_deceased_date_known = true; + + const [day, month, year] = getDateParts(deceasedDate); + body.deceased_date_day = day; + body.deceased_date_month = month; + body.deceased_date_year = year; + } + + if (Object.keys(rest).length) { + Object.assign(body, rest); + } + + responseData = await monicaCrmApiRequest.call(this, 'POST', '/contacts', body); + + } else if (operation === 'delete') { + + // ---------------------------------------- + // contact: delete + // ---------------------------------------- + + // https://www.monicahq.com/api/contacts#delete-a-contact + + const contactId = this.getNodeParameter('contactId', i); + + const endpoint = `/contacts/${contactId}`; + await monicaCrmApiRequest.call(this, 'DELETE', endpoint); + responseData = { success: true }; + + } else if (operation === 'get') { + + // ---------------------------------------- + // contact: get + // ---------------------------------------- + + // https://www.monicahq.com/api/contacts#get-a-specific-contact + + const contactId = this.getNodeParameter('contactId', i); + + const endpoint = `/contacts/${contactId}`; + responseData = await monicaCrmApiRequest.call(this, 'GET', endpoint); + + } else if (operation === 'getAll') { + + // ---------------------------------------- + // contact: getAll + // ---------------------------------------- + + // https://www.monicahq.com/api/contacts#list-all-your-contacts + + const qs = {} as IDataObject; + const filters = this.getNodeParameter('filters', i) as IDataObject; + + if (Object.keys(filters).length) { + Object.assign(qs, filters); + } + + responseData = await monicaCrmApiRequestAllItems.call(this, 'GET', '/contacts', {}, qs); + + } else if (operation === 'update') { + + // ---------------------------------------- + // contact: update + // ---------------------------------------- + + const contactId = this.getNodeParameter('contactId', i); + + const { data } = await monicaCrmApiRequest.call(this, 'GET', `/contacts/${contactId}`); + + const body = { + first_name: data.first_name, + } as IDataObject; + + const { + is_deaceased = false, + deceased_date, + birthdate, + ...rest + } = this.getNodeParameter('updateFields', i) as { + is_deaceased?: boolean; + deceased_date?: string; + birthdate?: string; + } & IDataObject; + + body.is_birthdate_known = false; + body.is_deceased = is_deaceased; + body.is_deceased_date_known = false; + + if (birthdate) { + body.is_birthdate_known = true; + + const [day, month, year] = getDateParts(birthdate); + body.birthdate_day = day; + body.birthdate_month = month; + body.birthdate_year = year; + } + + if (deceased_date) { + body.is_deceased = true; + body.is_deceased_date_known = true; + + const [day, month, year] = getDateParts(deceased_date); + body.deceased_date_day = day; + body.deceased_date_month = month; + body.deceased_date_year = year; + } + + if (Object.keys(rest).length) { + Object.assign(body, rest); + } + + const endpoint = `/contacts/${contactId}`; + responseData = await monicaCrmApiRequest.call(this, 'PUT', endpoint, body); + + } + + } else if (resource === 'contactField') { + + // ********************************************************************** + // contactField + // ********************************************************************** + + if (operation === 'create') { + + // ---------------------------------------- + // contactField: create + // ---------------------------------------- + + // https://www.monicahq.com/api/contactfields#create-a-contact-field + + const body = { + contact_field_type_id: this.getNodeParameter('contactFieldTypeId', i), + contact_id: this.getNodeParameter('contactId', i), + data: this.getNodeParameter('data', i), + } as IDataObject; + + responseData = await monicaCrmApiRequest.call(this, 'POST', '/contactfields', body); + + } else if (operation === 'delete') { + + // ---------------------------------------- + // contactField: delete + // ---------------------------------------- + + // https://www.monicahq.com/api/contactfields#delete-a-contact-field + + const contactFieldId = this.getNodeParameter('contactFieldId', i); + + const endpoint = `/contactfields/${contactFieldId}`; + await monicaCrmApiRequest.call(this, 'DELETE', endpoint); + responseData = { success: true }; + + } else if (operation === 'get') { + + // ---------------------------------------- + // contactField: get + // ---------------------------------------- + + // https://www.monicahq.com/api/contactfields#get-a-specific-contact-field + + const contactFieldId = this.getNodeParameter('contactFieldId', i); + + const endpoint = `/contactfields/${contactFieldId}`; + responseData = await monicaCrmApiRequest.call(this, 'GET', endpoint); + + } else if (operation === 'getAll') { + + // ---------------------------------------- + // contactField: getAll + // ---------------------------------------- + + // https://www.monicahq.com/api/contactfields#list-all-the-contact-fields-of-a-specific-contact + + const contactId = this.getNodeParameter('contactId', i); + + const endpoint = `/contact/${contactId}/contactfields`; + responseData = await monicaCrmApiRequestAllItems.call(this, 'GET', endpoint); + + } else if (operation === 'update') { + + // ---------------------------------------- + // contactField: update + // ---------------------------------------- + + // https://www.monicahq.com/api/contactfields#update-a-contact-field + + const body = { + contact_field_type_id: this.getNodeParameter('contactFieldTypeId', i), + contact_id: this.getNodeParameter('contactId', i), + data: this.getNodeParameter('data', i), + } as IDataObject; + + const contactFieldId = this.getNodeParameter('contactFieldId', i); + + const endpoint = `/contactfields/${contactFieldId}`; + responseData = await monicaCrmApiRequest.call(this, 'PUT', endpoint, body); + + } + + } else if (resource === 'contactTag') { + + // ********************************************************************** + // contactTag + // ********************************************************************** + + if (operation === 'add') { + + // ---------------------------------------- + // contactTag: add + // ---------------------------------------- + + // https://www.monicahq.com/api/tags#associate-a-tag-to-a-contact + + const body = { + tags: this.getNodeParameter('tagsToAdd', i), + } as IDataObject; + + const contactId = this.getNodeParameter('contactId', i); + + const endpoint = `/contacts/${contactId}/setTags`; + responseData = await monicaCrmApiRequest.call(this, 'POST', endpoint, body); + + } else if (operation === 'remove') { + + // ---------------------------------------- + // tag: remove + // ---------------------------------------- + + // https://www.monicahq.com/api/tags#remove-a-specific-tag-from-a-contact + + const body = { + tags: this.getNodeParameter('tagsToRemove', i), + } as IDataObject; + + const contactId = this.getNodeParameter('contactId', i); + + const endpoint = `/contacts/${contactId}/unsetTag`; + responseData = await monicaCrmApiRequest.call(this, 'POST', endpoint, body); + + } + + } else if (resource === 'conversation') { + + // ********************************************************************** + // conversation + // ********************************************************************** + + + + if (operation === 'create') { + + // ---------------------------------------- + // conversation: create + // ---------------------------------------- + + // https://www.monicahq.com/api/conversations#create-a-conversation + + const body = { + contact_field_type_id: this.getNodeParameter('contactFieldTypeId', i), + contact_id: this.getNodeParameter('contactId', i), + happened_at: this.getNodeParameter('happenedAt', i), + } as IDataObject; + + responseData = await monicaCrmApiRequest.call(this, 'POST', '/conversations', body); + + } else if (operation === 'delete') { + + // ---------------------------------------- + // conversation: delete + // ---------------------------------------- + + // https://www.monicahq.com/api/contactfields#delete-a-contact-field + + const conversationId = this.getNodeParameter('conversationId', i); + + const endpoint = `/conversations/${conversationId}`; + await monicaCrmApiRequest.call(this, 'DELETE', endpoint); + responseData = { success: true }; + + } else if (operation === 'get') { + + // ---------------------------------------- + // conversation: get + // ---------------------------------------- + + // https://www.monicahq.com/api/conversations#get-a-specific-conversation + + const conversationId = this.getNodeParameter('conversationId', i); + + const endpoint = `/conversations/${conversationId}`; + responseData = await monicaCrmApiRequest.call(this, 'GET', endpoint); + + } else if (operation === 'update') { + + // ---------------------------------------- + // conversation: update + // ---------------------------------------- + + // https://www.monicahq.com/api/conversations#update-a-conversation + + const body = { + contact_field_type_id: this.getNodeParameter('contactFieldTypeId', i), + happened_at: this.getNodeParameter('happenedAt', i), + } as IDataObject; + + const conversationId = this.getNodeParameter('conversationId', i); + + const endpoint = `/conversations/${conversationId}`; + responseData = await monicaCrmApiRequest.call(this, 'PUT', endpoint, body); + + } + } else if (resource === 'conversationMessage') { + if (operation === 'add') { + + // ---------------------------------------- + // conversationMessage: add + // ---------------------------------------- + + // https://www.monicahq.com/api/conversations#add-a-message-to-a-conversation + + const conversationId = this.getNodeParameter('conversationId', i); + + const endpoint = `/conversations/${conversationId}/messages`; + + const { data } = await monicaCrmApiRequest.call(this, 'GET', `/conversations/${conversationId}`); + + const body = { + contact_id: data.contact.id, + content: this.getNodeParameter('content', i), + written_at: this.getNodeParameter('writtenAt', i), + written_by_me: this.getNodeParameter('writtenByMe', i), + } as IDataObject; + + responseData = await monicaCrmApiRequest.call(this, 'POST', endpoint, body); + + } else if (operation === 'update') { + + // ---------------------------------------- + // conversationMessage: update + // ---------------------------------------- + + // https://www.monicahq.com/api/conversations#update-a-message-in-a-conversation + const conversationId = this.getNodeParameter('conversationId', i); + const messageId = this.getNodeParameter('messageId', i) as string; + const endpoint = `/conversations/${conversationId}/messages/${messageId}`; + + const updateFields = this.getNodeParameter('updateFields', i, {}) as IDataObject; + + const { data } = await monicaCrmApiRequest.call(this, 'GET', `/conversations/${conversationId}`); + + const message = data.messages.filter((message: IDataObject) => message.id === parseInt(messageId, 10))[0]; + + const body = { + contact_id: data.contact.id, + content: message.content, + written_at: message.written_at, + written_by_me: message.written_by_me, + } as IDataObject; + + if (Object.keys(updateFields).length) { + Object.assign(body, updateFields); + } + + responseData = await monicaCrmApiRequest.call(this, 'PUT', endpoint, body); + } + + } else if (resource === 'journalEntry') { + + // ********************************************************************** + // journalEntry + // ********************************************************************** + + if (operation === 'create') { + + // ---------------------------------------- + // journalEntry: create + // ---------------------------------------- + + // https://www.monicahq.com/api/notes#create-a-journal-entry + + const body = { + title: this.getNodeParameter('title', i), + post: this.getNodeParameter('post', i), + } as IDataObject; + + responseData = await monicaCrmApiRequest.call(this, 'POST', '/journal', body); + + } else if (operation === 'delete') { + + // ---------------------------------------- + // journalEntry: delete + // ---------------------------------------- + + // https://www.monicahq.com/api/journal#delete-a-journal-entry + + const journalId = this.getNodeParameter('journalId', i); + + await monicaCrmApiRequest.call(this, 'DELETE', `/journal/${journalId}`); + responseData = { success: true }; + + } else if (operation === 'get') { + + // ---------------------------------------- + // journalEntry: get + // ---------------------------------------- + + // https://www.monicahq.com/api/journal#get-a-specific-journal-entry + + const journalId = this.getNodeParameter('journalId', i); + + responseData = await monicaCrmApiRequest.call(this, 'GET', `/journal/${journalId}`); + + } else if (operation === 'getAll') { + + // ---------------------------------------- + // journalEntry: getAll + // ---------------------------------------- + + // https://www.monicahq.com/api/journal#list-all-the-entries-in-your-journal + + responseData = await monicaCrmApiRequestAllItems.call(this, 'GET', '/journal'); + + } else if (operation === 'update') { + + // ---------------------------------------- + // journalEntry: update + // ---------------------------------------- + + // https://www.monicahq.com/api/journal#update-a-journal-entry + + const journalId = this.getNodeParameter('journalId', i); + + const { data } = await monicaCrmApiRequest.call(this, 'GET', `/journal/${journalId}`); + + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + + const body = { + post: data.post, + title: data.title, + } as IDataObject; + + if (Object.keys(updateFields).length) { + Object.assign(body, updateFields); + } + + responseData = await monicaCrmApiRequest.call(this, 'PUT', `/journal/${journalId}`, body); + + } + + } else if (resource === 'note') { + + // ********************************************************************** + // note + // ********************************************************************** + + if (operation === 'create') { + + // ---------------------------------------- + // note: create + // ---------------------------------------- + + // https://www.monicahq.com/api/notes#create-a-note + + const body = { + body: this.getNodeParameter('body', i), + contact_id: this.getNodeParameter('contactId', i), + } as IDataObject; + + body.is_favorited = this.getNodeParameter('additionalFields.isFavorited', i, false); + + responseData = await monicaCrmApiRequest.call(this, 'POST', '/notes', body); + + } else if (operation === 'delete') { + + // ---------------------------------------- + // note: delete + // ---------------------------------------- + + // https://www.monicahq.com/api/notes#delete-a-note + + const noteId = this.getNodeParameter('noteId', i); + + await monicaCrmApiRequest.call(this, 'DELETE', `/notes/${noteId}`); + responseData = { success: true }; + + } else if (operation === 'get') { + + // ---------------------------------------- + // note: get + // ---------------------------------------- + + // https://www.monicahq.com/api/notes#get-a-specific-note + + const noteId = this.getNodeParameter('noteId', i); + + responseData = await monicaCrmApiRequest.call(this, 'GET', `/notes/${noteId}`); + + } else if (operation === 'getAll') { + + // ---------------------------------------- + // note: getAll + // ---------------------------------------- + + // https://www.monicahq.com/api/notes#list-all-the-notes-in-your-account + + const endpoint = `/notes`; + responseData = await monicaCrmApiRequestAllItems.call(this, 'GET', endpoint); + + } else if (operation === 'update') { + + // ---------------------------------------- + // note: update + // ---------------------------------------- + + // https://www.monicahq.com/api/notes#update-a-note + + const noteId = this.getNodeParameter('noteId', i); + + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + + const { data } = await monicaCrmApiRequest.call(this, 'GET', `/notes/${noteId}`); + + const body = { + body: data.body, + contact_id: data.contact.id, + } as IDataObject; + + + if (Object.keys(updateFields).length) { + Object.assign(body, updateFields); + } + + responseData = await monicaCrmApiRequest.call(this, 'PUT', `/notes/${noteId}`, body); + + } + + } else if (resource === 'reminder') { + + // ********************************************************************** + // reminder + // ********************************************************************** + + if (operation === 'create') { + + // ---------------------------------------- + // reminder: create + // ---------------------------------------- + + // https://www.monicahq.com/api/notes#create-a-reminder + + const initialDate = this.getNodeParameter('initialDate', i) as string; + + const body = { + contact_id: this.getNodeParameter('contactId', i), + frequency_type: this.getNodeParameter('frequencyType', i), + frequency_number: this.getNodeParameter('frequencyNumber', i, 1), + initial_date: initialDate.split('T')[0], + title: this.getNodeParameter('title', i), + } as IDataObject; + + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + + if (Object.keys(additionalFields).length) { + Object.assign(body, additionalFields); + } + + responseData = await monicaCrmApiRequest.call(this, 'POST', '/reminders', body); + + } else if (operation === 'delete') { + + // ---------------------------------------- + // reminder: delete + // ---------------------------------------- + + // https://www.monicahq.com/api/reminder#delete-a-reminder + + const reminderId = this.getNodeParameter('reminderId', i); + + const endpoint = `/reminders/${reminderId}`; + await monicaCrmApiRequest.call(this, 'DELETE', endpoint); + responseData = { success: true }; + + } else if (operation === 'get') { + + // ---------------------------------------- + // reminder: get + // ---------------------------------------- + + // https://www.monicahq.com/api/reminder#get-a-specific-reminder + + const reminderId = this.getNodeParameter('reminderId', i); + + const endpoint = `/reminders/${reminderId}`; + responseData = await monicaCrmApiRequest.call(this, 'GET', endpoint); + + } else if (operation === 'getAll') { + + // ---------------------------------------- + // reminder: getAll + // ---------------------------------------- + + // https://www.monicahq.com/api/reminders#list-all-the-reminders-in-your-account + + responseData = await monicaCrmApiRequestAllItems.call(this, 'GET', '/reminders'); + + } else if (operation === 'update') { + + // ---------------------------------------- + // reminder: update + // ---------------------------------------- + + // https://www.monicahq.com/api/reminders#update-a-reminder + + const reminderId = this.getNodeParameter('reminderId', i); + + const { data } = await monicaCrmApiRequest.call(this, 'GET', `/reminders/${reminderId}`); + + const body = { + contact_id: data.contact.id, + frequency_type: data.frequency_type, + frequency_number: data.frequency_number, + initial_date: data.initial_date, + title: data.title, + } as IDataObject; + + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + + if (Object.keys(updateFields).length) { + Object.assign(body, updateFields); + } + + body.initial_date = (body.initial_date as string).split('T')[0]; + + const endpoint = `/reminders/${reminderId}`; + responseData = await monicaCrmApiRequest.call(this, 'PUT', endpoint, body); + + } + + } else if (resource === 'tag') { + + // ********************************************************************** + // tag + // ********************************************************************** + + if (operation === 'create') { + + // ---------------------------------------- + // tag: create + // ---------------------------------------- + + // https://www.monicahq.com/api/tags#create-a-tag + + const body = { + name: this.getNodeParameter('name', i), + } as IDataObject; + + responseData = await monicaCrmApiRequest.call(this, 'POST', '/tags', body); + + } else if (operation === 'delete') { + + // ---------------------------------------- + // tag: delete + // ---------------------------------------- + + // https://www.monicahq.com/api/tag#delete-a-tag + + const tagId = this.getNodeParameter('tagId', i); + + await monicaCrmApiRequest.call(this, 'DELETE', `/tags/${tagId}`); + responseData = { success: true }; + + } else if (operation === 'get') { + + // ---------------------------------------- + // tag: get + // ---------------------------------------- + + // https://www.monicahq.com/api/task#get-a-specific-tag + + const tagId = this.getNodeParameter('tagId', i); + + responseData = await monicaCrmApiRequest.call(this, 'GET', `/tags/${tagId}`); + + } else if (operation === 'getAll') { + + // ---------------------------------------- + // tag: getAll + // ---------------------------------------- + + // https://www.monicahq.com/api/tags#list-all-your-tags + + responseData = await monicaCrmApiRequestAllItems.call(this, 'GET', '/tags'); + + } else if (operation === 'update') { + + // ---------------------------------------- + // tag: update + // ---------------------------------------- + + // https://www.monicahq.com/api/tags#update-a-tag + + const body = { + name: this.getNodeParameter('name', i), + } as IDataObject; + + const tagId = this.getNodeParameter('tagId', i); + + responseData = await monicaCrmApiRequest.call(this, 'PUT', `/tags/${tagId}`, body); + + } + + } else if (resource === 'task') { + + // ********************************************************************** + // task + // ********************************************************************** + + if (operation === 'create') { + + // ---------------------------------------- + // task: create + // ---------------------------------------- + + // https://www.monicahq.com/api/notes#create-a-task + + const body = { + contact_id: this.getNodeParameter('contactId', i), + title: this.getNodeParameter('title', i), + } as IDataObject; + + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + + if (Object.keys(additionalFields).length) { + Object.assign(body, additionalFields); + } + + responseData = await monicaCrmApiRequest.call(this, 'POST', '/tasks', body); + + } else if (operation === 'delete') { + + // ---------------------------------------- + // task: delete + // ---------------------------------------- + + // https://www.monicahq.com/api/task#delete-a-task + + const taskId = this.getNodeParameter('taskId', i); + + await monicaCrmApiRequest.call(this, 'DELETE', `/tasks/${taskId}`); + responseData = { success: true }; + + } else if (operation === 'get') { + + // ---------------------------------------- + // task: get + // ---------------------------------------- + + // https://www.monicahq.com/api/task#get-a-specific-task + + const taskId = this.getNodeParameter('taskId', i); + + responseData = await monicaCrmApiRequest.call(this, 'GET', `/tasks/${taskId}`); + + } else if (operation === 'getAll') { + + // ---------------------------------------- + // task: getAll + // ---------------------------------------- + + // https://www.monicahq.com/api/tasks#list-all-the-tasks-of-a-specific-contact + + const endpoint = `/tasks`; + responseData = await monicaCrmApiRequestAllItems.call(this, 'GET', endpoint); + + } else if (operation === 'update') { + + // ---------------------------------------- + // task: update + // ---------------------------------------- + + // https://www.monicahq.com/api/task#update-a-task + + const taskId = this.getNodeParameter('taskId', i); + + const { data } = await monicaCrmApiRequest.call(this, 'GET', `/tasks/${taskId}`); + + const body = { + contact_id: data.contact.id, + title: data.title, + completed: data.completed, + } as IDataObject; + + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + + if (Object.keys(updateFields).length) { + Object.assign(body, updateFields); + } + + responseData = await monicaCrmApiRequest.call(this, 'PUT', `/tasks/${taskId}`, body); + } + + } + + } catch (error) { + if (this.continueOnFail()) { + returnData.push({ json: { error: error.message } }); + continue; + } + + throw error; + } + + if ([ + 'create', + 'get', + 'update', + 'add', + ].includes(operation)) { + responseData = responseData.data; + } + + Array.isArray(responseData) + ? returnData.push(...responseData) + : returnData.push(responseData); + + } + + return [this.helpers.returnJsonArray(returnData)]; + } +} diff --git a/packages/nodes-base/nodes/MonicaCrm/descriptions/ActivityDescription.ts b/packages/nodes-base/nodes/MonicaCrm/descriptions/ActivityDescription.ts new file mode 100644 index 0000000000..fe326632bd --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/descriptions/ActivityDescription.ts @@ -0,0 +1,324 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const activityOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'activity', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create an activity', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete an activity', + }, + { + name: 'Get', + value: 'get', + description: 'Retrieve an activity', + }, + { + name: 'Get All', + value: 'getAll', + description: 'Retrieve all activities', + }, + { + name: 'Update', + value: 'update', + description: 'Update an activity', + }, + ], + default: 'create', + }, +] as INodeProperties[]; + +export const activityFields = [ + // ---------------------------------------- + // activity: create + // ---------------------------------------- + { + displayName: 'Activity Type', + name: 'activityTypeId', + type: 'options', + required: true, + default: '', + typeOptions: { + loadOptionsMethod: 'getActivityTypes', + }, + displayOptions: { + show: { + resource: [ + 'activity', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Contacts', + name: 'contacts', + description: 'Comma-separated list of IDs of the contacts to associate the activity with', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'activity', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Happened At', + name: 'happenedAt', + description: 'Date when the activity happened', + type: 'dateTime', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'activity', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Summary', + name: 'summary', + description: 'Brief description of the activity - max 255 characters', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'activity', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'activity', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + description: 'Description of the activity - max 100,000 characters', + typeOptions: { + alwaysOpenEditWindow: true, + }, + }, + ], + }, + + // ---------------------------------------- + // activity: delete + // ---------------------------------------- + { + displayName: 'Activity ID', + name: 'activityId', + description: 'ID of the activity to delete', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'activity', + ], + operation: [ + 'delete', + ], + }, + }, + }, + + // ---------------------------------------- + // activity: get + // ---------------------------------------- + { + displayName: 'Activity ID', + name: 'activityId', + description: 'ID of the activity to retrieve', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'activity', + ], + operation: [ + 'get', + ], + }, + }, + }, + + // ---------------------------------------- + // activity: getAll + // ---------------------------------------- + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + default: false, + description: 'Whether to return all results or only up to a given limit', + displayOptions: { + show: { + resource: [ + 'activity', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + default: 50, + description: 'How many results to return', + typeOptions: { + minValue: 1, + }, + displayOptions: { + show: { + resource: [ + 'activity', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + }, + + // ---------------------------------------- + // activity: update + // ---------------------------------------- + { + displayName: 'Activity ID', + name: 'activityId', + description: 'ID of the activity to update', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'activity', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'activity', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Activity Type', + name: 'activity_type_id', + type: 'options', + default: '', + typeOptions: { + loadOptionsMethod: 'getActivityTypes', + }, + }, + { + displayName: 'Contacts', + name: 'contacts', + description: 'IDs of the contacts to associate the activity with', + type: 'string', + default: '', + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + description: 'Description to add more details on the activity - max 100,000 characters', + typeOptions: { + alwaysOpenEditWindow: true, + }, + }, + { + displayName: 'Happened At', + name: 'happened_at', + description: 'Date when the activity happened', + type: 'dateTime', + default: '', + }, + { + displayName: 'Summary', + name: 'summary', + description: 'Brief description of the activity - max 255 characters', + type: 'string', + default: '', + }, + ], + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/MonicaCrm/descriptions/CallDescription.ts b/packages/nodes-base/nodes/MonicaCrm/descriptions/CallDescription.ts new file mode 100644 index 0000000000..1336515f70 --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/descriptions/CallDescription.ts @@ -0,0 +1,259 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const callOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'call', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a call', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a call', + }, + { + name: 'Get', + value: 'get', + description: 'Retrieve a call', + }, + { + name: 'Get All', + value: 'getAll', + description: 'Retrieve all calls', + }, + { + name: 'Update', + value: 'update', + description: 'Update a call', + }, + ], + default: 'create', + }, +] as INodeProperties[]; + +export const callFields = [ + // ---------------------------------------- + // call: create + // ---------------------------------------- + { + displayName: 'Contact ID', + name: 'contactId', + description: 'ID of the contact to associate the call with', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'call', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Called At', + name: 'calledAt', + description: 'Date when the call happened', + type: 'dateTime', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'call', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Description', + name: 'content', + description: 'Description of the call - max 100,000 characters', + typeOptions: { + alwaysOpenEditWindow: true, + }, + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'call', + ], + operation: [ + 'create', + ], + }, + }, + }, + + // ---------------------------------------- + // call: delete + // ---------------------------------------- + { + displayName: 'Call ID', + name: 'callId', + description: 'ID of the call to delete', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'call', + ], + operation: [ + 'delete', + ], + }, + }, + }, + + // ---------------------------------------- + // call: get + // ---------------------------------------- + { + displayName: 'Call ID', + name: 'callId', + description: 'ID of the call to retrieve', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'call', + ], + operation: [ + 'get', + ], + }, + }, + }, + + // ---------------------------------------- + // call: getAll + // ---------------------------------------- + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + default: false, + description: 'Whether to return all results or only up to a given limit', + displayOptions: { + show: { + resource: [ + 'call', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + default: 50, + description: 'How many results to return', + typeOptions: { + minValue: 1, + }, + displayOptions: { + show: { + resource: [ + 'call', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + }, + + // ---------------------------------------- + // call: update + // ---------------------------------------- + { + displayName: 'Call ID', + name: 'callId', + description: 'ID of the call to update', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'call', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'call', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Called At', + name: 'calledAt', + description: 'Date when the call happened', + type: 'dateTime', + default: '', + }, + { + displayName: 'Contact ID', + name: 'contactId', + description: 'ID of the contact to associate the call with', + type: 'string', + default: '', + }, + { + displayName: 'Description', + name: 'content', + description: 'Description of the call - max 100,000 characters', + type: 'string', + default: '', + }, + ], + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/MonicaCrm/descriptions/ContactDescription.ts b/packages/nodes-base/nodes/MonicaCrm/descriptions/ContactDescription.ts new file mode 100644 index 0000000000..63027d6ace --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/descriptions/ContactDescription.ts @@ -0,0 +1,400 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const contactOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'contact', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a contact', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a contact', + }, + { + name: 'Get', + value: 'get', + description: 'Retrieve a contact', + }, + { + name: 'Get All', + value: 'getAll', + description: 'Retrieve all contacts', + }, + { + name: 'Update', + value: 'update', + description: 'Update a contact', + }, + ], + default: 'create', + }, +] as INodeProperties[]; + +export const contactFields = [ + // ---------------------------------------- + // contact: create + // ---------------------------------------- + { + displayName: 'First Name', + name: 'firstName', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Gender', + name: 'genderId', + type: 'options', + required: true, + default: '', + typeOptions: { + loadOptionsMethod: 'getGenders', + }, + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Birthdate', + name: 'birthdate', + type: 'dateTime', + default: '', + }, + { + displayName: 'Deceased Date', + name: 'deceasedDate', + type: 'dateTime', + default: '', + }, + { + displayName: 'Is Deceased', + name: 'isDeceased', + description: 'Whether the contact has passed away', + type: 'boolean', + default: false, + }, + { + displayName: 'Last Name', + name: 'last_name', + type: 'string', + default: '', + }, + { + displayName: 'Nickname', + name: 'nickname', + type: 'string', + default: '', + }, + { + displayName: 'Type', + name: 'is_partial', + type: 'options', + default: false, + options: [ + { + name: 'Real', + value: false, + description: 'Contact with their own contact sheet', + }, + { + name: 'Partial', + value: true, + description: 'Contact without their own contact sheet', + }, + ], + }, + ], + }, + + // ---------------------------------------- + // contact: delete + // ---------------------------------------- + { + displayName: 'Contact ID', + name: 'contactId', + description: 'ID of the contact to delete', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'delete', + ], + }, + }, + }, + + // ---------------------------------------- + // contact: get + // ---------------------------------------- + { + displayName: 'Contact ID', + name: 'contactId', + description: 'ID of the contact to retrieve', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'get', + ], + }, + }, + }, + + // ---------------------------------------- + // contact: getAll + // ---------------------------------------- + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + default: false, + description: 'Whether to return all results or only up to a given limit', + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + default: 50, + description: 'How many results to return', + typeOptions: { + minValue: 1, + }, + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + }, + { + displayName: 'Filters', + name: 'filters', + type: 'collection', + placeholder: 'Add Field', + default: {}, + options: [ + { + displayName: 'Search Term', + name: 'query', + type: 'string', + default: '', + description: 'Search term to filter results by', + }, + { + displayName: 'Sort', + name: 'sort', + type: 'options', + options: [ + { + name: 'Ascended Created At', + value: 'created_at', + }, + { + name: 'Descended Created At', + value: '-created_at', + }, + { + name: 'Ascended Updated At', + value: 'updated_at', + }, + { + name: 'Descended Updated At', + value: '-updated_at', + }, + ], + default: '', + }, + ], + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + + // ---------------------------------------- + // contact: update + // ---------------------------------------- + { + displayName: 'Contact ID', + name: 'contactId', + description: 'ID of the contact to update', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Birthdate', + name: 'birthdate', + type: 'dateTime', + default: '', + }, + { + displayName: 'Deceased Date', + name: 'deceased_date', + type: 'dateTime', + default: '', + }, + { + displayName: 'First Name', + name: 'first_name', + type: 'string', + default: '', + }, + { + displayName: 'Gender', + name: 'gender_id', + type: 'options', + default: '', + typeOptions: { + loadOptionsMethod: 'getGenders', + }, + }, + { + displayName: 'Is Deceased', + name: 'is_deceased', + description: 'Whether the contact has passed away', + type: 'boolean', + default: false, + }, + { + displayName: 'Last Name', + name: 'last_name', + type: 'string', + default: '', + }, + { + displayName: 'Nickname', + name: 'nickname', + type: 'string', + default: '', + }, + { + displayName: 'Type', + name: 'is_partial', + type: 'options', + default: false, + options: [ + { + name: 'Real', + value: false, + description: 'Contact with their own contact sheet', + }, + { + name: 'Partial', + value: true, + description: 'Contact without their own contact sheet', + }, + ], + }, + ], + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/MonicaCrm/descriptions/ContactFieldDescription.ts b/packages/nodes-base/nodes/MonicaCrm/descriptions/ContactFieldDescription.ts new file mode 100644 index 0000000000..cca52a7e63 --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/descriptions/ContactFieldDescription.ts @@ -0,0 +1,292 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const contactFieldOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'contactField', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a contact field', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a contact field', + }, + { + name: 'Get', + value: 'get', + description: 'Retrieve a contact field', + }, + // { + // name: 'Get All', + // value: 'getAll', + // description: 'Retrieve all contact fields', + // }, + { + name: 'Update', + value: 'update', + description: 'Update a contact field', + }, + ], + default: 'create', + }, +] as INodeProperties[]; + +export const contactFieldFields = [ + // ---------------------------------------- + // contactField: create + // ---------------------------------------- + { + displayName: 'Contact ID', + name: 'contactId', + description: 'ID of the contact to associate the contact field with', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contactField', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Contact Field Type', + name: 'contactFieldTypeId', + type: 'options', + required: true, + typeOptions: { + loadOptionsMethod: 'getContactFieldTypes', + }, + default: '', + displayOptions: { + show: { + resource: [ + 'contactField', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Content', + name: 'data', + description: 'Content of the contact field - max 255 characters', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contactField', + ], + operation: [ + 'create', + ], + }, + }, + }, + + // ---------------------------------------- + // contactField: delete + // ---------------------------------------- + { + displayName: 'Contact Field ID', + name: 'contactFieldId', + description: 'ID of the contactField to delete', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contactField', + ], + operation: [ + 'delete', + ], + }, + }, + }, + + // ---------------------------------------- + // contactField: get + // ---------------------------------------- + { + displayName: 'Contact Field ID', + name: 'contactFieldId', + description: 'ID of the contact field to retrieve', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contactField', + ], + operation: [ + 'get', + ], + }, + }, + }, + + // ---------------------------------------- + // contactField: getAll + // ---------------------------------------- + { + displayName: 'Contact ID', + name: 'contactId', + description: 'ID of the contact whose fields to retrieve', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contactField', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + default: false, + description: 'Whether to return all results or only up to a given limit', + displayOptions: { + show: { + resource: [ + 'contactField', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + default: 50, + description: 'How many results to return', + typeOptions: { + minValue: 1, + }, + displayOptions: { + show: { + resource: [ + 'contactField', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + }, + + // ---------------------------------------- + // contactField: update + // ---------------------------------------- + { + displayName: 'Contact ID', + name: 'contactId', + description: 'ID of the contact to associate the contact field with', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contactField', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Contact Field ID', + name: 'contactFieldId', + description: 'ID of the contact field to update', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contactField', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Contact Field Type ID', + name: 'contactFieldTypeId', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getContactFieldTypes', + }, + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contactField', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Content', + name: 'data', + description: 'Content of the contact field - max 255 characters', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contactField', + ], + operation: [ + 'update', + ], + }, + }, + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/MonicaCrm/descriptions/ContactTagDescription.ts b/packages/nodes-base/nodes/MonicaCrm/descriptions/ContactTagDescription.ts new file mode 100644 index 0000000000..d786e832c7 --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/descriptions/ContactTagDescription.ts @@ -0,0 +1,117 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const contactTagOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'contactTag', + ], + }, + }, + options: [ + { + name: 'Add', + value: 'add', + }, + { + name: 'Remove', + value: 'remove', + }, + ], + default: 'add', + }, +] as INodeProperties[]; + +export const contactTagFields = [ + // ---------------------------------------- + // tag: add + // ---------------------------------------- + { + displayName: 'Contact ID', + name: 'contactId', + description: 'ID of the contact to add a tag to', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contactTag', + ], + operation: [ + 'add', + ], + }, + }, + }, + { + displayName: 'Tags', + name: 'tagsToAdd', + description: 'Tags to add to the contact', + type: 'multiOptions', + typeOptions: { + loadOptionsMethod: 'getTagsToAdd', + }, + required: true, + default: [], + displayOptions: { + show: { + resource: [ + 'contactTag', + ], + operation: [ + 'add', + ], + }, + }, + }, + + // ---------------------------------------- + // tag: remove + // ---------------------------------------- + { + displayName: 'Contact ID', + name: 'contactId', + description: 'ID of the contact to remove the tag from', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contactTag', + ], + operation: [ + 'remove', + ], + }, + }, + }, + { + displayName: 'Tags', + name: 'tagsToRemove', + description: 'Tags to remove from the contact', + type: 'multiOptions', + required: true, + typeOptions: { + loadOptionsMethod: 'getTagsToRemove', + }, + default: [], + displayOptions: { + show: { + resource: [ + 'contactTag', + ], + operation: [ + 'remove', + ], + }, + }, + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/MonicaCrm/descriptions/ConversationDescription.ts b/packages/nodes-base/nodes/MonicaCrm/descriptions/ConversationDescription.ts new file mode 100644 index 0000000000..9c9f97a392 --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/descriptions/ConversationDescription.ts @@ -0,0 +1,207 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const conversationOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'conversation', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a conversation', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a conversation', + }, + { + name: 'Get', + value: 'get', + description: 'Retrieve a conversation', + }, + { + name: 'Update', + value: 'update', + description: 'Update a conversation', + }, + ], + default: 'create', + }, +] as INodeProperties[]; + +export const conversationFields = [ + // ---------------------------------------- + // conversation: create + // ---------------------------------------- + { + displayName: 'Contact ID', + name: 'contactId', + description: 'ID of the contact to associate the conversation with', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'conversation', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Contact Field Type', + name: 'contactFieldTypeId', + type: 'options', + required: true, + default: '', + typeOptions: { + loadOptionsMethod: 'getContactFieldTypes', + }, + displayOptions: { + show: { + resource: [ + 'conversation', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Happened At', + name: 'happenedAt', + description: 'Date when the conversation happened', + type: 'dateTime', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'conversation', + ], + operation: [ + 'create', + ], + }, + }, + }, + + // ---------------------------------------- + // conversation: delete + // ---------------------------------------- + { + displayName: 'Conversation ID', + name: 'conversationId', + description: 'ID of the conversation to delete', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'conversation', + ], + operation: [ + 'delete', + ], + }, + }, + }, + + // ---------------------------------------- + // conversation: get + // ---------------------------------------- + { + displayName: 'Conversation ID', + name: 'conversationId', + description: 'ID of the conversation to retrieve', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'conversation', + ], + operation: [ + 'get', + ], + }, + }, + }, + + // ---------------------------------------- + // conversation: update + // ---------------------------------------- + { + displayName: 'Conversation ID', + name: 'conversationId', + description: 'ID of the conversation to update', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'conversation', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Contact Field Type', + name: 'contactFieldTypeId', + type: 'options', + required: true, + default: '', + typeOptions: { + loadOptionsMethod: 'getContactFieldTypes', + }, + displayOptions: { + show: { + resource: [ + 'conversation', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Happened At', + name: 'happenedAt', + description: 'Date when the conversation happened', + type: 'dateTime', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'conversation', + ], + operation: [ + 'update', + ], + }, + }, + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/MonicaCrm/descriptions/ConversationMessageDescription.ts b/packages/nodes-base/nodes/MonicaCrm/descriptions/ConversationMessageDescription.ts new file mode 100644 index 0000000000..3fc42640f8 --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/descriptions/ConversationMessageDescription.ts @@ -0,0 +1,217 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const conversationMessageOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'conversationMessage', + ], + }, + }, + options: [ + { + name: 'Add', + value: 'add', + description: 'Add a message to a conversation', + }, + { + name: 'Update', + value: 'update', + description: 'Update a message in a conversation', + }, + ], + default: 'add', + }, +] as INodeProperties[]; + +export const conversationMessageFields = [ + // ---------------------------------------- + // conversationMessage: add + // ---------------------------------------- + { + displayName: 'Conversation ID', + name: 'conversationId', + description: 'ID of the contact whose conversation', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'conversationMessage', + ], + operation: [ + 'add', + ], + }, + }, + }, + { + displayName: 'Content', + name: 'content', + description: 'Content of the message', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'conversationMessage', + ], + operation: [ + 'add', + ], + }, + }, + }, + { + displayName: 'Written At', + name: 'writtenAt', + description: 'Date when the message was written', + type: 'dateTime', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'conversationMessage', + ], + operation: [ + 'add', + ], + }, + }, + }, + { + displayName: 'Written By', + name: 'writtenByMe', + description: 'Author of the message', + type: 'options', + required: true, + default: true, + options: [ + { + name: 'User', + value: true, + }, + { + name: 'Contact', + value: false, + }, + ], + displayOptions: { + show: { + resource: [ + 'conversationMessage', + ], + operation: [ + 'add', + ], + }, + }, + }, + + // ---------------------------------------- + // conversationMessage: update + // ---------------------------------------- + { + displayName: 'Message ID', + name: 'messageId', + description: 'ID of the message to update', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'conversationMessage', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Conversation ID', + name: 'conversationId', + description: 'ID of the conversation whose message to update', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'conversationMessage', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'conversationMessage', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Contact ID', + name: 'contact_id', + description: 'ID of the contact to associate the conversationMessage with', + type: 'string', + default: '', + }, + { + displayName: 'Content', + name: 'content', + description: 'Content of the message', + type: 'string', + default: '', + }, + { + displayName: 'Written At', + name: 'written_at', + description: 'Date when the message was written', + type: 'dateTime', + default: '', + }, + { + displayName: 'Written By', + name: 'written_by_me', + description: 'Author of the message', + type: 'options', + required: true, + default: true, + options: [ + { + name: 'User', + value: true, + }, + { + name: 'Contact', + value: false, + }, + ], + }, + ], + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/MonicaCrm/descriptions/JournalEntryDescription.ts b/packages/nodes-base/nodes/MonicaCrm/descriptions/JournalEntryDescription.ts new file mode 100644 index 0000000000..8610e7c592 --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/descriptions/JournalEntryDescription.ts @@ -0,0 +1,237 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const journalEntryOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'journalEntry', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a journal entry', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a journal entry', + }, + { + name: 'Get', + value: 'get', + description: 'Retrieve a journal entry', + }, + { + name: 'Get All', + value: 'getAll', + description: 'Retrieve all journal entries', + }, + { + name: 'Update', + value: 'update', + description: 'Update a journal entry', + }, + ], + default: 'create', + }, +] as INodeProperties[]; + +export const journalEntryFields = [ + // ---------------------------------------- + // journalEntry: create + // ---------------------------------------- + { + displayName: 'Title', + name: 'title', + description: 'Title of the journal entry - max 250 characters', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'journalEntry', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Content', + name: 'post', + description: 'Content of the journal entry - max 100,000 characters', + type: 'string', + required: true, + default: '', + typeOptions: { + alwaysOpenEditWindow: true, + }, + displayOptions: { + show: { + resource: [ + 'journalEntry', + ], + operation: [ + 'create', + ], + }, + }, + }, + + // ---------------------------------------- + // journalEntry: delete + // ---------------------------------------- + { + displayName: 'Journal Entry ID', + name: 'journalId', + description: 'ID of the journal entry to delete', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'journalEntry', + ], + operation: [ + 'delete', + ], + }, + }, + }, + + // ---------------------------------------- + // journalEntry: get + // ---------------------------------------- + { + displayName: 'Journal Entry ID', + name: 'journalId', + description: 'ID of the journal entry to retrieve', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'journalEntry', + ], + operation: [ + 'get', + ], + }, + }, + }, + + // ---------------------------------------- + // journalEntry: getAll + // ---------------------------------------- + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + default: false, + description: 'Whether to return all results or only up to a given limit', + displayOptions: { + show: { + resource: [ + 'journalEntry', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + default: 50, + description: 'How many results to return', + typeOptions: { + minValue: 1, + }, + displayOptions: { + show: { + resource: [ + 'journalEntry', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + }, + + // ---------------------------------------- + // journalEntry: update + // ---------------------------------------- + { + displayName: 'Journal Entry ID', + name: 'journalId', + description: 'ID of the journal entry to update', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'journalEntry', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'journalEntry', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Content', + name: 'post', + description: 'Content of the journal entry - max 100,000 characters', + type: 'string', + default: '', + typeOptions: { + alwaysOpenEditWindow: true, + }, + }, + { + displayName: 'Title', + name: 'title', + description: 'Title of the journal entry - max 250 characters', + type: 'string', + default: '', + }, + ], + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/MonicaCrm/descriptions/NoteDescription.ts b/packages/nodes-base/nodes/MonicaCrm/descriptions/NoteDescription.ts new file mode 100644 index 0000000000..d4c51cb83a --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/descriptions/NoteDescription.ts @@ -0,0 +1,269 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const noteOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'note', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a note', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a note', + }, + { + name: 'Get', + value: 'get', + description: 'Retrieve a note', + }, + { + name: 'Get All', + value: 'getAll', + description: 'Retrieve all notes', + }, + { + name: 'Update', + value: 'update', + description: 'Update a note', + }, + ], + default: 'create', + }, +] as INodeProperties[]; + +export const noteFields = [ + // ---------------------------------------- + // note: create + // ---------------------------------------- + { + displayName: 'Contact ID', + name: 'contactId', + description: 'ID of the contact to associate the note with', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'note', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Body', + name: 'body', + description: 'Body of the note - max 100,000 characters', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'note', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'note', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Is Favorited', + name: 'isFavorited', + description: 'Whether the note has been favorited', + type: 'boolean', + default: false, + }, + ], + }, + + // ---------------------------------------- + // note: delete + // ---------------------------------------- + { + displayName: 'Note ID', + name: 'noteId', + description: 'ID of the note to delete', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'note', + ], + operation: [ + 'delete', + ], + }, + }, + }, + + // ---------------------------------------- + // note: get + // ---------------------------------------- + { + displayName: 'Note ID', + name: 'noteId', + description: 'ID of the note to retrieve', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'note', + ], + operation: [ + 'get', + ], + }, + }, + }, + + // ---------------------------------------- + // note: getAll + // ---------------------------------------- + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + default: false, + description: 'Whether to return all results or only up to a given limit', + displayOptions: { + show: { + resource: [ + 'note', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + default: 50, + description: 'How many results to return', + typeOptions: { + minValue: 1, + }, + displayOptions: { + show: { + resource: [ + 'note', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + }, + + // ---------------------------------------- + // note: update + // ---------------------------------------- + { + displayName: 'Note ID', + name: 'noteId', + description: 'ID of the note to update', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'note', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'note', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Body', + name: 'body', + description: 'Body of the note - max 100,000 characters', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + }, + { + displayName: 'Contact ID', + name: 'contact_id', + description: 'ID of the contact to associate the note with', + type: 'string', + default: '', + }, + { + displayName: 'Is Favorited', + name: 'is_favorited', + description: 'Whether the note has been favorited', + type: 'boolean', + }, + ], + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/MonicaCrm/descriptions/ReminderDescription.ts b/packages/nodes-base/nodes/MonicaCrm/descriptions/ReminderDescription.ts new file mode 100644 index 0000000000..fe51030d0a --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/descriptions/ReminderDescription.ts @@ -0,0 +1,394 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const reminderOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'reminder', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a reminder', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a reminder', + }, + { + name: 'Get', + value: 'get', + description: 'Retrieve a reminder', + }, + { + name: 'Get All', + value: 'getAll', + description: 'Retrieve all reminders', + }, + { + name: 'Update', + value: 'update', + description: 'Update a reminder', + }, + ], + default: 'create', + }, +] as INodeProperties[]; + +export const reminderFields = [ + // ---------------------------------------- + // reminder: create + // ---------------------------------------- + { + displayName: 'Contact ID', + name: 'contactId', + type: 'string', + default: '', + description: 'ID of the contact to associate the reminder with', + displayOptions: { + show: { + resource: [ + 'reminder', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Frequency Type', + name: 'frequencyType', + description: 'Type of frequency of the reminder', + type: 'options', + required: true, + default: 'one_time', + options: [ + { + name: 'Once', + value: 'one_time', + }, + { + name: 'Weekly', + value: 'week', + }, + { + name: 'Monthly', + value: 'month', + }, + { + name: 'Yearly', + value: 'year', + }, + ], + displayOptions: { + show: { + resource: [ + 'reminder', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Recurring Interval', + name: 'frequencyNumber', + type: 'number', + default: 0, + description: 'Interval for the reminder', + displayOptions: { + show: { + resource: [ + 'reminder', + ], + operation: [ + 'create', + ], + frequencyType: [ + 'week', + 'month', + 'year', + ], + }, + }, + }, + { + displayName: 'Initial Date', + name: 'initialDate', + description: 'Date of the reminder', + type: 'dateTime', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'reminder', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Title', + name: 'title', + description: 'Title of the reminder - max 100,000 characters', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'reminder', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'reminder', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + description: 'Description about the reminder - Max 100,000 characters', + typeOptions: { + alwaysOpenEditWindow: true, + }, + }, + ], + }, + + // ---------------------------------------- + // reminder: delete + // ---------------------------------------- + { + displayName: 'Reminder ID', + name: 'reminderId', + description: 'ID of the reminder to delete', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'reminder', + ], + operation: [ + 'delete', + ], + }, + }, + }, + + // ---------------------------------------- + // reminder: get + // ---------------------------------------- + { + displayName: 'Reminder ID', + name: 'reminderId', + description: 'ID of the reminder to retrieve', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'reminder', + ], + operation: [ + 'get', + ], + }, + }, + }, + + // ---------------------------------------- + // reminder: getAll + // ---------------------------------------- + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + default: false, + description: 'Whether to return all results or only up to a given limit', + displayOptions: { + show: { + resource: [ + 'reminder', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + default: 50, + description: 'How many results to return', + typeOptions: { + minValue: 1, + }, + displayOptions: { + show: { + resource: [ + 'reminder', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + }, + + // ---------------------------------------- + // reminder: update + // ---------------------------------------- + { + displayName: 'Reminder ID', + name: 'reminderId', + description: 'ID of the reminder to update', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'reminder', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'reminder', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Contact ID', + name: 'contact_id', + type: 'string', + default: '', + description: 'ID of the contact to associate the reminder with', + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + description: 'Description about the reminder - Max 100,000 characters', + typeOptions: { + alwaysOpenEditWindow: true, + }, + }, + { + displayName: 'Frequency Type', + name: 'frequency_type', + description: 'Frequency of the reminder', + type: 'options', + default: 'one_time', + options: [ + { + name: 'One Time', + value: 'one_time', + }, + { + name: 'Week', + value: 'week', + }, + { + name: 'Month', + value: 'month', + }, + { + name: 'Year', + value: 'year', + }, + ], + }, + { + displayName: 'Initial Date', + name: 'initial_data', + description: 'Date of the reminder', + type: 'dateTime', + default: '', + }, + { + displayName: 'Recurring Interval', + name: 'frequency_number', + type: 'number', + default: 0, + description: 'Interval for the reminder', + displayOptions: { + show: { + frequency_type: [ + 'week', + 'month', + 'year', + ], + }, + }, + }, + + { + displayName: 'Title', + name: 'title', + description: 'Title of the reminder - max 100,000 characters', + type: 'string', + default: '', + }, + ], + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/MonicaCrm/descriptions/TagDescription.ts b/packages/nodes-base/nodes/MonicaCrm/descriptions/TagDescription.ts new file mode 100644 index 0000000000..ed293abecf --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/descriptions/TagDescription.ts @@ -0,0 +1,198 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const tagOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'tag', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a tag', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a tag', + }, + { + name: 'Get', + value: 'get', + description: 'Retrieve a tag', + }, + { + name: 'Get All', + value: 'getAll', + description: 'Retrieve all tags', + }, + { + name: 'Update', + value: 'update', + description: 'Update a tag', + }, + ], + default: 'create', + }, +] as INodeProperties[]; + +export const tagFields = [ + // ---------------------------------------- + // tag: create + // ---------------------------------------- + { + displayName: 'Name', + name: 'name', + description: 'Name of the tag - max 250 characters', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'tag', + ], + operation: [ + 'create', + ], + }, + }, + }, + + // ---------------------------------------- + // tag: delete + // ---------------------------------------- + { + displayName: 'Tag ID', + name: 'tagId', + description: 'ID of the tag to delete', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'tag', + ], + operation: [ + 'delete', + ], + }, + }, + }, + + // ---------------------------------------- + // tag: get + // ---------------------------------------- + { + displayName: 'Tag ID', + name: 'tagId', + description: 'ID of the tag to retrieve', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'tag', + ], + operation: [ + 'get', + ], + }, + }, + }, + + // ---------------------------------------- + // tag: getAll + // ---------------------------------------- + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + default: false, + description: 'Whether to return all results or only up to a given limit', + displayOptions: { + show: { + resource: [ + 'tag', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + default: 50, + description: 'How many results to return', + typeOptions: { + minValue: 1, + }, + displayOptions: { + show: { + resource: [ + 'tag', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + }, + + // ---------------------------------------- + // tag: update + // ---------------------------------------- + { + displayName: 'Tag ID', + name: 'tagId', + description: 'ID of the tag to update', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'tag', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Name', + name: 'name', + description: 'Name of the tag - max 250 characters', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'tag', + ], + operation: [ + 'update', + ], + }, + }, + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/MonicaCrm/descriptions/TaskDescription.ts b/packages/nodes-base/nodes/MonicaCrm/descriptions/TaskDescription.ts new file mode 100644 index 0000000000..dd3a603682 --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/descriptions/TaskDescription.ts @@ -0,0 +1,277 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const taskOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'task', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a task', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a task', + }, + { + name: 'Get', + value: 'get', + description: 'Retrieve a task', + }, + { + name: 'Get All', + value: 'getAll', + description: 'Retrieve all tasks', + }, + { + name: 'Update', + value: 'update', + description: 'Update a task', + }, + ], + default: 'create', + }, +] as INodeProperties[]; + +export const taskFields = [ + // ---------------------------------------- + // task: create + // ---------------------------------------- + { + displayName: 'Contact ID', + name: 'contactId', + description: 'ID of the contact to associate the task with', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Title', + name: 'title', + description: 'Title of the task entry - max 250 characters', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + description: 'Description of the task - max 100,000 characters', + typeOptions: { + alwaysOpenEditWindow: true, + }, + }, + ], + }, + + // ---------------------------------------- + // task: delete + // ---------------------------------------- + { + displayName: 'Task ID', + name: 'taskId', + description: 'ID of the task to delete', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'delete', + ], + }, + }, + }, + + // ---------------------------------------- + // task: get + // ---------------------------------------- + { + displayName: 'Task ID', + name: 'taskId', + description: 'ID of the task to retrieve', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'get', + ], + }, + }, + }, + + // ---------------------------------------- + // task: getAll + // ---------------------------------------- + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + default: false, + description: 'Whether to return all results or only up to a given limit', + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + default: 50, + description: 'How many results to return', + typeOptions: { + minValue: 1, + }, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + }, + + // ---------------------------------------- + // task: update + // ---------------------------------------- + { + displayName: 'Task ID', + name: 'taskId', + description: 'ID of the task to update', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Contact ID', + name: 'contactId', + description: 'ID of the contact to associate the task with', + type: 'string', + default: '', + }, + { + displayName: 'Completed', + name: 'completed', + description: 'Whether the task has been completed', + type: 'boolean', + default: false, + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + description: 'Description of the task - max 100,000 characters', + typeOptions: { + alwaysOpenEditWindow: true, + }, + }, + { + displayName: 'Title', + name: 'title', + description: 'Title of the task entry - max 250 characters', + type: 'string', + default: '', + }, + ], + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/MonicaCrm/descriptions/index.ts b/packages/nodes-base/nodes/MonicaCrm/descriptions/index.ts new file mode 100644 index 0000000000..973a631c28 --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/descriptions/index.ts @@ -0,0 +1,12 @@ +export * from './ActivityDescription'; +export * from './CallDescription'; +export * from './ContactDescription'; +export * from './ContactFieldDescription'; +export * from './ContactTagDescription'; +export * from './ConversationDescription'; +export * from './ConversationMessageDescription'; +export * from './JournalEntryDescription'; +export * from './NoteDescription'; +export * from './ReminderDescription'; +export * from './TagDescription'; +export * from './TaskDescription'; diff --git a/packages/nodes-base/nodes/MonicaCrm/monicaCrm.png b/packages/nodes-base/nodes/MonicaCrm/monicaCrm.png new file mode 100644 index 0000000000..1600e626fe Binary files /dev/null and b/packages/nodes-base/nodes/MonicaCrm/monicaCrm.png differ diff --git a/packages/nodes-base/nodes/MonicaCrm/types.d.ts b/packages/nodes-base/nodes/MonicaCrm/types.d.ts new file mode 100644 index 0000000000..96361ec2f0 --- /dev/null +++ b/packages/nodes-base/nodes/MonicaCrm/types.d.ts @@ -0,0 +1,13 @@ +import { IDataObject } from "n8n-workflow"; + +export type LoaderGetResponse = { + data: Array<{ + id: string; + name: string; + }> +} & IDataObject; + +export type Option = { + value: string; + name: string; +}; diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index a1dd7ea7b6..006a851d8f 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -172,6 +172,7 @@ "dist/credentials/MicrosoftToDoOAuth2Api.credentials.js", "dist/credentials/MindeeReceiptApi.credentials.js", "dist/credentials/MindeeInvoiceApi.credentials.js", + "dist/credentials/MonicaCrmApi.credentials.js", "dist/credentials/MoceanApi.credentials.js", "dist/credentials/MondayComApi.credentials.js", "dist/credentials/MondayComOAuth2Api.credentials.js", @@ -469,6 +470,7 @@ "dist/nodes/Microsoft/Teams/MicrosoftTeams.node.js", "dist/nodes/Microsoft/ToDo/MicrosoftToDo.node.js", "dist/nodes/Mindee/Mindee.node.js", + "dist/nodes/MonicaCrm/MonicaCrm.node.js", "dist/nodes/MoveBinaryData.node.js", "dist/nodes/Mocean/Mocean.node.js", "dist/nodes/MondayCom/MondayCom.node.js",