Skip to content
This repository has been archived by the owner on Nov 6, 2023. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'upstream/dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
soyombo-baterdene committed Oct 24, 2023
2 parents 6d486a2 + fb2e477 commit 01d7229
Show file tree
Hide file tree
Showing 15 changed files with 315 additions and 131 deletions.
3 changes: 3 additions & 0 deletions builder/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/erxes

*.log
1 change: 1 addition & 0 deletions cli/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/enabled-services.json
2 changes: 1 addition & 1 deletion cli/commands/dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ module.exports.devCmd = async program => {
PORT: 4000,
CLIENT_PORTAL_DOMAINS: configs.client_portal_domains || '',
...commonEnv,
...((configs.gateway || {}).envs || {})
...((configs.gateway || {}).extra_env || {})
}
});

Expand Down
41 changes: 31 additions & 10 deletions packages/api-utils/src/automations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ export const replacePlaceHolders = async ({
target,
isRelated = true,
getRelatedValue,
relatedValueProps
relatedValueProps,
complexFields
}: {
models;
subdomain: string;
Expand All @@ -17,6 +18,7 @@ export const replacePlaceHolders = async ({
isRelated?: boolean;
getRelatedValue: any;
relatedValueProps?: any;
complexFields?: string[];
}) => {
if (actionData) {
const targetKeys = Object.keys(target);
Expand Down Expand Up @@ -86,20 +88,39 @@ export const replacePlaceHolders = async ({
);
}

for (const complexFieldKey of ['customFieldsData', 'trackedData']) {
for (const complexFieldKey of [
'customFieldsData',
'trackedData'
].concat(complexFields || [])) {
if (actionData[actionDataKey].includes(complexFieldKey)) {
const regex = new RegExp(`{{ ${complexFieldKey}.([\\w\\d]+) }}`);
const match = regex.exec(actionData[actionDataKey]);
const fieldId = match && match.length === 2 ? match[1] : '';

const complexFieldData = target[complexFieldKey].find(
cfd => cfd.field === fieldId
);

actionData[actionDataKey] = actionData[actionDataKey].replace(
`{{ ${complexFieldKey}.${fieldId} }}`,
complexFieldData ? complexFieldData.value : ''
);
if ((complexFields || [])?.includes(complexFieldKey)) {
const replaceValue =
(await getRelatedValue(
models,
subdomain,
target,
`${complexFieldKey}.${fieldId}`,
relatedValueProps
)) || target[targetKey];

actionData[actionDataKey] = actionData[actionDataKey].replace(
`{{ ${complexFieldKey}.${fieldId} }}`,
replaceValue
);
} else {
const complexFieldData = target[complexFieldKey].find(
cfd => cfd.field === fieldId
);

actionData[actionDataKey] = actionData[actionDataKey].replace(
`{{ ${complexFieldKey}.${fieldId} }}`,
complexFieldData ? complexFieldData.value : ''
);
}
}
}
}
Expand Down
24 changes: 21 additions & 3 deletions packages/gateway/src/apollo-router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const {
CLIENT_PORTAL_DOMAINS,
ALLOWED_ORIGINS,
NODE_ENV,
APOLLO_ROUTER_PORT
APOLLO_ROUTER_PORT,
INTROSPECTION
} = process.env;

let routerProcess: ChildProcess | undefined = undefined;
Expand Down Expand Up @@ -59,7 +60,21 @@ const createRouterConfig = async () => {
// Don't rewrite in production if it exists. Delete and restart to update the config
return;
}
// const rhaiPath = path.resolve(__dirname, 'rhai/main.rhai');

if (
NODE_ENV === 'production' &&
(INTROSPECTION || '').trim().toLowerCase() === 'true'
) {
console.warn(
'----------------------------------------------------------------------------------------------'
);
console.warn(
"Graphql introspection is enabled in production environment. Disable it, if it isn't required for front-end development. Hint: Check gateway config in configs.json"
);
console.warn(
'----------------------------------------------------------------------------------------------'
);
}

const config = {
include_subgraph_errors: {
Expand Down Expand Up @@ -91,7 +106,10 @@ const createRouterConfig = async () => {
}
},
supergraph: {
listen: `127.0.0.1:${apolloRouterPort}`
listen: `127.0.0.1:${apolloRouterPort}`,
introspection:
NODE_ENV === 'development' ||
(INTROSPECTION || '').trim().toLowerCase() === 'true'
}
};

Expand Down
25 changes: 24 additions & 1 deletion packages/plugin-cards-api/src/automations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,31 @@ const getRelatedValue = async (
return result;
}

if (targetKey.includes('productsData')) {
const [_parentFieldName, childFieldName] = targetKey.split('.');

if (childFieldName === 'amount') {
return generateTotalAmount(target.productsData);
}
}

return false;
};

const generateTotalAmount = productsData => {
let totalAmount = 0;

(productsData || []).forEach(product => {
if (product.tickUsed) {
return;
}

totalAmount += product?.amount || 0;
});

return totalAmount;
};

// module related services
const relatedServices = (
subdomain: string,
Expand Down Expand Up @@ -330,7 +352,8 @@ export default {
getRelatedValue,
actionData: config,
target,
relatedValueProps
relatedValueProps,
complexFields: ['productsData']
});
},
constants: {
Expand Down
3 changes: 2 additions & 1 deletion packages/plugin-contacts-api/src/graphql/contacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ const queryParams = `
searchValue: String,
fieldsMustExist:[String]
sortField: String
sortDirection: String
sortDirection: String,
usageType: String
`;

export const queries = `
Expand Down
141 changes: 92 additions & 49 deletions packages/plugin-contacts-api/src/graphql/resolvers/contactQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ type ContactType = {
fullName: string;
};

const gneerateSort = ({ type, sortField, sortDirection, searchValue }) => {
const generateSort = async ({
type,
sortField,
sortDirection,
searchValue
}) => {
let sort = {};
const esTypes = getEsTypes(type);
let fieldToSort = sortField || 'createdAt';
Expand All @@ -37,34 +42,24 @@ const generateQuery = async args => {
const positiveList: any = [];
const negativeList: any = [];

if (searchValue.includes('@')) {
positiveList.push({
match_phrase: {
searchText: {
query: searchValue
}
}
});
} else {
positiveList.push({
bool: {
should: [
{
match: {
searchText: {
query: searchValue
}
}
},
{
wildcard: {
searchText: `*${searchValue.toLowerCase()}*`
positiveList.push({
bool: {
should: [
{
match: {
searchText: {
query: searchValue
}
}
]
}
});
}
},
{
wildcard: {
searchText: `*${searchValue.toLowerCase()}*`
}
}
]
}
});

if (!!fieldsMustExist?.length) {
for (const field of fieldsMustExist) {
Expand All @@ -91,6 +86,28 @@ const generateQuery = async args => {
};
};

const generateAutoCompleteQuery = args => {
if (args?.usageType !== 'autoComplete') {
return [];
}

return args?.searchValue
? args.searchValue
.split(',')
.filter(value => {
if (value.match(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/)) {
args.searchValue = args.searchValue.replace(`${value},`, '');
return value;
}
})
.map(value => ({
match: {
primaryEmail: { query: value }
}
}))
: [];
};

const generateContentType = (type, source) => {
switch (type) {
case 'companies':
Expand All @@ -115,18 +132,59 @@ const generateFullName = (contentType, source) => {
return null;
};

const generateList = (type, response) => {
return response.hits.hits.map(hit => {
const { primaryEmail, primaryPhone, avatar, createdAt, status } =
hit._source || {};

return {
_id: hit._id,
primaryEmail,
primaryPhone,
avatar,
createdAt,
status,
contentType: generateContentType(type, hit._source || {}),
fullName: generateFullName(type, hit._source || {})
};
});
};

const contactQueries = {
async contacts(_root, args, { subdomain }: IContext) {
const { perPage, page } = args;

let list: ContactType[] = [];
let autoCompleteList: ContactType[] = [];

const _page = Number(page || 1);
const _limit = Number(perPage || 20);

const autoCompleteQuery = generateAutoCompleteQuery(args);

for (const type of ['customers', 'companies']) {
const customersQueryOptions = await generateQuery(args);
const customersSortOptions = await gneerateSort({ type, ...args });
const contactsQueryOptions = await generateQuery(args);
const contactsSortOptions = await generateSort({ type, ...args });

if (!!autoCompleteQuery?.length) {
const response = await fetchEs({
subdomain,
action: 'search',
index: type,
body: {
query: {
bool: {
should: autoCompleteQuery
}
}
}
});

autoCompleteList = [
...autoCompleteList,
...generateList(type, response)
];
}

if (list.length === _limit) {
continue;
Expand All @@ -139,30 +197,15 @@ const contactQueries = {
body: {
from: (_page - 1) * _limit,
size: _limit - list.length,
...customersQueryOptions,
sort: [customersSortOptions]
...contactsQueryOptions,
sort: [contactsSortOptions]
}
});

const responseList: ContactType[] = response.hits.hits.map(hit => {
const { primaryEmail, primaryPhone, avatar, createdAt, status } =
hit._source || {};

return {
_id: hit._id,
primaryEmail,
primaryPhone,
avatar,
createdAt,
status,
contentType: generateContentType(type, hit._source || {}),
fullName: generateFullName(type, hit._source || {})
};
});

list = [...list, ...responseList];
list = [...list, ...generateList(type, response)];
}
return list;

return [...autoCompleteList, ...list];
}
};

Expand Down
Loading

0 comments on commit 01d7229

Please sign in to comment.