Skip to content

Commit

Permalink
Merge pull request #295 from webitel/feature/add-contact-api
Browse files Browse the repository at this point in the history
@24.10.5 feature: add contactAPI[WTEL-4776]
  • Loading branch information
Lera24 authored Sep 10, 2024
2 parents bd41922 + 204479c commit 81d6c41
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 2 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@webitel/ui-sdk",
"version": "24.10.4",
"version": "24.10.5",
"private": false,
"scripts": {
"dev": "vite",
Expand Down
235 changes: 235 additions & 0 deletions src/api/crm/contacts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
import { ContactsApiFactory } from 'webitel-sdk';
import {
getDefaultGetListResponse,
getDefaultGetParams,
getDefaultInstance,
getDefaultOpenAPIConfig,
} from '../defaults/index.js';
import applyTransform, {
camelToSnake,
merge,
notify,
sanitize,
snakeToCamel,
} from '../transformers/index.js';
import ContactsSearchMode from './enums/ContactsSearchMode.js';

const instance = getDefaultInstance();
const configuration = getDefaultOpenAPIConfig();

const contactService = new ContactsApiFactory(configuration, '', instance);

const formatAccessMode = (item) => ({
...item,
access: {
edit: item.mode.includes('w'),
delete: item.mode.includes('d'),
},
});

const getList = async (params) => {
const fieldsToSend = ['page', 'size', 'q', 'sort', 'fields', 'id', 'qin'];

if (!params.fields) {
params.fields = [
'id',
'etag',
'name',
'managers',
'labels',
'about',
'variables',
'timezones',
'phones',
'emails',
'imclients',
];
}

const listResponseHandler = (items) =>
items?.map((item) => ({
...item,
name: item.name.commonName,
managers: item.managers ? [...item.managers.data] : [],
labels: item.labels ? [...item.labels.data] : [],
variables: item.variables ? [...item.variables.data] : [],
timezones: item.timezones ? [...item.timezones.data] : [],
phones: item.phones ? [...item.phones.data] : [],
emails: item.emails ? [...item.emails.data] : [],
}));

let changedParams;

if(params?.search) {
changedParams = { ...params, q: params.search };
} else if (params?.q && params?.qin) {
changedParams = { ...params };
} else {
let searchValue = '';
let searchKey = '';

if (params[ContactsSearchMode.NAME]) {
searchValue = params[ContactsSearchMode.NAME];
searchKey = ContactsSearchMode.NAME;
} else if (params[ContactsSearchMode.LABELS]) {
searchValue = params[ContactsSearchMode.LABELS];
searchKey = ContactsSearchMode.LABELS;
} else if (params[ContactsSearchMode.ABOUT]) {
searchValue = params[ContactsSearchMode.ABOUT];
searchKey = ContactsSearchMode.ABOUT;
} else if (params[ContactsSearchMode.VARIABLES]) {
searchValue = params[ContactsSearchMode.VARIABLES];
searchKey = ContactsSearchMode.VARIABLES;
} else if (params[ContactsSearchMode.DESTINATION]) {
searchValue = params[ContactsSearchMode.DESTINATION];
searchKey = 'emails,phones';
}

// This code needed for adding starToSearch method to applyTransform while searchKey !== SearchMode.VARIABLES because '*' in variables search mode brokes backend logic.
// if (searchKey !== ContactsSearchMode.VARIABLES) {
// transformations.push(starToSearch('q')); WTEL-4265
// }

changedParams = {
...params,
q: searchValue || '',
qin: searchKey || '',
};
}

const transformations = [sanitize(fieldsToSend), merge(getDefaultGetParams()), camelToSnake()];

const { page, size, q, sort, fields, id, qin } = applyTransform(changedParams, transformations);

try {
const response = await contactService.searchContacts(
page,
size,
q,
sort || '+name',
['mode', ...fields],
id,
qin,
);
const { data, next } = applyTransform(response.data, [
snakeToCamel(),
merge(getDefaultGetListResponse()),
]);
return {
items: applyTransform(data, [(items) => items?.map((item) => formatAccessMode(item)), listResponseHandler]),
next,
};
} catch (err) {
throw applyTransform(err, [notify]);
}
};

const get = async ({ itemId: id }) => {
const fields = [
'name',
'about',
'labels',
'etag',
'mode',
'managers',
'timezones',
'variables',
'phones',
'emails',
'imclients',
];

const defaultObject = {};
const itemResponseHandler = (item) => {
return {
...item,
labels: item.labels ? [...item.labels.data] : [],
managers: item.managers ? [...item.managers.data] : [],
timezones: item.timezones ? [...item.timezones.data] : [],
variables: item.variables ? [...item.variables.data] : [],
phones: item.phones ? [...item.phones.data] : [],
emails: item.emails ? [...item.emails.data] : [],
};
};
try {
const response = await contactService.locateContact(id, fields);
return applyTransform(response.data, [
snakeToCamel(),
merge(defaultObject),
itemResponseHandler,
formatAccessMode,
]);
} catch (err) {
throw applyTransform(err, [notify]);
}
};

const fieldsToSend = ['name', 'labels', 'about', 'managers', 'timezones'];

const sanitizeManagers = (itemInstance) => {
// handle many managers and even no managers field cases
const managers = (itemInstance.managers || []).filter(({ user } = {}) => user.id);
return { ...itemInstance, managers };
};

const sanitizeTimezones = (itemInstance) => {
// handle many timezones and even no timezones field cases
const timezones = (itemInstance.timezones || []).filter(({ timezone } = {}) => timezone.id);
return { ...itemInstance, timezones };
};

const add = async ({ itemInstance }) => {
const item = applyTransform(itemInstance, [
sanitizeManagers,
sanitizeTimezones,
sanitize(fieldsToSend),
camelToSnake(),
]);
try {
const response = await contactService.createContact(item);
return applyTransform(response.data, [snakeToCamel()]);
} catch (err) {
throw applyTransform(err, [notify]);
}
};

const update = async ({ itemInstance }) => {
const { etag } = itemInstance;
const item = applyTransform(itemInstance, [
sanitizeManagers,
sanitizeTimezones,
sanitize(fieldsToSend),
camelToSnake(),
]);
try {
const response = await contactService.updateContact(etag, item);
return applyTransform(response.data, [snakeToCamel()]);
} catch (err) {
throw applyTransform(err, [notify]);
}
};

const deleteContact = async ({ id }) => {
try {
const response = await contactService.deleteContact(id);
return applyTransform(response.data, []);
} catch (err) {
throw applyTransform(err, [notify]);
}
};

const getContactsLookup = (params) => getList({
...params,
fields: params.fields || ['id', 'name'],
});

const ContactsAPI = {
getList,
get,
add,
update,
delete: deleteContact,
getLookup: getContactsLookup,
};

export default ContactsAPI;
9 changes: 9 additions & 0 deletions src/api/crm/enums/ContactsSearchMode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const ContactsSearchMode = Object.freeze({
NAME: 'name',
LABELS: 'labels',
ABOUT: 'about',
VARIABLES: 'variables',
DESTINATION: 'destination',
});

export default ContactsSearchMode;
3 changes: 2 additions & 1 deletion src/api/crm/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import contacts from './contacts.js';
import contactChatMessagesHistoryHistory from './contactChatMessagesHistory.js';

export { contactChatMessagesHistoryHistory };
export { contacts, contactChatMessagesHistoryHistory };

0 comments on commit 81d6c41

Please sign in to comment.