Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vtiger): query records action and element selection field for search record action #3829

Merged
merged 2 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/pieces/community/vtiger/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@activepieces/piece-vtiger",
"version": "0.1.8",
"version": "1.1.8",
"dependencies": {
"@activepieces/pieces-framework": "*",
"@activepieces/pieces-common": "*",
Expand Down
2 changes: 2 additions & 0 deletions packages/pieces/community/vtiger/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { searchRecords } from './lib/actions/search-record';
import { updateRecord } from './lib/actions/update-record';
import { instanceLogin, isBaseUrl } from './lib/common';
import { newOrUpdatedRecord } from './lib/triggers/new-or-updated-record';
import { queryRecords } from './lib/actions/query-records';

const markdownProperty = `
To obtain your Access Key, follow these steps:
Expand Down Expand Up @@ -110,6 +111,7 @@ export const vtiger = createPiece({
getRecord,
updateRecord,
deleteRecord,
queryRecords,
searchRecords,
makeAPICall,
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
export const makeAPICall = createAction({
name: 'make_api_call',
auth: vtigerAuth,
displayName: 'Make API Call',
displayName: 'Custom API Call',
description: 'Performs an arbitrary authorized API call. ',
props: {
method: Property.StaticDropdown<HttpMethod>({
Expand Down
57 changes: 57 additions & 0 deletions packages/pieces/community/vtiger/src/lib/actions/query-records.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Property, createAction } from '@activepieces/pieces-framework';
import { vtigerAuth } from '../..';
import {
Operation,
elementTypeProperty,
instanceLogin,
prepareHttpRequest,
} from '../common';
import { httpClient } from '@activepieces/pieces-common';

//Docs: https://code.vtiger.com/vtiger/vtigercrm-manual/-/wikis/Webservice-Docs
//Extra: https://help.vtiger.com/article/147111249-Rest-API-Manual

export const queryRecords = createAction({
name: 'query_records',
auth: vtigerAuth,
displayName: 'Query Records',
description: 'Query records by SQL statement.',
props: {
query: Property.LongText({
displayName: 'Query',
description:
'Enter the query statement, e.g. SELECT count(*) FROM Contacts;',
required: true,
}),
},
async run({ propsValue, auth }) {
const vtigerInstance = await instanceLogin(
auth.instance_url,
auth.username,
auth.password
);
if (vtigerInstance === null) return;

const response = await httpClient.sendRequest<{
success: boolean;
result: Record<string, unknown>[];
}>(
prepareHttpRequest(
auth.instance_url,
vtigerInstance.sessionId ?? vtigerInstance.sessionName,
'query' as Operation,
{ query: propsValue.query }
)
);

if (response.body.success) {
return response.body.result;
} else {
console.debug(response);

return {
error: 'Unexpected outcome!',
};
}
},
});
114 changes: 51 additions & 63 deletions packages/pieces/community/vtiger/src/lib/actions/search-record.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import {
DynamicPropsValue,
PiecePropValueSchema,
Property,
createAction,
} from '@activepieces/pieces-framework';
import { vtigerAuth } from '../..';
import { Operation, instanceLogin, prepareHttpRequest } from '../common';
import { httpClient } from '@activepieces/pieces-common';
import {
VTigerAuthValue,
queryRecords,
countRecords,
elementTypeProperty,
generateElementFields,
instanceLogin,
} from '../common';

//Docs: https://code.vtiger.com/vtiger/vtigercrm-manual/-/wikis/Webservice-Docs
//Extra: https://help.vtiger.com/article/147111249-Rest-API-Manual
Expand All @@ -16,64 +22,39 @@ export const searchRecords = createAction({
displayName: 'Search Records',
description: 'Search for a record.',
props: {
search_by: Property.StaticDropdown({
displayName: 'Search By',
description: `Select the mode of search for your records`,
required: true,
defaultValue: 'filter',
options: {
options: [
{ label: 'Filter', value: 'filter' },
{ label: 'Query', value: 'query' },
],
},
}),
search: Property.DynamicProperties({
elementType: elementTypeProperty,
fields: Property.DynamicProperties({
displayName: 'Search Fields',
description: 'Add new fields to be created in the new record',
description: 'Enter your filter criteria',
required: true,
refreshers: ['search_by'],
props: async ({ auth, search_by }) => {
if (!auth || !search_by) {
refreshers: ['elementType'],
props: async ({ auth, elementType }) => {
if (!auth || !elementType) {
return {};
}

const fields: DynamicPropsValue = {};

if ((search_by as unknown as string) === 'filter') {
fields['filter'] = Property.DynamicProperties({
displayName: 'filter',
description: `Enter your filter criteria`,
required: true,
refreshers: ['search_by'],
props: async ({ search_by }) => {
console.debug('search_by', search_by);
const instance = await instanceLogin(
(auth as PiecePropValueSchema<typeof vtigerAuth>).instance_url,
(auth as PiecePropValueSchema<typeof vtigerAuth>).username,
(auth as PiecePropValueSchema<typeof vtigerAuth>).password
);

return {
simple: Property.LongText({
displayName: 'query',
description: `Enter the query to search for record new record`,
required: true,
}),
} as DynamicPropsValue;
},
});
} else {
fields['query'] = Property.LongText({
displayName: 'query',
description: `Enter the query to search for record new record`,
required: true,
});
if (instance === null) {
return {};
}

return fields;
return generateElementFields(
auth as VTigerAuthValue,
elementType as unknown as string,
{},
true
);
},
}),
limit: Property.Number({
displayName: 'Limit',
description: 'Enter the maximum number of records to return.',
defaultValue: 100,
required: true,
required: false,
}),
},
async run({ propsValue, auth }) {
Expand All @@ -84,23 +65,30 @@ export const searchRecords = createAction({
);
if (vtigerInstance === null) return;

const httpRequest = prepareHttpRequest(
auth.instance_url,
vtigerInstance.sessionId ?? vtigerInstance.sessionName,
'query' as Operation,
{}
);
const count = await countRecords(auth, propsValue.elementType as string);
if (count > 0) {
const records: Record<string, unknown>[] = await queryRecords(
auth,
propsValue.elementType as string,
0,
count
);

const response = await httpClient.sendRequest<Record<string, unknown>[]>(
httpRequest
);
const filtered = records.filter((record) => {
return Object.entries(propsValue['fields']).every(([key, value]) => {
if (typeof value === 'string') {
return (record[key] as unknown as string)
.toLowerCase()
.includes(value.toLowerCase());
} else {
return record[key] === value.toLowerCase();
}
});
});

if ([200, 201].includes(response.status)) {
return response.body;
return propsValue.limit ? filtered.slice(0, propsValue.limit) : filtered;
} else {
return [];
}

return {
error: 'Unexpected outcome!',
};
},
});