Restructure omni services and add Chatwoot research snapshot
This commit is contained in:
63
research/chatwoot/app/javascript/dashboard/api/ApiClient.js
Normal file
63
research/chatwoot/app/javascript/dashboard/api/ApiClient.js
Normal file
@@ -0,0 +1,63 @@
|
||||
/* global axios */
|
||||
|
||||
const DEFAULT_API_VERSION = 'v1';
|
||||
|
||||
class ApiClient {
|
||||
constructor(resource, options = {}) {
|
||||
this.apiVersion = `/api/${options.apiVersion || DEFAULT_API_VERSION}`;
|
||||
this.options = options;
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
get url() {
|
||||
return `${this.baseUrl()}/${this.resource}`;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
get accountIdFromRoute() {
|
||||
const isInsideAccountScopedURLs =
|
||||
window.location.pathname.includes('/app/accounts');
|
||||
|
||||
if (isInsideAccountScopedURLs) {
|
||||
return window.location.pathname.split('/')[3];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
baseUrl() {
|
||||
let url = this.apiVersion;
|
||||
|
||||
if (this.options.enterprise) {
|
||||
url = `/enterprise${url}`;
|
||||
}
|
||||
|
||||
if (this.options.accountScoped && this.accountIdFromRoute) {
|
||||
url = `${url}/accounts/${this.accountIdFromRoute}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
get() {
|
||||
return axios.get(this.url);
|
||||
}
|
||||
|
||||
show(id) {
|
||||
return axios.get(`${this.url}/${id}`);
|
||||
}
|
||||
|
||||
create(data) {
|
||||
return axios.post(this.url, data);
|
||||
}
|
||||
|
||||
update(id, data) {
|
||||
return axios.patch(`${this.url}/${id}`, data);
|
||||
}
|
||||
|
||||
delete(id) {
|
||||
return axios.delete(`${this.url}/${id}`);
|
||||
}
|
||||
}
|
||||
|
||||
export default ApiClient;
|
||||
@@ -0,0 +1,97 @@
|
||||
/* global axios */
|
||||
import { DataManager } from '../helper/CacheHelper/DataManager';
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class CacheEnabledApiClient extends ApiClient {
|
||||
constructor(resource, options = {}) {
|
||||
super(resource, options);
|
||||
this.dataManager = new DataManager(this.accountIdFromRoute);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
get cacheModelName() {
|
||||
throw new Error('cacheModelName is not defined');
|
||||
}
|
||||
|
||||
get(cache = false) {
|
||||
if (cache) {
|
||||
return this.getFromCache();
|
||||
}
|
||||
|
||||
return this.getFromNetwork();
|
||||
}
|
||||
|
||||
getFromNetwork() {
|
||||
return axios.get(this.url);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
extractDataFromResponse(response) {
|
||||
return response.data.payload;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
marshallData(dataToParse) {
|
||||
return { data: { payload: dataToParse } };
|
||||
}
|
||||
|
||||
async getFromCache() {
|
||||
try {
|
||||
// IDB is not supported in Firefox private mode: https://bugzilla.mozilla.org/show_bug.cgi?id=781982
|
||||
await this.dataManager.initDb();
|
||||
} catch {
|
||||
return this.getFromNetwork();
|
||||
}
|
||||
|
||||
const { data } = await axios.get(
|
||||
`/api/v1/accounts/${this.accountIdFromRoute}/cache_keys`
|
||||
);
|
||||
const cacheKeyFromApi = data.cache_keys[this.cacheModelName];
|
||||
const isCacheValid = await this.validateCacheKey(cacheKeyFromApi);
|
||||
|
||||
let localData = [];
|
||||
if (isCacheValid) {
|
||||
localData = await this.dataManager.get({
|
||||
modelName: this.cacheModelName,
|
||||
});
|
||||
}
|
||||
|
||||
if (localData.length === 0) {
|
||||
return this.refetchAndCommit(cacheKeyFromApi);
|
||||
}
|
||||
|
||||
return this.marshallData(localData);
|
||||
}
|
||||
|
||||
async refetchAndCommit(newKey = null) {
|
||||
const response = await this.getFromNetwork();
|
||||
|
||||
try {
|
||||
await this.dataManager.initDb();
|
||||
|
||||
this.dataManager.replace({
|
||||
modelName: this.cacheModelName,
|
||||
data: this.extractDataFromResponse(response),
|
||||
});
|
||||
|
||||
await this.dataManager.setCacheKeys({
|
||||
[this.cacheModelName]: newKey,
|
||||
});
|
||||
} catch {
|
||||
// Ignore error
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
async validateCacheKey(cacheKeyFromApi) {
|
||||
if (!this.dataManager.db) {
|
||||
await this.dataManager.initDb();
|
||||
}
|
||||
|
||||
const cachekey = await this.dataManager.getCacheKey(this.cacheModelName);
|
||||
return cacheKeyFromApi === cachekey;
|
||||
}
|
||||
}
|
||||
|
||||
export default CacheEnabledApiClient;
|
||||
21
research/chatwoot/app/javascript/dashboard/api/account.js
Normal file
21
research/chatwoot/app/javascript/dashboard/api/account.js
Normal file
@@ -0,0 +1,21 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class AccountAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('', { accountScoped: true });
|
||||
}
|
||||
|
||||
createAccount(data) {
|
||||
return axios.post(`${this.apiVersion}/accounts`, data);
|
||||
}
|
||||
|
||||
async getCacheKeys() {
|
||||
const response = await axios.get(
|
||||
`/api/v1/accounts/${this.accountIdFromRoute}/cache_keys`
|
||||
);
|
||||
return response.data.cache_keys;
|
||||
}
|
||||
}
|
||||
|
||||
export default new AccountAPI();
|
||||
@@ -0,0 +1,18 @@
|
||||
/* global axios */
|
||||
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class AccountActions extends ApiClient {
|
||||
constructor() {
|
||||
super('actions', { accountScoped: true });
|
||||
}
|
||||
|
||||
merge(parentId, childId) {
|
||||
return axios.post(`${this.url}/contact_merge`, {
|
||||
base_contact_id: parentId,
|
||||
mergee_contact_id: childId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new AccountActions();
|
||||
30
research/chatwoot/app/javascript/dashboard/api/agentBots.js
Normal file
30
research/chatwoot/app/javascript/dashboard/api/agentBots.js
Normal file
@@ -0,0 +1,30 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class AgentBotsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('agent_bots', { accountScoped: true });
|
||||
}
|
||||
|
||||
create(data) {
|
||||
return axios.post(this.url, data, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
});
|
||||
}
|
||||
|
||||
update(id, data) {
|
||||
return axios.patch(`${this.url}/${id}`, data, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
});
|
||||
}
|
||||
|
||||
deleteAgentBotAvatar(botId) {
|
||||
return axios.delete(`${this.url}/${botId}/avatar`);
|
||||
}
|
||||
|
||||
resetAccessToken(botId) {
|
||||
return axios.post(`${this.url}/${botId}/reset_access_token`);
|
||||
}
|
||||
}
|
||||
|
||||
export default new AgentBotsAPI();
|
||||
@@ -0,0 +1,43 @@
|
||||
/* global axios */
|
||||
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class AgentCapacityPolicies extends ApiClient {
|
||||
constructor() {
|
||||
super('agent_capacity_policies', { accountScoped: true });
|
||||
}
|
||||
|
||||
getUsers(policyId) {
|
||||
return axios.get(`${this.url}/${policyId}/users`);
|
||||
}
|
||||
|
||||
addUser(policyId, userData) {
|
||||
return axios.post(`${this.url}/${policyId}/users`, {
|
||||
user_id: userData.id,
|
||||
capacity: userData.capacity,
|
||||
});
|
||||
}
|
||||
|
||||
removeUser(policyId, userId) {
|
||||
return axios.delete(`${this.url}/${policyId}/users/${userId}`);
|
||||
}
|
||||
|
||||
createInboxLimit(policyId, limitData) {
|
||||
return axios.post(`${this.url}/${policyId}/inbox_limits`, {
|
||||
inbox_id: limitData.inboxId,
|
||||
conversation_limit: limitData.conversationLimit,
|
||||
});
|
||||
}
|
||||
|
||||
updateInboxLimit(policyId, limitId, limitData) {
|
||||
return axios.put(`${this.url}/${policyId}/inbox_limits/${limitId}`, {
|
||||
conversation_limit: limitData.conversationLimit,
|
||||
});
|
||||
}
|
||||
|
||||
deleteInboxLimit(policyId, limitId) {
|
||||
return axios.delete(`${this.url}/${policyId}/inbox_limits/${limitId}`);
|
||||
}
|
||||
}
|
||||
|
||||
export default new AgentCapacityPolicies();
|
||||
17
research/chatwoot/app/javascript/dashboard/api/agents.js
Normal file
17
research/chatwoot/app/javascript/dashboard/api/agents.js
Normal file
@@ -0,0 +1,17 @@
|
||||
/* global axios */
|
||||
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class Agents extends ApiClient {
|
||||
constructor() {
|
||||
super('agents', { accountScoped: true });
|
||||
}
|
||||
|
||||
bulkInvite({ emails }) {
|
||||
return axios.post(`${this.url}/bulk_create`, {
|
||||
emails,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new Agents();
|
||||
@@ -0,0 +1,16 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class AssignableAgents extends ApiClient {
|
||||
constructor() {
|
||||
super('assignable_agents', { accountScoped: true });
|
||||
}
|
||||
|
||||
get(inboxIds) {
|
||||
return axios.get(this.url, {
|
||||
params: { inbox_ids: inboxIds },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new AssignableAgents();
|
||||
@@ -0,0 +1,36 @@
|
||||
/* global axios */
|
||||
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class AssignmentPolicies extends ApiClient {
|
||||
constructor() {
|
||||
super('assignment_policies', { accountScoped: true });
|
||||
}
|
||||
|
||||
getInboxes(policyId) {
|
||||
return axios.get(`${this.url}/${policyId}/inboxes`);
|
||||
}
|
||||
|
||||
setInboxPolicy(inboxId, policyId) {
|
||||
return axios.post(
|
||||
`/api/v1/accounts/${this.accountIdFromRoute}/inboxes/${inboxId}/assignment_policy`,
|
||||
{
|
||||
assignment_policy_id: policyId,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
getInboxPolicy(inboxId) {
|
||||
return axios.get(
|
||||
`/api/v1/accounts/${this.accountIdFromRoute}/inboxes/${inboxId}/assignment_policy`
|
||||
);
|
||||
}
|
||||
|
||||
removeInboxPolicy(inboxId) {
|
||||
return axios.delete(
|
||||
`/api/v1/accounts/${this.accountIdFromRoute}/inboxes/${inboxId}/assignment_policy`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default new AssignmentPolicies();
|
||||
14
research/chatwoot/app/javascript/dashboard/api/attributes.js
Normal file
14
research/chatwoot/app/javascript/dashboard/api/attributes.js
Normal file
@@ -0,0 +1,14 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class AttributeAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('custom_attribute_definitions', { accountScoped: true });
|
||||
}
|
||||
|
||||
getAttributesByModel() {
|
||||
return axios.get(this.url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new AttributeAPI();
|
||||
16
research/chatwoot/app/javascript/dashboard/api/auditLogs.js
Normal file
16
research/chatwoot/app/javascript/dashboard/api/auditLogs.js
Normal file
@@ -0,0 +1,16 @@
|
||||
/* global axios */
|
||||
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class AuditLogs extends ApiClient {
|
||||
constructor() {
|
||||
super('audit_logs', { accountScoped: true });
|
||||
}
|
||||
|
||||
get({ page }) {
|
||||
const url = page ? `${this.url}?page=${page}` : this.url;
|
||||
return axios.get(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new AuditLogs();
|
||||
109
research/chatwoot/app/javascript/dashboard/api/auth.js
Normal file
109
research/chatwoot/app/javascript/dashboard/api/auth.js
Normal file
@@ -0,0 +1,109 @@
|
||||
/* global axios */
|
||||
|
||||
import Cookies from 'js-cookie';
|
||||
import endPoints from './endPoints';
|
||||
import {
|
||||
clearCookiesOnLogout,
|
||||
deleteIndexedDBOnLogout,
|
||||
} from '../store/utils/api';
|
||||
|
||||
export default {
|
||||
validityCheck() {
|
||||
const urlData = endPoints('validityCheck');
|
||||
return axios.get(urlData.url);
|
||||
},
|
||||
logout() {
|
||||
const urlData = endPoints('logout');
|
||||
const fetchPromise = new Promise((resolve, reject) => {
|
||||
axios
|
||||
.delete(urlData.url)
|
||||
.then(response => {
|
||||
deleteIndexedDBOnLogout();
|
||||
clearCookiesOnLogout();
|
||||
resolve(response);
|
||||
})
|
||||
.catch(error => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
return fetchPromise;
|
||||
},
|
||||
hasAuthCookie() {
|
||||
return !!Cookies.get('cw_d_session_info');
|
||||
},
|
||||
getAuthData() {
|
||||
if (this.hasAuthCookie()) {
|
||||
const savedAuthInfo = Cookies.get('cw_d_session_info');
|
||||
return JSON.parse(savedAuthInfo || '{}');
|
||||
}
|
||||
return false;
|
||||
},
|
||||
profileUpdate({ displayName, avatar, ...profileAttributes }) {
|
||||
const formData = new FormData();
|
||||
Object.keys(profileAttributes).forEach(key => {
|
||||
const hasValue = profileAttributes[key] === undefined;
|
||||
if (!hasValue) {
|
||||
formData.append(`profile[${key}]`, profileAttributes[key]);
|
||||
}
|
||||
});
|
||||
formData.append('profile[display_name]', displayName || '');
|
||||
if (avatar) {
|
||||
formData.append('profile[avatar]', avatar);
|
||||
}
|
||||
return axios.put(endPoints('profileUpdate').url, formData);
|
||||
},
|
||||
|
||||
profilePasswordUpdate({ currentPassword, password, passwordConfirmation }) {
|
||||
return axios.put(endPoints('profileUpdate').url, {
|
||||
profile: {
|
||||
current_password: currentPassword,
|
||||
password,
|
||||
password_confirmation: passwordConfirmation,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
updateUISettings({ uiSettings }) {
|
||||
return axios.put(endPoints('profileUpdate').url, {
|
||||
profile: { ui_settings: uiSettings },
|
||||
});
|
||||
},
|
||||
|
||||
updateAvailability(availabilityData) {
|
||||
return axios.post(endPoints('availabilityUpdate').url, {
|
||||
profile: { ...availabilityData },
|
||||
});
|
||||
},
|
||||
|
||||
updateAutoOffline(accountId, autoOffline = false) {
|
||||
return axios.post(endPoints('autoOffline').url, {
|
||||
profile: { account_id: accountId, auto_offline: autoOffline },
|
||||
});
|
||||
},
|
||||
|
||||
deleteAvatar() {
|
||||
return axios.delete(endPoints('deleteAvatar').url);
|
||||
},
|
||||
|
||||
resetPassword({ email }) {
|
||||
const urlData = endPoints('resetPassword');
|
||||
return axios.post(urlData.url, { email });
|
||||
},
|
||||
|
||||
setActiveAccount({ accountId }) {
|
||||
const urlData = endPoints('setActiveAccount');
|
||||
return axios.put(urlData.url, {
|
||||
profile: {
|
||||
account_id: accountId,
|
||||
},
|
||||
});
|
||||
},
|
||||
resendConfirmation() {
|
||||
const urlData = endPoints('resendConfirmation');
|
||||
return axios.post(urlData.url);
|
||||
},
|
||||
resetAccessToken() {
|
||||
const urlData = endPoints('resetAccessToken');
|
||||
return axios.post(urlData.url);
|
||||
},
|
||||
};
|
||||
14
research/chatwoot/app/javascript/dashboard/api/automation.js
Normal file
14
research/chatwoot/app/javascript/dashboard/api/automation.js
Normal file
@@ -0,0 +1,14 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class AutomationsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('automation_rules', { accountScoped: true });
|
||||
}
|
||||
|
||||
clone(automationId) {
|
||||
return axios.post(`${this.url}/${automationId}/clone`);
|
||||
}
|
||||
}
|
||||
|
||||
export default new AutomationsAPI();
|
||||
@@ -0,0 +1,9 @@
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class BulkActionsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('bulk_actions', { accountScoped: true });
|
||||
}
|
||||
}
|
||||
|
||||
export default new BulkActionsAPI();
|
||||
@@ -0,0 +1,9 @@
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class CampaignsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('campaigns', { accountScoped: true });
|
||||
}
|
||||
}
|
||||
|
||||
export default new CampaignsAPI();
|
||||
@@ -0,0 +1,16 @@
|
||||
/* global axios */
|
||||
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class CannedResponse extends ApiClient {
|
||||
constructor() {
|
||||
super('canned_responses', { accountScoped: true });
|
||||
}
|
||||
|
||||
get({ searchKey }) {
|
||||
const url = searchKey ? `${this.url}?search=${searchKey}` : this.url;
|
||||
return axios.get(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new CannedResponse();
|
||||
@@ -0,0 +1,26 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class CaptainAssistant extends ApiClient {
|
||||
constructor() {
|
||||
super('captain/assistants', { accountScoped: true });
|
||||
}
|
||||
|
||||
get({ page = 1, searchKey } = {}) {
|
||||
return axios.get(this.url, {
|
||||
params: {
|
||||
page,
|
||||
searchKey,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
playground({ assistantId, messageContent, messageHistory }) {
|
||||
return axios.post(`${this.url}/${assistantId}/playground`, {
|
||||
message_content: messageContent,
|
||||
message_history: messageHistory,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new CaptainAssistant();
|
||||
@@ -0,0 +1,9 @@
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class CaptainBulkActionsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('captain/bulk_actions', { accountScoped: true });
|
||||
}
|
||||
}
|
||||
|
||||
export default new CaptainBulkActionsAPI();
|
||||
@@ -0,0 +1,18 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class CopilotMessages extends ApiClient {
|
||||
constructor() {
|
||||
super('captain/copilot_threads', { accountScoped: true });
|
||||
}
|
||||
|
||||
get(threadId) {
|
||||
return axios.get(`${this.url}/${threadId}/copilot_messages`);
|
||||
}
|
||||
|
||||
create({ threadId, ...rest }) {
|
||||
return axios.post(`${this.url}/${threadId}/copilot_messages`, rest);
|
||||
}
|
||||
}
|
||||
|
||||
export default new CopilotMessages();
|
||||
@@ -0,0 +1,9 @@
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class CopilotThreads extends ApiClient {
|
||||
constructor() {
|
||||
super('captain/copilot_threads', { accountScoped: true });
|
||||
}
|
||||
}
|
||||
|
||||
export default new CopilotThreads();
|
||||
@@ -0,0 +1,36 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class CaptainCustomTools extends ApiClient {
|
||||
constructor() {
|
||||
super('captain/custom_tools', { accountScoped: true });
|
||||
}
|
||||
|
||||
get({ page = 1, searchKey } = {}) {
|
||||
return axios.get(this.url, {
|
||||
params: { page, searchKey },
|
||||
});
|
||||
}
|
||||
|
||||
show(id) {
|
||||
return axios.get(`${this.url}/${id}`);
|
||||
}
|
||||
|
||||
create(data = {}) {
|
||||
return axios.post(this.url, {
|
||||
custom_tool: data,
|
||||
});
|
||||
}
|
||||
|
||||
update(id, data = {}) {
|
||||
return axios.put(`${this.url}/${id}`, {
|
||||
custom_tool: data,
|
||||
});
|
||||
}
|
||||
|
||||
delete(id) {
|
||||
return axios.delete(`${this.url}/${id}`);
|
||||
}
|
||||
}
|
||||
|
||||
export default new CaptainCustomTools();
|
||||
@@ -0,0 +1,20 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class CaptainDocument extends ApiClient {
|
||||
constructor() {
|
||||
super('captain/documents', { accountScoped: true });
|
||||
}
|
||||
|
||||
get({ page = 1, searchKey, assistantId } = {}) {
|
||||
return axios.get(this.url, {
|
||||
params: {
|
||||
page,
|
||||
searchKey,
|
||||
assistant_id: assistantId,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new CaptainDocument();
|
||||
@@ -0,0 +1,26 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class CaptainInboxes extends ApiClient {
|
||||
constructor() {
|
||||
super('captain/assistants', { accountScoped: true });
|
||||
}
|
||||
|
||||
get({ assistantId } = {}) {
|
||||
return axios.get(`${this.url}/${assistantId}/inboxes`);
|
||||
}
|
||||
|
||||
create(params = {}) {
|
||||
const { assistantId, inboxId } = params;
|
||||
return axios.post(`${this.url}/${assistantId}/inboxes`, {
|
||||
inbox: { inbox_id: inboxId },
|
||||
});
|
||||
}
|
||||
|
||||
delete(params = {}) {
|
||||
const { assistantId, inboxId } = params;
|
||||
return axios.delete(`${this.url}/${assistantId}/inboxes/${inboxId}`);
|
||||
}
|
||||
}
|
||||
|
||||
export default new CaptainInboxes();
|
||||
@@ -0,0 +1,18 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class CaptainPreferences extends ApiClient {
|
||||
constructor() {
|
||||
super('captain/preferences', { accountScoped: true });
|
||||
}
|
||||
|
||||
get() {
|
||||
return axios.get(this.url);
|
||||
}
|
||||
|
||||
updatePreferences(data) {
|
||||
return axios.put(this.url, data);
|
||||
}
|
||||
}
|
||||
|
||||
export default new CaptainPreferences();
|
||||
@@ -0,0 +1,22 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class CaptainResponses extends ApiClient {
|
||||
constructor() {
|
||||
super('captain/assistant_responses', { accountScoped: true });
|
||||
}
|
||||
|
||||
get({ page = 1, search, assistantId, documentId, status } = {}) {
|
||||
return axios.get(this.url, {
|
||||
params: {
|
||||
page,
|
||||
search,
|
||||
assistant_id: assistantId,
|
||||
document_id: documentId,
|
||||
status,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new CaptainResponses();
|
||||
@@ -0,0 +1,36 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class CaptainScenarios extends ApiClient {
|
||||
constructor() {
|
||||
super('captain/assistants', { accountScoped: true });
|
||||
}
|
||||
|
||||
get({ assistantId, page = 1, searchKey } = {}) {
|
||||
return axios.get(`${this.url}/${assistantId}/scenarios`, {
|
||||
params: { page, searchKey },
|
||||
});
|
||||
}
|
||||
|
||||
show({ assistantId, id }) {
|
||||
return axios.get(`${this.url}/${assistantId}/scenarios/${id}`);
|
||||
}
|
||||
|
||||
create({ assistantId, ...data } = {}) {
|
||||
return axios.post(`${this.url}/${assistantId}/scenarios`, {
|
||||
scenario: data,
|
||||
});
|
||||
}
|
||||
|
||||
update({ assistantId, id }, data = {}) {
|
||||
return axios.put(`${this.url}/${assistantId}/scenarios/${id}`, {
|
||||
scenario: data,
|
||||
});
|
||||
}
|
||||
|
||||
delete({ assistantId, id }) {
|
||||
return axios.delete(`${this.url}/${assistantId}/scenarios/${id}`);
|
||||
}
|
||||
}
|
||||
|
||||
export default new CaptainScenarios();
|
||||
107
research/chatwoot/app/javascript/dashboard/api/captain/tasks.js
Normal file
107
research/chatwoot/app/javascript/dashboard/api/captain/tasks.js
Normal file
@@ -0,0 +1,107 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
/**
|
||||
* A client for the Captain Tasks API.
|
||||
* @extends ApiClient
|
||||
*/
|
||||
class TasksAPI extends ApiClient {
|
||||
/**
|
||||
* Creates a new TasksAPI instance.
|
||||
*/
|
||||
constructor() {
|
||||
super('captain/tasks', { accountScoped: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrites content with a specific operation.
|
||||
* @param {Object} options - The rewrite options.
|
||||
* @param {string} options.content - The content to rewrite.
|
||||
* @param {string} options.operation - The rewrite operation (fix_spelling_grammar, casual, professional, etc).
|
||||
* @param {string} [options.conversationId] - The conversation ID for context (required for 'improve').
|
||||
* @param {AbortSignal} [signal] - AbortSignal to cancel the request.
|
||||
* @returns {Promise} A promise that resolves with the rewritten content.
|
||||
*/
|
||||
rewrite({ content, operation, conversationId }, signal) {
|
||||
return axios.post(
|
||||
`${this.url}/rewrite`,
|
||||
{
|
||||
content,
|
||||
operation,
|
||||
conversation_display_id: conversationId,
|
||||
},
|
||||
{ signal }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Summarizes a conversation.
|
||||
* @param {string} conversationId - The conversation ID to summarize.
|
||||
* @param {AbortSignal} [signal] - AbortSignal to cancel the request.
|
||||
* @returns {Promise} A promise that resolves with the summary.
|
||||
*/
|
||||
summarize(conversationId, signal) {
|
||||
return axios.post(
|
||||
`${this.url}/summarize`,
|
||||
{
|
||||
conversation_display_id: conversationId,
|
||||
},
|
||||
{ signal }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reply suggestion for a conversation.
|
||||
* @param {string} conversationId - The conversation ID.
|
||||
* @param {AbortSignal} [signal] - AbortSignal to cancel the request.
|
||||
* @returns {Promise} A promise that resolves with the reply suggestion.
|
||||
*/
|
||||
replySuggestion(conversationId, signal) {
|
||||
return axios.post(
|
||||
`${this.url}/reply_suggestion`,
|
||||
{
|
||||
conversation_display_id: conversationId,
|
||||
},
|
||||
{ signal }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets label suggestions for a conversation.
|
||||
* @param {string} conversationId - The conversation ID.
|
||||
* @param {AbortSignal} [signal] - AbortSignal to cancel the request.
|
||||
* @returns {Promise} A promise that resolves with label suggestions.
|
||||
*/
|
||||
labelSuggestion(conversationId, signal) {
|
||||
return axios.post(
|
||||
`${this.url}/label_suggestion`,
|
||||
{
|
||||
conversation_display_id: conversationId,
|
||||
},
|
||||
{ signal }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a follow-up message to continue refining a previous task result.
|
||||
* @param {Object} options - The follow-up options.
|
||||
* @param {Object} options.followUpContext - The follow-up context from a previous task.
|
||||
* @param {string} options.message - The follow-up message/request from the user.
|
||||
* @param {string} [options.conversationId] - The conversation ID for Langfuse session tracking.
|
||||
* @param {AbortSignal} [signal] - AbortSignal to cancel the request.
|
||||
* @returns {Promise} A promise that resolves with the follow-up response and updated follow-up context.
|
||||
*/
|
||||
followUp({ followUpContext, message, conversationId }, signal) {
|
||||
return axios.post(
|
||||
`${this.url}/follow_up`,
|
||||
{
|
||||
follow_up_context: followUpContext,
|
||||
message,
|
||||
conversation_display_id: conversationId,
|
||||
},
|
||||
{ signal }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default new TasksAPI();
|
||||
@@ -0,0 +1,16 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class CaptainTools extends ApiClient {
|
||||
constructor() {
|
||||
super('captain/assistants/tools', { accountScoped: true });
|
||||
}
|
||||
|
||||
get(params = {}) {
|
||||
return axios.get(this.url, {
|
||||
params,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new CaptainTools();
|
||||
16
research/chatwoot/app/javascript/dashboard/api/changelog.js
Normal file
16
research/chatwoot/app/javascript/dashboard/api/changelog.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import axios from 'axios';
|
||||
import ApiClient from './ApiClient';
|
||||
import { CHANGELOG_API_URL } from 'shared/constants/links';
|
||||
|
||||
class ChangelogApi extends ApiClient {
|
||||
constructor() {
|
||||
super('changelog', { apiVersion: 'v1' });
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
fetchFromHub() {
|
||||
return axios.get(CHANGELOG_API_URL);
|
||||
}
|
||||
}
|
||||
|
||||
export default new ChangelogApi();
|
||||
@@ -0,0 +1,24 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class FBChannel extends ApiClient {
|
||||
constructor() {
|
||||
super('facebook_indicators', { accountScoped: true });
|
||||
}
|
||||
|
||||
create(params) {
|
||||
return axios.post(
|
||||
`${this.url.replace(this.resource, '')}callbacks/register_facebook_page`,
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
reauthorizeFacebookPage({ omniauthToken, inboxId }) {
|
||||
return axios.post(`${this.baseUrl()}/callbacks/reauthorize_page`, {
|
||||
omniauth_token: omniauthToken,
|
||||
inbox_id: inboxId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new FBChannel();
|
||||
@@ -0,0 +1,14 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class MicrosoftClient extends ApiClient {
|
||||
constructor() {
|
||||
super('google', { accountScoped: true });
|
||||
}
|
||||
|
||||
generateAuthorization(payload) {
|
||||
return axios.post(`${this.url}/authorization`, payload);
|
||||
}
|
||||
}
|
||||
|
||||
export default new MicrosoftClient();
|
||||
@@ -0,0 +1,14 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class InstagramChannel extends ApiClient {
|
||||
constructor() {
|
||||
super('instagram', { accountScoped: true });
|
||||
}
|
||||
|
||||
generateAuthorization(payload) {
|
||||
return axios.post(`${this.url}/authorization`, payload);
|
||||
}
|
||||
}
|
||||
|
||||
export default new InstagramChannel();
|
||||
@@ -0,0 +1,14 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class MicrosoftClient extends ApiClient {
|
||||
constructor() {
|
||||
super('microsoft', { accountScoped: true });
|
||||
}
|
||||
|
||||
generateAuthorization(payload) {
|
||||
return axios.post(`${this.url}/authorization`, payload);
|
||||
}
|
||||
}
|
||||
|
||||
export default new MicrosoftClient();
|
||||
@@ -0,0 +1,14 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class TiktokChannel extends ApiClient {
|
||||
constructor() {
|
||||
super('tiktok', { accountScoped: true });
|
||||
}
|
||||
|
||||
generateAuthorization(payload) {
|
||||
return axios.post(`${this.url}/authorization`, payload);
|
||||
}
|
||||
}
|
||||
|
||||
export default new TiktokChannel();
|
||||
@@ -0,0 +1,9 @@
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class TwilioChannel extends ApiClient {
|
||||
constructor() {
|
||||
super('channels/twilio_channel', { accountScoped: true });
|
||||
}
|
||||
}
|
||||
|
||||
export default new TwilioChannel();
|
||||
@@ -0,0 +1,14 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class TwitterClient extends ApiClient {
|
||||
constructor() {
|
||||
super('twitter', { accountScoped: true });
|
||||
}
|
||||
|
||||
generateAuthorization() {
|
||||
return axios.post(`${this.url}/authorization`);
|
||||
}
|
||||
}
|
||||
|
||||
export default new TwitterClient();
|
||||
@@ -0,0 +1,95 @@
|
||||
import { Device } from '@twilio/voice-sdk';
|
||||
import VoiceAPI from './voiceAPIClient';
|
||||
|
||||
const createCallDisconnectedEvent = () => new CustomEvent('call:disconnected');
|
||||
|
||||
class TwilioVoiceClient extends EventTarget {
|
||||
constructor() {
|
||||
super();
|
||||
this.device = null;
|
||||
this.activeConnection = null;
|
||||
this.initialized = false;
|
||||
this.inboxId = null;
|
||||
}
|
||||
|
||||
async initializeDevice(inboxId) {
|
||||
this.destroyDevice();
|
||||
|
||||
const response = await VoiceAPI.getToken(inboxId);
|
||||
const { token, account_id } = response || {};
|
||||
if (!token) throw new Error('Invalid token');
|
||||
|
||||
this.device = new Device(token, {
|
||||
allowIncomingWhileBusy: true,
|
||||
disableAudioContextSounds: true,
|
||||
appParams: { account_id },
|
||||
});
|
||||
|
||||
this.device.removeAllListeners();
|
||||
this.device.on('connect', conn => {
|
||||
this.activeConnection = conn;
|
||||
conn.on('disconnect', this.onDisconnect);
|
||||
});
|
||||
|
||||
this.device.on('disconnect', this.onDisconnect);
|
||||
|
||||
this.device.on('tokenWillExpire', async () => {
|
||||
const r = await VoiceAPI.getToken(this.inboxId);
|
||||
if (r?.token) this.device.updateToken(r.token);
|
||||
});
|
||||
|
||||
this.initialized = true;
|
||||
this.inboxId = inboxId;
|
||||
|
||||
return this.device;
|
||||
}
|
||||
|
||||
get hasActiveConnection() {
|
||||
return !!this.activeConnection;
|
||||
}
|
||||
|
||||
endClientCall() {
|
||||
if (this.activeConnection) {
|
||||
this.activeConnection.disconnect();
|
||||
}
|
||||
this.activeConnection = null;
|
||||
if (this.device) {
|
||||
this.device.disconnectAll();
|
||||
}
|
||||
}
|
||||
|
||||
destroyDevice() {
|
||||
if (this.device) {
|
||||
this.device.destroy();
|
||||
}
|
||||
this.activeConnection = null;
|
||||
this.device = null;
|
||||
this.initialized = false;
|
||||
this.inboxId = null;
|
||||
}
|
||||
|
||||
async joinClientCall({ to, conversationId }) {
|
||||
if (!this.device || !this.initialized || !to) return null;
|
||||
if (this.activeConnection) return this.activeConnection;
|
||||
|
||||
const params = {
|
||||
To: to,
|
||||
is_agent: 'true',
|
||||
conversation_id: conversationId,
|
||||
};
|
||||
|
||||
const connection = await this.device.connect({ params });
|
||||
this.activeConnection = connection;
|
||||
|
||||
connection.on('disconnect', this.onDisconnect);
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
onDisconnect = () => {
|
||||
this.activeConnection = null;
|
||||
this.dispatchEvent(createCallDisconnectedEvent());
|
||||
};
|
||||
}
|
||||
|
||||
export default new TwilioVoiceClient();
|
||||
@@ -0,0 +1,40 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../../ApiClient';
|
||||
import ContactsAPI from '../../contacts';
|
||||
|
||||
class VoiceAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('voice', { accountScoped: true });
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
initiateCall(contactId, inboxId) {
|
||||
return ContactsAPI.initiateCall(contactId, inboxId).then(r => r.data);
|
||||
}
|
||||
|
||||
leaveConference(inboxId, conversationId) {
|
||||
return axios
|
||||
.delete(`${this.baseUrl()}/inboxes/${inboxId}/conference`, {
|
||||
params: { conversation_id: conversationId },
|
||||
})
|
||||
.then(r => r.data);
|
||||
}
|
||||
|
||||
joinConference({ conversationId, inboxId, callSid }) {
|
||||
return axios
|
||||
.post(`${this.baseUrl()}/inboxes/${inboxId}/conference`, {
|
||||
conversation_id: conversationId,
|
||||
call_sid: callSid,
|
||||
})
|
||||
.then(r => r.data);
|
||||
}
|
||||
|
||||
getToken(inboxId) {
|
||||
if (!inboxId) return Promise.reject(new Error('Inbox ID is required'));
|
||||
return axios
|
||||
.get(`${this.baseUrl()}/inboxes/${inboxId}/conference/token`)
|
||||
.then(r => r.data);
|
||||
}
|
||||
}
|
||||
|
||||
export default new VoiceAPI();
|
||||
@@ -0,0 +1,9 @@
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class WebChannel extends ApiClient {
|
||||
constructor() {
|
||||
super('inboxes', { accountScoped: true });
|
||||
}
|
||||
}
|
||||
|
||||
export default new WebChannel();
|
||||
@@ -0,0 +1,21 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class WhatsappChannel extends ApiClient {
|
||||
constructor() {
|
||||
super('whatsapp', { accountScoped: true });
|
||||
}
|
||||
|
||||
createEmbeddedSignup(params) {
|
||||
return axios.post(`${this.baseUrl()}/whatsapp/authorization`, params);
|
||||
}
|
||||
|
||||
reauthorizeWhatsApp({ inboxId, ...params }) {
|
||||
return axios.post(`${this.baseUrl()}/whatsapp/authorization`, {
|
||||
...params,
|
||||
inbox_id: inboxId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new WhatsappChannel();
|
||||
13
research/chatwoot/app/javascript/dashboard/api/channels.js
Normal file
13
research/chatwoot/app/javascript/dashboard/api/channels.js
Normal file
@@ -0,0 +1,13 @@
|
||||
/* eslint no-console: 0 */
|
||||
/* global axios */
|
||||
/* eslint no-undef: "error" */
|
||||
/* eslint no-unused-expressions: ["error", { "allowShortCircuit": true }] */
|
||||
import endPoints from './endPoints';
|
||||
|
||||
export default {
|
||||
fetchFacebookPages(token, accountId) {
|
||||
const urlData = endPoints('fetchFacebookPages');
|
||||
urlData.params.omniauth_token = token;
|
||||
return axios.post(urlData.url(accountId), urlData.params);
|
||||
},
|
||||
};
|
||||
37
research/chatwoot/app/javascript/dashboard/api/companies.js
Normal file
37
research/chatwoot/app/javascript/dashboard/api/companies.js
Normal file
@@ -0,0 +1,37 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
export const buildCompanyParams = (page, sort) => {
|
||||
let params = `page=${page}`;
|
||||
if (sort) {
|
||||
params = `${params}&sort=${sort}`;
|
||||
}
|
||||
return params;
|
||||
};
|
||||
|
||||
export const buildSearchParams = (query, page, sort) => {
|
||||
let params = `q=${encodeURIComponent(query)}&page=${page}`;
|
||||
if (sort) {
|
||||
params = `${params}&sort=${sort}`;
|
||||
}
|
||||
return params;
|
||||
};
|
||||
|
||||
class CompanyAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('companies', { accountScoped: true });
|
||||
}
|
||||
|
||||
get(params = {}) {
|
||||
const { page = 1, sort = 'name' } = params;
|
||||
const requestURL = `${this.url}?${buildCompanyParams(page, sort)}`;
|
||||
return axios.get(requestURL);
|
||||
}
|
||||
|
||||
search(query = '', page = 1, sort = 'name') {
|
||||
const requestURL = `${this.url}/search?${buildSearchParams(query, page, sort)}`;
|
||||
return axios.get(requestURL);
|
||||
}
|
||||
}
|
||||
|
||||
export default new CompanyAPI();
|
||||
@@ -0,0 +1,29 @@
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class ContactNotes extends ApiClient {
|
||||
constructor() {
|
||||
super('notes', { accountScoped: true });
|
||||
this.contactId = null;
|
||||
}
|
||||
|
||||
get url() {
|
||||
return `${this.baseUrl()}/contacts/${this.contactId}/notes`;
|
||||
}
|
||||
|
||||
get(contactId) {
|
||||
this.contactId = contactId;
|
||||
return super.get();
|
||||
}
|
||||
|
||||
create(contactId, content) {
|
||||
this.contactId = contactId;
|
||||
return super.create({ content });
|
||||
}
|
||||
|
||||
delete(contactId, id) {
|
||||
this.contactId = contactId;
|
||||
return super.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
export default new ContactNotes();
|
||||
104
research/chatwoot/app/javascript/dashboard/api/contacts.js
Normal file
104
research/chatwoot/app/javascript/dashboard/api/contacts.js
Normal file
@@ -0,0 +1,104 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
export const buildContactParams = (page, sortAttr, label, search) => {
|
||||
let params = `include_contact_inboxes=false&page=${page}&sort=${sortAttr}`;
|
||||
if (search) {
|
||||
params = `${params}&q=${search}`;
|
||||
}
|
||||
if (label) {
|
||||
params = `${params}&labels[]=${label}`;
|
||||
}
|
||||
return params;
|
||||
};
|
||||
|
||||
class ContactAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('contacts', { accountScoped: true });
|
||||
}
|
||||
|
||||
get(page, sortAttr = 'name', label = '') {
|
||||
let requestURL = `${this.url}?${buildContactParams(
|
||||
page,
|
||||
sortAttr,
|
||||
label,
|
||||
''
|
||||
)}`;
|
||||
return axios.get(requestURL);
|
||||
}
|
||||
|
||||
show(id) {
|
||||
return axios.get(`${this.url}/${id}?include_contact_inboxes=false`);
|
||||
}
|
||||
|
||||
update(id, data) {
|
||||
return axios.patch(`${this.url}/${id}?include_contact_inboxes=false`, data);
|
||||
}
|
||||
|
||||
getConversations(contactId) {
|
||||
return axios.get(`${this.url}/${contactId}/conversations`);
|
||||
}
|
||||
|
||||
getContactableInboxes(contactId) {
|
||||
return axios.get(`${this.url}/${contactId}/contactable_inboxes`);
|
||||
}
|
||||
|
||||
getContactLabels(contactId) {
|
||||
return axios.get(`${this.url}/${contactId}/labels`);
|
||||
}
|
||||
|
||||
initiateCall(contactId, inboxId) {
|
||||
return axios.post(`${this.url}/${contactId}/call`, {
|
||||
inbox_id: inboxId,
|
||||
});
|
||||
}
|
||||
|
||||
updateContactLabels(contactId, labels) {
|
||||
return axios.post(`${this.url}/${contactId}/labels`, { labels });
|
||||
}
|
||||
|
||||
search(search = '', page = 1, sortAttr = 'name', label = '') {
|
||||
let requestURL = `${this.url}/search?${buildContactParams(
|
||||
page,
|
||||
sortAttr,
|
||||
label,
|
||||
search
|
||||
)}`;
|
||||
return axios.get(requestURL);
|
||||
}
|
||||
|
||||
active(page = 1, sortAttr = 'name') {
|
||||
let requestURL = `${this.url}/active?${buildContactParams(page, sortAttr)}`;
|
||||
return axios.get(requestURL);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line default-param-last
|
||||
filter(page = 1, sortAttr = 'name', queryPayload) {
|
||||
let requestURL = `${this.url}/filter?${buildContactParams(page, sortAttr)}`;
|
||||
return axios.post(requestURL, queryPayload);
|
||||
}
|
||||
|
||||
importContacts(file) {
|
||||
const formData = new FormData();
|
||||
formData.append('import_file', file);
|
||||
return axios.post(`${this.url}/import`, formData, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
});
|
||||
}
|
||||
|
||||
destroyCustomAttributes(contactId, customAttributes) {
|
||||
return axios.post(`${this.url}/${contactId}/destroy_custom_attributes`, {
|
||||
custom_attributes: customAttributes,
|
||||
});
|
||||
}
|
||||
|
||||
destroyAvatar(contactId) {
|
||||
return axios.delete(`${this.url}/${contactId}/avatar`);
|
||||
}
|
||||
|
||||
exportContacts(queryPayload) {
|
||||
return axios.post(`${this.url}/export`, queryPayload);
|
||||
}
|
||||
}
|
||||
|
||||
export default new ContactAPI();
|
||||
@@ -0,0 +1,18 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class ConversationApi extends ApiClient {
|
||||
constructor() {
|
||||
super('conversations', { accountScoped: true });
|
||||
}
|
||||
|
||||
getLabels(conversationID) {
|
||||
return axios.get(`${this.url}/${conversationID}/labels`);
|
||||
}
|
||||
|
||||
updateLabels(conversationID, labels) {
|
||||
return axios.post(`${this.url}/${conversationID}/labels`, { labels });
|
||||
}
|
||||
}
|
||||
|
||||
export default new ConversationApi();
|
||||
@@ -0,0 +1,46 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class CSATReportsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('csat_survey_responses', { accountScoped: true });
|
||||
}
|
||||
|
||||
get({ page, from, to, user_ids, inbox_id, team_id, rating } = {}) {
|
||||
return axios.get(this.url, {
|
||||
params: {
|
||||
page,
|
||||
since: from,
|
||||
until: to,
|
||||
sort: '-created_at',
|
||||
user_ids,
|
||||
inbox_id,
|
||||
team_id,
|
||||
rating,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
download({ from, to, user_ids, inbox_id, team_id, rating } = {}) {
|
||||
return axios.get(`${this.url}/download`, {
|
||||
params: {
|
||||
since: from,
|
||||
until: to,
|
||||
sort: '-created_at',
|
||||
user_ids,
|
||||
inbox_id,
|
||||
team_id,
|
||||
rating,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getMetrics({ from, to, user_ids, inbox_id, team_id, rating } = {}) {
|
||||
// no ratings for metrics
|
||||
return axios.get(`${this.url}/metrics`, {
|
||||
params: { since: from, until: to, user_ids, inbox_id, team_id, rating },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new CSATReportsAPI();
|
||||
@@ -0,0 +1,9 @@
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class CustomRole extends ApiClient {
|
||||
constructor() {
|
||||
super('custom_roles', { accountScoped: true });
|
||||
}
|
||||
}
|
||||
|
||||
export default new CustomRole();
|
||||
@@ -0,0 +1,18 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class CustomViewsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('custom_filters', { accountScoped: true });
|
||||
}
|
||||
|
||||
getCustomViewsByFilterType(type) {
|
||||
return axios.get(`${this.url}?filter_type=${type}`);
|
||||
}
|
||||
|
||||
deleteCustomViews(id, type) {
|
||||
return axios.delete(`${this.url}/${id}?filter_type=${type}`);
|
||||
}
|
||||
}
|
||||
|
||||
export default new CustomViewsAPI();
|
||||
@@ -0,0 +1,9 @@
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class DashboardAppsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('dashboard_apps', { accountScoped: true });
|
||||
}
|
||||
}
|
||||
|
||||
export default new DashboardAppsAPI();
|
||||
62
research/chatwoot/app/javascript/dashboard/api/endPoints.js
Normal file
62
research/chatwoot/app/javascript/dashboard/api/endPoints.js
Normal file
@@ -0,0 +1,62 @@
|
||||
/* eslint arrow-body-style: ["error", "always"] */
|
||||
|
||||
const endPoints = {
|
||||
resetPassword: {
|
||||
url: 'auth/password',
|
||||
},
|
||||
register: {
|
||||
url: 'api/v1/accounts.json',
|
||||
},
|
||||
validityCheck: {
|
||||
url: '/auth/validate_token',
|
||||
},
|
||||
profileUpdate: {
|
||||
url: '/api/v1/profile',
|
||||
},
|
||||
availabilityUpdate: {
|
||||
url: '/api/v1/profile/availability',
|
||||
},
|
||||
autoOffline: {
|
||||
url: '/api/v1/profile/auto_offline',
|
||||
},
|
||||
logout: {
|
||||
url: 'auth/sign_out',
|
||||
},
|
||||
|
||||
me: {
|
||||
url: 'api/v1/conversations.json',
|
||||
params: { type: 0, page: 1 },
|
||||
},
|
||||
|
||||
getInbox: {
|
||||
url: 'api/v1/conversations.json',
|
||||
params: { inbox_id: null },
|
||||
},
|
||||
|
||||
fetchFacebookPages: {
|
||||
url(accountId) {
|
||||
return `api/v1/accounts/${accountId}/callbacks/facebook_pages.json`;
|
||||
},
|
||||
params: { omniauth_token: '' },
|
||||
},
|
||||
|
||||
deleteAvatar: {
|
||||
url: '/api/v1/profile/avatar',
|
||||
},
|
||||
|
||||
setActiveAccount: {
|
||||
url: '/api/v1/profile/set_active_account',
|
||||
},
|
||||
|
||||
resendConfirmation: {
|
||||
url: '/api/v1/profile/resend_confirmation',
|
||||
},
|
||||
|
||||
resetAccessToken: {
|
||||
url: '/api/v1/profile/reset_access_token',
|
||||
},
|
||||
};
|
||||
|
||||
export default page => {
|
||||
return endPoints[page];
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class EnterpriseAccountAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('', { accountScoped: true, enterprise: true });
|
||||
}
|
||||
|
||||
checkout() {
|
||||
return axios.post(`${this.url}checkout`);
|
||||
}
|
||||
|
||||
subscription() {
|
||||
return axios.post(`${this.url}subscription`);
|
||||
}
|
||||
|
||||
getLimits() {
|
||||
return axios.get(`${this.url}limits`);
|
||||
}
|
||||
|
||||
toggleDeletion(action) {
|
||||
return axios.post(`${this.url}toggle_deletion`, {
|
||||
action_type: action,
|
||||
});
|
||||
}
|
||||
|
||||
createTopupCheckout(credits) {
|
||||
return axios.post(`${this.url}topup_checkout`, { credits });
|
||||
}
|
||||
}
|
||||
|
||||
export default new EnterpriseAccountAPI();
|
||||
@@ -0,0 +1,89 @@
|
||||
import accountAPI from '../account';
|
||||
import ApiClient from '../../ApiClient';
|
||||
|
||||
describe('#enterpriseAccountAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(accountAPI).toBeInstanceOf(ApiClient);
|
||||
expect(accountAPI).toHaveProperty('get');
|
||||
expect(accountAPI).toHaveProperty('show');
|
||||
expect(accountAPI).toHaveProperty('create');
|
||||
expect(accountAPI).toHaveProperty('update');
|
||||
expect(accountAPI).toHaveProperty('delete');
|
||||
expect(accountAPI).toHaveProperty('checkout');
|
||||
expect(accountAPI).toHaveProperty('toggleDeletion');
|
||||
expect(accountAPI).toHaveProperty('createTopupCheckout');
|
||||
expect(accountAPI).toHaveProperty('getLimits');
|
||||
});
|
||||
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#checkout', () => {
|
||||
accountAPI.checkout();
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/enterprise/api/v1/checkout'
|
||||
);
|
||||
});
|
||||
|
||||
it('#subscription', () => {
|
||||
accountAPI.subscription();
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/enterprise/api/v1/subscription'
|
||||
);
|
||||
});
|
||||
|
||||
it('#toggleDeletion with delete action', () => {
|
||||
accountAPI.toggleDeletion('delete');
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/enterprise/api/v1/toggle_deletion',
|
||||
{ action_type: 'delete' }
|
||||
);
|
||||
});
|
||||
|
||||
it('#toggleDeletion with undelete action', () => {
|
||||
accountAPI.toggleDeletion('undelete');
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/enterprise/api/v1/toggle_deletion',
|
||||
{ action_type: 'undelete' }
|
||||
);
|
||||
});
|
||||
|
||||
it('#createTopupCheckout with credits', () => {
|
||||
accountAPI.createTopupCheckout(1000);
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/enterprise/api/v1/topup_checkout',
|
||||
{ credits: 1000 }
|
||||
);
|
||||
});
|
||||
|
||||
it('#createTopupCheckout with different credit amounts', () => {
|
||||
const creditAmounts = [1000, 2500, 6000, 12000];
|
||||
creditAmounts.forEach(credits => {
|
||||
accountAPI.createTopupCheckout(credits);
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/enterprise/api/v1/topup_checkout',
|
||||
{ credits }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('#getLimits', () => {
|
||||
accountAPI.getLimits();
|
||||
expect(axiosMock.get).toHaveBeenCalledWith('/enterprise/api/v1/limits');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,77 @@
|
||||
/* global axios */
|
||||
|
||||
import PortalsAPI from './portals';
|
||||
import { getArticleSearchURL } from 'dashboard/helper/URLHelper.js';
|
||||
|
||||
class ArticlesAPI extends PortalsAPI {
|
||||
constructor() {
|
||||
super('articles', { accountScoped: true });
|
||||
}
|
||||
|
||||
getArticles({
|
||||
pageNumber,
|
||||
portalSlug,
|
||||
locale,
|
||||
status,
|
||||
authorId,
|
||||
categorySlug,
|
||||
sort,
|
||||
}) {
|
||||
const url = getArticleSearchURL({
|
||||
pageNumber,
|
||||
portalSlug,
|
||||
locale,
|
||||
status,
|
||||
authorId,
|
||||
categorySlug,
|
||||
sort,
|
||||
host: this.url,
|
||||
});
|
||||
|
||||
return axios.get(url);
|
||||
}
|
||||
|
||||
searchArticles({ portalSlug, query }) {
|
||||
const url = getArticleSearchURL({
|
||||
portalSlug,
|
||||
query,
|
||||
host: this.url,
|
||||
});
|
||||
return axios.get(url);
|
||||
}
|
||||
|
||||
getArticle({ id, portalSlug }) {
|
||||
return axios.get(`${this.url}/${portalSlug}/articles/${id}`);
|
||||
}
|
||||
|
||||
updateArticle({ portalSlug, articleId, articleObj }) {
|
||||
return axios.patch(
|
||||
`${this.url}/${portalSlug}/articles/${articleId}`,
|
||||
articleObj
|
||||
);
|
||||
}
|
||||
|
||||
createArticle({ portalSlug, articleObj }) {
|
||||
const { content, title, authorId, categoryId, locale } = articleObj;
|
||||
return axios.post(`${this.url}/${portalSlug}/articles`, {
|
||||
content,
|
||||
title,
|
||||
author_id: authorId,
|
||||
category_id: categoryId,
|
||||
locale,
|
||||
});
|
||||
}
|
||||
|
||||
deleteArticle({ articleId, portalSlug }) {
|
||||
return axios.delete(`${this.url}/${portalSlug}/articles/${articleId}`);
|
||||
}
|
||||
|
||||
reorderArticles({ portalSlug, reorderedGroup, categorySlug }) {
|
||||
return axios.post(`${this.url}/${portalSlug}/articles/reorder`, {
|
||||
positions_hash: reorderedGroup,
|
||||
category_slug: categorySlug,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new ArticlesAPI();
|
||||
@@ -0,0 +1,30 @@
|
||||
/* global axios */
|
||||
|
||||
import PortalsAPI from './portals';
|
||||
|
||||
class CategoriesAPI extends PortalsAPI {
|
||||
constructor() {
|
||||
super('categories', { accountScoped: true });
|
||||
}
|
||||
|
||||
get({ portalSlug, locale }) {
|
||||
return axios.get(`${this.url}/${portalSlug}/categories?locale=${locale}`);
|
||||
}
|
||||
|
||||
create({ portalSlug, categoryObj }) {
|
||||
return axios.post(`${this.url}/${portalSlug}/categories`, categoryObj);
|
||||
}
|
||||
|
||||
update({ portalSlug, categoryId, categoryObj }) {
|
||||
return axios.patch(
|
||||
`${this.url}/${portalSlug}/categories/${categoryId}`,
|
||||
categoryObj
|
||||
);
|
||||
}
|
||||
|
||||
delete({ portalSlug, categoryId }) {
|
||||
return axios.delete(`${this.url}/${portalSlug}/categories/${categoryId}`);
|
||||
}
|
||||
}
|
||||
|
||||
export default new CategoriesAPI();
|
||||
@@ -0,0 +1,34 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class PortalsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('portals', { accountScoped: true });
|
||||
}
|
||||
|
||||
getPortal({ portalSlug, locale }) {
|
||||
return axios.get(`${this.url}/${portalSlug}?locale=${locale}`);
|
||||
}
|
||||
|
||||
updatePortal({ portalSlug, portalObj }) {
|
||||
return axios.patch(`${this.url}/${portalSlug}`, portalObj);
|
||||
}
|
||||
|
||||
deletePortal(portalSlug) {
|
||||
return axios.delete(`${this.url}/${portalSlug}`);
|
||||
}
|
||||
|
||||
deleteLogo(portalSlug) {
|
||||
return axios.delete(`${this.url}/${portalSlug}/logo`);
|
||||
}
|
||||
|
||||
sendCnameInstructions(portalSlug, email) {
|
||||
return axios.post(`${this.url}/${portalSlug}/send_instructions`, { email });
|
||||
}
|
||||
|
||||
sslStatus(portalSlug) {
|
||||
return axios.get(`${this.url}/${portalSlug}/ssl_status`);
|
||||
}
|
||||
}
|
||||
|
||||
export default PortalsAPI;
|
||||
@@ -0,0 +1,145 @@
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class ConversationApi extends ApiClient {
|
||||
constructor() {
|
||||
super('conversations', { accountScoped: true });
|
||||
}
|
||||
|
||||
get({
|
||||
inboxId,
|
||||
status,
|
||||
assigneeType,
|
||||
page,
|
||||
labels,
|
||||
teamId,
|
||||
conversationType,
|
||||
sortBy,
|
||||
updatedWithin,
|
||||
}) {
|
||||
return axios.get(this.url, {
|
||||
params: {
|
||||
inbox_id: inboxId,
|
||||
team_id: teamId,
|
||||
status,
|
||||
assignee_type: assigneeType,
|
||||
page,
|
||||
labels,
|
||||
conversation_type: conversationType,
|
||||
sort_by: sortBy,
|
||||
updated_within: updatedWithin,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
filter(payload) {
|
||||
return axios.post(`${this.url}/filter`, payload.queryData, {
|
||||
params: {
|
||||
page: payload.page,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
search({ q }) {
|
||||
return axios.get(`${this.url}/search`, {
|
||||
params: {
|
||||
q,
|
||||
page: 1,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
toggleStatus({ conversationId, status, snoozedUntil = null }) {
|
||||
return axios.post(`${this.url}/${conversationId}/toggle_status`, {
|
||||
status,
|
||||
snoozed_until: snoozedUntil,
|
||||
});
|
||||
}
|
||||
|
||||
togglePriority({ conversationId, priority }) {
|
||||
return axios.post(`${this.url}/${conversationId}/toggle_priority`, {
|
||||
priority,
|
||||
});
|
||||
}
|
||||
|
||||
assignAgent({ conversationId, agentId }) {
|
||||
return axios.post(`${this.url}/${conversationId}/assignments`, {
|
||||
assignee_id: agentId,
|
||||
});
|
||||
}
|
||||
|
||||
assignTeam({ conversationId, teamId }) {
|
||||
const params = { team_id: teamId };
|
||||
return axios.post(`${this.url}/${conversationId}/assignments`, params);
|
||||
}
|
||||
|
||||
markMessageRead({ id }) {
|
||||
return axios.post(`${this.url}/${id}/update_last_seen`);
|
||||
}
|
||||
|
||||
markMessagesUnread({ id }) {
|
||||
return axios.post(`${this.url}/${id}/unread`);
|
||||
}
|
||||
|
||||
toggleTyping({ conversationId, status, isPrivate }) {
|
||||
return axios.post(`${this.url}/${conversationId}/toggle_typing_status`, {
|
||||
typing_status: status,
|
||||
is_private: isPrivate,
|
||||
});
|
||||
}
|
||||
|
||||
mute(conversationId) {
|
||||
return axios.post(`${this.url}/${conversationId}/mute`);
|
||||
}
|
||||
|
||||
unmute(conversationId) {
|
||||
return axios.post(`${this.url}/${conversationId}/unmute`);
|
||||
}
|
||||
|
||||
meta({ inboxId, status, assigneeType, labels, teamId, conversationType }) {
|
||||
return axios.get(`${this.url}/meta`, {
|
||||
params: {
|
||||
inbox_id: inboxId,
|
||||
status,
|
||||
assignee_type: assigneeType,
|
||||
labels,
|
||||
team_id: teamId,
|
||||
conversation_type: conversationType,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
sendEmailTranscript({ conversationId, email }) {
|
||||
return axios.post(`${this.url}/${conversationId}/transcript`, { email });
|
||||
}
|
||||
|
||||
updateCustomAttributes({ conversationId, customAttributes }) {
|
||||
return axios.post(`${this.url}/${conversationId}/custom_attributes`, {
|
||||
custom_attributes: customAttributes,
|
||||
});
|
||||
}
|
||||
|
||||
fetchParticipants(conversationId) {
|
||||
return axios.get(`${this.url}/${conversationId}/participants`);
|
||||
}
|
||||
|
||||
updateParticipants({ conversationId, userIds }) {
|
||||
return axios.patch(`${this.url}/${conversationId}/participants`, {
|
||||
user_ids: userIds,
|
||||
});
|
||||
}
|
||||
|
||||
getAllAttachments(conversationId) {
|
||||
return axios.get(`${this.url}/${conversationId}/attachments`);
|
||||
}
|
||||
|
||||
getInboxAssistant(conversationId) {
|
||||
return axios.get(`${this.url}/${conversationId}/inbox_assistant`);
|
||||
}
|
||||
|
||||
delete(conversationId) {
|
||||
return axios.delete(`${this.url}/${conversationId}`);
|
||||
}
|
||||
}
|
||||
|
||||
export default new ConversationApi();
|
||||
113
research/chatwoot/app/javascript/dashboard/api/inbox/message.js
Normal file
113
research/chatwoot/app/javascript/dashboard/api/inbox/message.js
Normal file
@@ -0,0 +1,113 @@
|
||||
/* eslint no-console: 0 */
|
||||
/* global axios */
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
export const buildCreatePayload = ({
|
||||
message,
|
||||
isPrivate,
|
||||
contentAttributes,
|
||||
echoId,
|
||||
files,
|
||||
ccEmails = '',
|
||||
bccEmails = '',
|
||||
toEmails = '',
|
||||
templateParams,
|
||||
}) => {
|
||||
let payload;
|
||||
if (files && files.length !== 0) {
|
||||
payload = new FormData();
|
||||
if (message) {
|
||||
payload.append('content', message);
|
||||
}
|
||||
files.forEach(file => {
|
||||
payload.append('attachments[]', file);
|
||||
});
|
||||
payload.append('private', isPrivate);
|
||||
payload.append('echo_id', echoId);
|
||||
payload.append('cc_emails', ccEmails);
|
||||
payload.append('bcc_emails', bccEmails);
|
||||
|
||||
if (toEmails) {
|
||||
payload.append('to_emails', toEmails);
|
||||
}
|
||||
if (contentAttributes) {
|
||||
payload.append('content_attributes', JSON.stringify(contentAttributes));
|
||||
}
|
||||
} else {
|
||||
payload = {
|
||||
content: message,
|
||||
private: isPrivate,
|
||||
echo_id: echoId,
|
||||
content_attributes: contentAttributes,
|
||||
cc_emails: ccEmails,
|
||||
bcc_emails: bccEmails,
|
||||
to_emails: toEmails,
|
||||
template_params: templateParams,
|
||||
};
|
||||
}
|
||||
return payload;
|
||||
};
|
||||
|
||||
class MessageApi extends ApiClient {
|
||||
constructor() {
|
||||
super('conversations', { accountScoped: true });
|
||||
}
|
||||
|
||||
create({
|
||||
conversationId,
|
||||
message,
|
||||
private: isPrivate,
|
||||
contentAttributes,
|
||||
echo_id: echoId,
|
||||
files,
|
||||
ccEmails = '',
|
||||
bccEmails = '',
|
||||
toEmails = '',
|
||||
templateParams,
|
||||
}) {
|
||||
return axios({
|
||||
method: 'post',
|
||||
url: `${this.url}/${conversationId}/messages`,
|
||||
data: buildCreatePayload({
|
||||
message,
|
||||
isPrivate,
|
||||
contentAttributes,
|
||||
echoId,
|
||||
files,
|
||||
ccEmails,
|
||||
bccEmails,
|
||||
toEmails,
|
||||
templateParams,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
delete(conversationID, messageId) {
|
||||
return axios.delete(`${this.url}/${conversationID}/messages/${messageId}`);
|
||||
}
|
||||
|
||||
retry(conversationID, messageId) {
|
||||
return axios.post(
|
||||
`${this.url}/${conversationID}/messages/${messageId}/retry`
|
||||
);
|
||||
}
|
||||
|
||||
getPreviousMessages({ conversationId, after, before }) {
|
||||
const params = { before };
|
||||
if (after && Number(after) !== Number(before)) {
|
||||
params.after = after;
|
||||
}
|
||||
return axios.get(`${this.url}/${conversationId}/messages`, { params });
|
||||
}
|
||||
|
||||
translateMessage(conversationId, messageId, targetLanguage) {
|
||||
return axios.post(
|
||||
`${this.url}/${conversationId}/messages/${messageId}/translate`,
|
||||
{
|
||||
target_language: targetLanguage,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default new MessageApi();
|
||||
@@ -0,0 +1,14 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class InboxHealthAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('inboxes', { accountScoped: true });
|
||||
}
|
||||
|
||||
getHealthStatus(inboxId) {
|
||||
return axios.get(`${this.url}/${inboxId}/health`);
|
||||
}
|
||||
}
|
||||
|
||||
export default new InboxHealthAPI();
|
||||
@@ -0,0 +1,17 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class InboxMembers extends ApiClient {
|
||||
constructor() {
|
||||
super('inbox_members', { accountScoped: true });
|
||||
}
|
||||
|
||||
update({ inboxId, agentList }) {
|
||||
return axios.patch(this.url, {
|
||||
inbox_id: inboxId,
|
||||
user_ids: agentList,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new InboxMembers();
|
||||
47
research/chatwoot/app/javascript/dashboard/api/inboxes.js
Normal file
47
research/chatwoot/app/javascript/dashboard/api/inboxes.js
Normal file
@@ -0,0 +1,47 @@
|
||||
/* global axios */
|
||||
import CacheEnabledApiClient from './CacheEnabledApiClient';
|
||||
|
||||
class Inboxes extends CacheEnabledApiClient {
|
||||
constructor() {
|
||||
super('inboxes', { accountScoped: true });
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
get cacheModelName() {
|
||||
return 'inbox';
|
||||
}
|
||||
|
||||
getCampaigns(inboxId) {
|
||||
return axios.get(`${this.url}/${inboxId}/campaigns`);
|
||||
}
|
||||
|
||||
deleteInboxAvatar(inboxId) {
|
||||
return axios.delete(`${this.url}/${inboxId}/avatar`);
|
||||
}
|
||||
|
||||
getAgentBot(inboxId) {
|
||||
return axios.get(`${this.url}/${inboxId}/agent_bot`);
|
||||
}
|
||||
|
||||
setAgentBot(inboxId, botId) {
|
||||
return axios.post(`${this.url}/${inboxId}/set_agent_bot`, {
|
||||
agent_bot: botId,
|
||||
});
|
||||
}
|
||||
|
||||
syncTemplates(inboxId) {
|
||||
return axios.post(`${this.url}/${inboxId}/sync_templates`);
|
||||
}
|
||||
|
||||
createCSATTemplate(inboxId, template) {
|
||||
return axios.post(`${this.url}/${inboxId}/csat_template`, {
|
||||
template,
|
||||
});
|
||||
}
|
||||
|
||||
getCSATTemplateStatus(inboxId) {
|
||||
return axios.get(`${this.url}/${inboxId}/csat_template`);
|
||||
}
|
||||
}
|
||||
|
||||
export default new Inboxes();
|
||||
@@ -0,0 +1,43 @@
|
||||
/* global axios */
|
||||
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class IntegrationsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('integrations/apps', { accountScoped: true });
|
||||
}
|
||||
|
||||
connectSlack(code) {
|
||||
return axios.post(`${this.baseUrl()}/integrations/slack`, { code });
|
||||
}
|
||||
|
||||
updateSlack({ referenceId }) {
|
||||
return axios.patch(`${this.baseUrl()}/integrations/slack`, {
|
||||
reference_id: referenceId,
|
||||
});
|
||||
}
|
||||
|
||||
listAllSlackChannels() {
|
||||
return axios.get(`${this.baseUrl()}/integrations/slack/list_all_channels`);
|
||||
}
|
||||
|
||||
delete(integrationId) {
|
||||
return axios.delete(`${this.baseUrl()}/integrations/${integrationId}`);
|
||||
}
|
||||
|
||||
createHook(hookData) {
|
||||
return axios.post(`${this.baseUrl()}/integrations/hooks`, hookData);
|
||||
}
|
||||
|
||||
deleteHook(hookId) {
|
||||
return axios.delete(`${this.baseUrl()}/integrations/hooks/${hookId}`);
|
||||
}
|
||||
|
||||
connectShopify({ shopDomain }) {
|
||||
return axios.post(`${this.baseUrl()}/integrations/shopify/auth`, {
|
||||
shop_domain: shopDomain,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new IntegrationsAPI();
|
||||
@@ -0,0 +1,23 @@
|
||||
/* global axios */
|
||||
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class DyteAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('integrations/dyte', { accountScoped: true });
|
||||
}
|
||||
|
||||
createAMeeting(conversationId) {
|
||||
return axios.post(`${this.url}/create_a_meeting`, {
|
||||
conversation_id: conversationId,
|
||||
});
|
||||
}
|
||||
|
||||
addParticipantToMeeting(messageId) {
|
||||
return axios.post(`${this.url}/add_participant_to_meeting`, {
|
||||
message_id: messageId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new DyteAPI();
|
||||
@@ -0,0 +1,49 @@
|
||||
/* global axios */
|
||||
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class LinearAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('integrations/linear', { accountScoped: true });
|
||||
}
|
||||
|
||||
getTeams() {
|
||||
return axios.get(`${this.url}/teams`);
|
||||
}
|
||||
|
||||
getTeamEntities(teamId) {
|
||||
return axios.get(`${this.url}/team_entities?team_id=${teamId}`);
|
||||
}
|
||||
|
||||
createIssue(data) {
|
||||
return axios.post(`${this.url}/create_issue`, data);
|
||||
}
|
||||
|
||||
link_issue(conversationId, issueId, title) {
|
||||
return axios.post(`${this.url}/link_issue`, {
|
||||
issue_id: issueId,
|
||||
conversation_id: conversationId,
|
||||
title: title,
|
||||
});
|
||||
}
|
||||
|
||||
getLinkedIssue(conversationId) {
|
||||
return axios.get(
|
||||
`${this.url}/linked_issues?conversation_id=${conversationId}`
|
||||
);
|
||||
}
|
||||
|
||||
unlinkIssue(linkId, issueIdentifier, conversationId) {
|
||||
return axios.post(`${this.url}/unlink_issue`, {
|
||||
link_id: linkId,
|
||||
issue_id: issueIdentifier,
|
||||
conversation_id: conversationId,
|
||||
});
|
||||
}
|
||||
|
||||
searchIssues(query) {
|
||||
return axios.get(`${this.url}/search_issue?q=${query}`);
|
||||
}
|
||||
}
|
||||
|
||||
export default new LinearAPI();
|
||||
@@ -0,0 +1,17 @@
|
||||
/* global axios */
|
||||
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
class ShopifyAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('integrations/shopify', { accountScoped: true });
|
||||
}
|
||||
|
||||
getOrders(contactId) {
|
||||
return axios.get(`${this.url}/orders`, {
|
||||
params: { contact_id: contactId },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new ShopifyAPI();
|
||||
14
research/chatwoot/app/javascript/dashboard/api/labels.js
Normal file
14
research/chatwoot/app/javascript/dashboard/api/labels.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import CacheEnabledApiClient from './CacheEnabledApiClient';
|
||||
|
||||
class LabelsAPI extends CacheEnabledApiClient {
|
||||
constructor() {
|
||||
super('labels', { accountScoped: true });
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
get cacheModelName() {
|
||||
return 'label';
|
||||
}
|
||||
}
|
||||
|
||||
export default new LabelsAPI();
|
||||
@@ -0,0 +1,20 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class LiveReportsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('live_reports', { accountScoped: true, apiVersion: 'v2' });
|
||||
}
|
||||
|
||||
getConversationMetric(params = {}) {
|
||||
return axios.get(`${this.url}/conversation_metrics`, { params });
|
||||
}
|
||||
|
||||
getGroupedConversations({ groupBy } = { groupBy: 'assignee_id' }) {
|
||||
return axios.get(`${this.url}/grouped_conversation_metrics`, {
|
||||
params: { group_by: groupBy },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new LiveReportsAPI();
|
||||
16
research/chatwoot/app/javascript/dashboard/api/macros.js
Normal file
16
research/chatwoot/app/javascript/dashboard/api/macros.js
Normal file
@@ -0,0 +1,16 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class MacrosAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('macros', { accountScoped: true });
|
||||
}
|
||||
|
||||
executeMacro({ macroId, conversationIds }) {
|
||||
return axios.post(`${this.url}/${macroId}/execute`, {
|
||||
conversation_ids: conversationIds,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new MacrosAPI();
|
||||
28
research/chatwoot/app/javascript/dashboard/api/mfa.js
Normal file
28
research/chatwoot/app/javascript/dashboard/api/mfa.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class MfaAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('profile/mfa', { accountScoped: false });
|
||||
}
|
||||
|
||||
enable() {
|
||||
return axios.post(`${this.url}`);
|
||||
}
|
||||
|
||||
verify(otpCode) {
|
||||
return axios.post(`${this.url}/verify`, { otp_code: otpCode });
|
||||
}
|
||||
|
||||
disable(password, otpCode) {
|
||||
return axios.delete(this.url, {
|
||||
data: { password, otp_code: otpCode },
|
||||
});
|
||||
}
|
||||
|
||||
regenerateBackupCodes(otpCode) {
|
||||
return axios.post(`${this.url}/backup_codes`, { otp_code: otpCode });
|
||||
}
|
||||
}
|
||||
|
||||
export default new MfaAPI();
|
||||
@@ -0,0 +1,9 @@
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class NotificationSubscriptions extends ApiClient {
|
||||
constructor() {
|
||||
super('notification_subscriptions');
|
||||
}
|
||||
}
|
||||
|
||||
export default new NotificationSubscriptions();
|
||||
@@ -0,0 +1,61 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class NotificationsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('notifications', { accountScoped: true });
|
||||
}
|
||||
|
||||
get({ page, status, type, sortOrder }) {
|
||||
const includesFilter = [status, type].filter(value => !!value);
|
||||
|
||||
return axios.get(this.url, {
|
||||
params: {
|
||||
page,
|
||||
sort_order: sortOrder,
|
||||
includes: includesFilter,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getNotifications(contactId) {
|
||||
return axios.get(`${this.url}/${contactId}/notifications`);
|
||||
}
|
||||
|
||||
getUnreadCount() {
|
||||
return axios.get(`${this.url}/unread_count`);
|
||||
}
|
||||
|
||||
read(primaryActorType, primaryActorId) {
|
||||
return axios.post(`${this.url}/read_all`, {
|
||||
primary_actor_type: primaryActorType,
|
||||
primary_actor_id: primaryActorId,
|
||||
});
|
||||
}
|
||||
|
||||
unRead(id) {
|
||||
return axios.post(`${this.url}/${id}/unread`);
|
||||
}
|
||||
|
||||
readAll() {
|
||||
return axios.post(`${this.url}/read_all`);
|
||||
}
|
||||
|
||||
delete(id) {
|
||||
return axios.delete(`${this.url}/${id}`);
|
||||
}
|
||||
|
||||
deleteAll({ type = 'all' }) {
|
||||
return axios.post(`${this.url}/destroy_all`, {
|
||||
type,
|
||||
});
|
||||
}
|
||||
|
||||
snooze({ id, snoozedUntil = null }) {
|
||||
return axios.post(`${this.url}/${id}/snooze`, {
|
||||
snoozed_until: snoozedUntil,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new NotificationsAPI();
|
||||
@@ -0,0 +1,14 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class NotionOAuthClient extends ApiClient {
|
||||
constructor() {
|
||||
super('notion', { accountScoped: true });
|
||||
}
|
||||
|
||||
generateAuthorization() {
|
||||
return axios.post(`${this.url}/authorization`);
|
||||
}
|
||||
}
|
||||
|
||||
export default new NotionOAuthClient();
|
||||
113
research/chatwoot/app/javascript/dashboard/api/reports.js
Normal file
113
research/chatwoot/app/javascript/dashboard/api/reports.js
Normal file
@@ -0,0 +1,113 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
const getTimeOffset = () => -new Date().getTimezoneOffset() / 60;
|
||||
|
||||
class ReportsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('reports', { accountScoped: true, apiVersion: 'v2' });
|
||||
}
|
||||
|
||||
getReports({
|
||||
metric,
|
||||
from,
|
||||
to,
|
||||
type = 'account',
|
||||
id,
|
||||
groupBy,
|
||||
businessHours,
|
||||
}) {
|
||||
return axios.get(`${this.url}`, {
|
||||
params: {
|
||||
metric,
|
||||
since: from,
|
||||
until: to,
|
||||
type,
|
||||
id,
|
||||
group_by: groupBy,
|
||||
business_hours: businessHours,
|
||||
timezone_offset: getTimeOffset(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line default-param-last
|
||||
getSummary(since, until, type = 'account', id, groupBy, businessHours) {
|
||||
return axios.get(`${this.url}/summary`, {
|
||||
params: {
|
||||
since,
|
||||
until,
|
||||
type,
|
||||
id,
|
||||
group_by: groupBy,
|
||||
business_hours: businessHours,
|
||||
timezone_offset: getTimeOffset(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getConversationMetric(type = 'account', page = 1) {
|
||||
return axios.get(`${this.url}/conversations`, {
|
||||
params: {
|
||||
type,
|
||||
page,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getAgentReports({ from: since, to: until, businessHours }) {
|
||||
return axios.get(`${this.url}/agents`, {
|
||||
params: { since, until, business_hours: businessHours },
|
||||
});
|
||||
}
|
||||
|
||||
getConversationsSummaryReports({ from: since, to: until, businessHours }) {
|
||||
return axios.get(`${this.url}/conversations_summary`, {
|
||||
params: { since, until, business_hours: businessHours },
|
||||
});
|
||||
}
|
||||
|
||||
getConversationTrafficCSV({ daysBefore = 6 } = {}) {
|
||||
return axios.get(`${this.url}/conversation_traffic`, {
|
||||
params: { timezone_offset: getTimeOffset(), days_before: daysBefore },
|
||||
});
|
||||
}
|
||||
|
||||
getLabelReports({ from: since, to: until, businessHours }) {
|
||||
return axios.get(`${this.url}/labels`, {
|
||||
params: { since, until, business_hours: businessHours },
|
||||
});
|
||||
}
|
||||
|
||||
getInboxReports({ from: since, to: until, businessHours }) {
|
||||
return axios.get(`${this.url}/inboxes`, {
|
||||
params: { since, until, business_hours: businessHours },
|
||||
});
|
||||
}
|
||||
|
||||
getTeamReports({ from: since, to: until, businessHours }) {
|
||||
return axios.get(`${this.url}/teams`, {
|
||||
params: { since, until, business_hours: businessHours },
|
||||
});
|
||||
}
|
||||
|
||||
getBotMetrics({ from, to } = {}) {
|
||||
return axios.get(`${this.url}/bot_metrics`, {
|
||||
params: { since: from, until: to },
|
||||
});
|
||||
}
|
||||
|
||||
getBotSummary({ from, to, groupBy, businessHours } = {}) {
|
||||
return axios.get(`${this.url}/bot_summary`, {
|
||||
params: {
|
||||
since: from,
|
||||
until: to,
|
||||
type: 'account',
|
||||
group_by: groupBy,
|
||||
business_hours: businessHours,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new ReportsAPI();
|
||||
@@ -0,0 +1,26 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class SamlSettingsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('saml_settings', { accountScoped: true });
|
||||
}
|
||||
|
||||
get() {
|
||||
return axios.get(this.url);
|
||||
}
|
||||
|
||||
create(data) {
|
||||
return axios.post(this.url, { saml_settings: data });
|
||||
}
|
||||
|
||||
update(data) {
|
||||
return axios.put(this.url, { saml_settings: data });
|
||||
}
|
||||
|
||||
delete() {
|
||||
return axios.delete(this.url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new SamlSettingsAPI();
|
||||
64
research/chatwoot/app/javascript/dashboard/api/search.js
Normal file
64
research/chatwoot/app/javascript/dashboard/api/search.js
Normal file
@@ -0,0 +1,64 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class SearchAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('search', { accountScoped: true });
|
||||
}
|
||||
|
||||
get({ q }) {
|
||||
return axios.get(this.url, {
|
||||
params: {
|
||||
q,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
contacts({ q, page = 1, since, until }) {
|
||||
return axios.get(`${this.url}/contacts`, {
|
||||
params: {
|
||||
q,
|
||||
page: page,
|
||||
since,
|
||||
until,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
conversations({ q, page = 1, since, until }) {
|
||||
return axios.get(`${this.url}/conversations`, {
|
||||
params: {
|
||||
q,
|
||||
page: page,
|
||||
since,
|
||||
until,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
messages({ q, page = 1, since, until, from, inboxId }) {
|
||||
return axios.get(`${this.url}/messages`, {
|
||||
params: {
|
||||
q,
|
||||
page: page,
|
||||
since,
|
||||
until,
|
||||
from,
|
||||
inbox_id: inboxId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
articles({ q, page = 1, since, until }) {
|
||||
return axios.get(`${this.url}/articles`, {
|
||||
params: {
|
||||
q,
|
||||
page: page,
|
||||
since,
|
||||
until,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new SearchAPI();
|
||||
9
research/chatwoot/app/javascript/dashboard/api/sla.js
Normal file
9
research/chatwoot/app/javascript/dashboard/api/sla.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class SlaAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('sla_policies', { accountScoped: true });
|
||||
}
|
||||
}
|
||||
|
||||
export default new SlaAPI();
|
||||
78
research/chatwoot/app/javascript/dashboard/api/slaReports.js
Normal file
78
research/chatwoot/app/javascript/dashboard/api/slaReports.js
Normal file
@@ -0,0 +1,78 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class SLAReportsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('applied_slas', { accountScoped: true });
|
||||
}
|
||||
|
||||
get({
|
||||
from,
|
||||
to,
|
||||
assigned_agent_id,
|
||||
inbox_id,
|
||||
team_id,
|
||||
sla_policy_id,
|
||||
label_list,
|
||||
page,
|
||||
} = {}) {
|
||||
return axios.get(this.url, {
|
||||
params: {
|
||||
since: from,
|
||||
until: to,
|
||||
assigned_agent_id,
|
||||
inbox_id,
|
||||
team_id,
|
||||
sla_policy_id,
|
||||
label_list,
|
||||
page,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
download({
|
||||
from,
|
||||
to,
|
||||
assigned_agent_id,
|
||||
inbox_id,
|
||||
team_id,
|
||||
sla_policy_id,
|
||||
label_list,
|
||||
} = {}) {
|
||||
return axios.get(`${this.url}/download`, {
|
||||
params: {
|
||||
since: from,
|
||||
until: to,
|
||||
assigned_agent_id,
|
||||
inbox_id,
|
||||
team_id,
|
||||
label_list,
|
||||
sla_policy_id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getMetrics({
|
||||
from,
|
||||
to,
|
||||
assigned_agent_id,
|
||||
inbox_id,
|
||||
team_id,
|
||||
label_list,
|
||||
sla_policy_id,
|
||||
} = {}) {
|
||||
return axios.get(`${this.url}/metrics`, {
|
||||
params: {
|
||||
since: from,
|
||||
until: to,
|
||||
assigned_agent_id,
|
||||
inbox_id,
|
||||
label_list,
|
||||
team_id,
|
||||
sla_policy_id,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new SLAReportsAPI();
|
||||
@@ -0,0 +1,41 @@
|
||||
import accountAPI from '../account';
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
describe('#accountAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(accountAPI).toBeInstanceOf(ApiClient);
|
||||
expect(accountAPI).toHaveProperty('get');
|
||||
expect(accountAPI).toHaveProperty('show');
|
||||
expect(accountAPI).toHaveProperty('create');
|
||||
expect(accountAPI).toHaveProperty('update');
|
||||
expect(accountAPI).toHaveProperty('delete');
|
||||
expect(accountAPI).toHaveProperty('createAccount');
|
||||
});
|
||||
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#createAccount', () => {
|
||||
accountAPI.createAccount({
|
||||
name: 'Chatwoot',
|
||||
});
|
||||
expect(axiosMock.post).toHaveBeenCalledWith('/api/v1/accounts', {
|
||||
name: 'Chatwoot',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import accountActionsAPI from '../accountActions';
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
describe('#ContactsAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(accountActionsAPI).toBeInstanceOf(ApiClient);
|
||||
expect(accountActionsAPI).toHaveProperty('merge');
|
||||
});
|
||||
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#merge', () => {
|
||||
accountActionsAPI.merge(1, 2);
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/actions/contact_merge',
|
||||
{
|
||||
base_contact_id: 1,
|
||||
mergee_contact_id: 2,
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
import AgentBotsAPI from '../agentBots';
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
describe('#AgentBotsAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(AgentBotsAPI).toBeInstanceOf(ApiClient);
|
||||
expect(AgentBotsAPI).toHaveProperty('get');
|
||||
expect(AgentBotsAPI).toHaveProperty('show');
|
||||
expect(AgentBotsAPI).toHaveProperty('create');
|
||||
expect(AgentBotsAPI).toHaveProperty('update');
|
||||
expect(AgentBotsAPI).toHaveProperty('delete');
|
||||
expect(AgentBotsAPI).toHaveProperty('resetAccessToken');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,98 @@
|
||||
import agentCapacityPolicies from '../agentCapacityPolicies';
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
describe('#AgentCapacityPoliciesAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(agentCapacityPolicies).toBeInstanceOf(ApiClient);
|
||||
expect(agentCapacityPolicies).toHaveProperty('get');
|
||||
expect(agentCapacityPolicies).toHaveProperty('show');
|
||||
expect(agentCapacityPolicies).toHaveProperty('create');
|
||||
expect(agentCapacityPolicies).toHaveProperty('update');
|
||||
expect(agentCapacityPolicies).toHaveProperty('delete');
|
||||
expect(agentCapacityPolicies).toHaveProperty('getUsers');
|
||||
expect(agentCapacityPolicies).toHaveProperty('addUser');
|
||||
expect(agentCapacityPolicies).toHaveProperty('removeUser');
|
||||
expect(agentCapacityPolicies).toHaveProperty('createInboxLimit');
|
||||
expect(agentCapacityPolicies).toHaveProperty('updateInboxLimit');
|
||||
expect(agentCapacityPolicies).toHaveProperty('deleteInboxLimit');
|
||||
});
|
||||
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
put: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
// Mock accountIdFromRoute
|
||||
Object.defineProperty(agentCapacityPolicies, 'accountIdFromRoute', {
|
||||
get: () => '1',
|
||||
configurable: true,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#getUsers', () => {
|
||||
agentCapacityPolicies.getUsers(123);
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/accounts/1/agent_capacity_policies/123/users'
|
||||
);
|
||||
});
|
||||
|
||||
it('#addUser', () => {
|
||||
const userData = { id: 456, capacity: 20 };
|
||||
agentCapacityPolicies.addUser(123, userData);
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/accounts/1/agent_capacity_policies/123/users',
|
||||
{
|
||||
user_id: 456,
|
||||
capacity: 20,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('#removeUser', () => {
|
||||
agentCapacityPolicies.removeUser(123, 456);
|
||||
expect(axiosMock.delete).toHaveBeenCalledWith(
|
||||
'/api/v1/accounts/1/agent_capacity_policies/123/users/456'
|
||||
);
|
||||
});
|
||||
|
||||
it('#createInboxLimit', () => {
|
||||
const limitData = { inboxId: 1, conversationLimit: 10 };
|
||||
agentCapacityPolicies.createInboxLimit(123, limitData);
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/accounts/1/agent_capacity_policies/123/inbox_limits',
|
||||
{
|
||||
inbox_id: 1,
|
||||
conversation_limit: 10,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('#updateInboxLimit', () => {
|
||||
const limitData = { conversationLimit: 15 };
|
||||
agentCapacityPolicies.updateInboxLimit(123, 789, limitData);
|
||||
expect(axiosMock.put).toHaveBeenCalledWith(
|
||||
'/api/v1/accounts/1/agent_capacity_policies/123/inbox_limits/789',
|
||||
{
|
||||
conversation_limit: 15,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('#deleteInboxLimit', () => {
|
||||
agentCapacityPolicies.deleteInboxLimit(123, 789);
|
||||
expect(axiosMock.delete).toHaveBeenCalledWith(
|
||||
'/api/v1/accounts/1/agent_capacity_policies/123/inbox_limits/789'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import agents from '../agents';
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
describe('#AgentAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(agents).toBeInstanceOf(ApiClient);
|
||||
expect(agents).toHaveProperty('get');
|
||||
expect(agents).toHaveProperty('show');
|
||||
expect(agents).toHaveProperty('create');
|
||||
expect(agents).toHaveProperty('update');
|
||||
expect(agents).toHaveProperty('delete');
|
||||
});
|
||||
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#bulkInvite', () => {
|
||||
agents.bulkInvite({ emails: ['hello@hi.com'] });
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/agents/bulk_create',
|
||||
{
|
||||
emails: ['hello@hi.com'],
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,156 @@
|
||||
import articlesAPI from '../helpCenter/articles';
|
||||
import ApiClient from 'dashboard/api/helpCenter/portals';
|
||||
|
||||
describe('#PortalAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(articlesAPI).toBeInstanceOf(ApiClient);
|
||||
expect(articlesAPI).toHaveProperty('get');
|
||||
expect(articlesAPI).toHaveProperty('show');
|
||||
expect(articlesAPI).toHaveProperty('create');
|
||||
expect(articlesAPI).toHaveProperty('update');
|
||||
expect(articlesAPI).toHaveProperty('delete');
|
||||
expect(articlesAPI).toHaveProperty('getArticles');
|
||||
});
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#getArticles', () => {
|
||||
articlesAPI.getArticles({
|
||||
pageNumber: 1,
|
||||
portalSlug: 'room-rental',
|
||||
locale: 'en-US',
|
||||
status: 'published',
|
||||
authorId: '1',
|
||||
});
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/portals/room-rental/articles?page=1&locale=en-US&status=published&author_id=1'
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#getArticle', () => {
|
||||
articlesAPI.getArticle({
|
||||
id: 1,
|
||||
portalSlug: 'room-rental',
|
||||
});
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/portals/room-rental/articles/1'
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#searchArticles', () => {
|
||||
articlesAPI.searchArticles({
|
||||
query: 'test',
|
||||
portalSlug: 'room-rental',
|
||||
});
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/portals/room-rental/articles?query=test'
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#updateArticle', () => {
|
||||
articlesAPI.updateArticle({
|
||||
articleId: 1,
|
||||
portalSlug: 'room-rental',
|
||||
articleObj: { title: 'Update shipping address' },
|
||||
});
|
||||
expect(axiosMock.patch).toHaveBeenCalledWith(
|
||||
'/api/v1/portals/room-rental/articles/1',
|
||||
{
|
||||
title: 'Update shipping address',
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#deleteArticle', () => {
|
||||
articlesAPI.deleteArticle({
|
||||
articleId: 1,
|
||||
portalSlug: 'room-rental',
|
||||
});
|
||||
expect(axiosMock.delete).toHaveBeenCalledWith(
|
||||
'/api/v1/portals/room-rental/articles/1'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
import assignableAgentsAPI from '../assignableAgents';
|
||||
|
||||
describe('#AssignableAgentsAPI', () => {
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#getAssignableAgents', () => {
|
||||
assignableAgentsAPI.get([1]);
|
||||
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/assignable_agents', {
|
||||
params: {
|
||||
inbox_ids: [1],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
import assignmentPolicies from '../assignmentPolicies';
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
describe('#AssignmentPoliciesAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(assignmentPolicies).toBeInstanceOf(ApiClient);
|
||||
expect(assignmentPolicies).toHaveProperty('get');
|
||||
expect(assignmentPolicies).toHaveProperty('show');
|
||||
expect(assignmentPolicies).toHaveProperty('create');
|
||||
expect(assignmentPolicies).toHaveProperty('update');
|
||||
expect(assignmentPolicies).toHaveProperty('delete');
|
||||
expect(assignmentPolicies).toHaveProperty('getInboxes');
|
||||
expect(assignmentPolicies).toHaveProperty('setInboxPolicy');
|
||||
expect(assignmentPolicies).toHaveProperty('getInboxPolicy');
|
||||
expect(assignmentPolicies).toHaveProperty('removeInboxPolicy');
|
||||
});
|
||||
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
// Mock accountIdFromRoute
|
||||
Object.defineProperty(assignmentPolicies, 'accountIdFromRoute', {
|
||||
get: () => '1',
|
||||
configurable: true,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#getInboxes', () => {
|
||||
assignmentPolicies.getInboxes(123);
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/accounts/1/assignment_policies/123/inboxes'
|
||||
);
|
||||
});
|
||||
|
||||
it('#setInboxPolicy', () => {
|
||||
assignmentPolicies.setInboxPolicy(456, 123);
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/accounts/1/inboxes/456/assignment_policy',
|
||||
{
|
||||
assignment_policy_id: 123,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('#getInboxPolicy', () => {
|
||||
assignmentPolicies.getInboxPolicy(456);
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/accounts/1/inboxes/456/assignment_policy'
|
||||
);
|
||||
});
|
||||
|
||||
it('#removeInboxPolicy', () => {
|
||||
assignmentPolicies.removeInboxPolicy(456);
|
||||
expect(axiosMock.delete).toHaveBeenCalledWith(
|
||||
'/api/v1/accounts/1/inboxes/456/assignment_policy'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import automations from '../automation';
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
describe('#AutomationsAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(automations).toBeInstanceOf(ApiClient);
|
||||
expect(automations).toHaveProperty('get');
|
||||
expect(automations).toHaveProperty('show');
|
||||
expect(automations).toHaveProperty('create');
|
||||
expect(automations).toHaveProperty('update');
|
||||
expect(automations).toHaveProperty('delete');
|
||||
expect(automations).toHaveProperty('clone');
|
||||
expect(automations.url).toBe('/api/v1/automation_rules');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
import bulkActions from '../bulkActions';
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
describe('#BulkActionsAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(bulkActions).toBeInstanceOf(ApiClient);
|
||||
expect(bulkActions).toHaveProperty('create');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
import campaigns from '../campaigns';
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
describe('#CampaignAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(campaigns).toBeInstanceOf(ApiClient);
|
||||
expect(campaigns).toHaveProperty('get');
|
||||
expect(campaigns).toHaveProperty('show');
|
||||
expect(campaigns).toHaveProperty('create');
|
||||
expect(campaigns).toHaveProperty('update');
|
||||
expect(campaigns).toHaveProperty('delete');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
import fbChannel from '../../channel/fbChannel';
|
||||
import ApiClient from '../../ApiClient';
|
||||
|
||||
describe('#FBChannel', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(fbChannel).toBeInstanceOf(ApiClient);
|
||||
expect(fbChannel).toHaveProperty('get');
|
||||
expect(fbChannel).toHaveProperty('show');
|
||||
expect(fbChannel).toHaveProperty('create');
|
||||
expect(fbChannel).toHaveProperty('update');
|
||||
expect(fbChannel).toHaveProperty('delete');
|
||||
});
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#create', () => {
|
||||
fbChannel.create({ omniauthToken: 'ASFM131CSF@#@$', appId: 'chatwoot' });
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/callbacks/register_facebook_page',
|
||||
{
|
||||
omniauthToken: 'ASFM131CSF@#@$',
|
||||
appId: 'chatwoot',
|
||||
}
|
||||
);
|
||||
});
|
||||
it('#reauthorize', () => {
|
||||
fbChannel.reauthorizeFacebookPage({
|
||||
omniauthToken: 'ASFM131CSF@#@$',
|
||||
inboxId: 1,
|
||||
});
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/callbacks/reauthorize_page',
|
||||
{
|
||||
omniauth_token: 'ASFM131CSF@#@$',
|
||||
inbox_id: 1,
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
import twilioChannel from '../../channel/twilioChannel';
|
||||
import ApiClient from '../../ApiClient';
|
||||
|
||||
describe('#twilioChannel', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(twilioChannel).toBeInstanceOf(ApiClient);
|
||||
expect(twilioChannel).toHaveProperty('get');
|
||||
expect(twilioChannel).toHaveProperty('show');
|
||||
expect(twilioChannel).toHaveProperty('create');
|
||||
expect(twilioChannel).toHaveProperty('update');
|
||||
expect(twilioChannel).toHaveProperty('delete');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
import twitterClient from '../../channel/twitterClient';
|
||||
import ApiClient from '../../ApiClient';
|
||||
|
||||
describe('#TwitterClient', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(twitterClient).toBeInstanceOf(ApiClient);
|
||||
expect(twitterClient).toHaveProperty('get');
|
||||
expect(twitterClient).toHaveProperty('show');
|
||||
expect(twitterClient).toHaveProperty('create');
|
||||
expect(twitterClient).toHaveProperty('update');
|
||||
expect(twitterClient).toHaveProperty('delete');
|
||||
expect(twitterClient).toHaveProperty('generateAuthorization');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
import webChannelClient from '../../channel/webChannel';
|
||||
import ApiClient from '../../ApiClient';
|
||||
|
||||
describe('#webChannelClient', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(webChannelClient).toBeInstanceOf(ApiClient);
|
||||
expect(webChannelClient).toHaveProperty('get');
|
||||
expect(webChannelClient).toHaveProperty('show');
|
||||
expect(webChannelClient).toHaveProperty('create');
|
||||
expect(webChannelClient).toHaveProperty('update');
|
||||
expect(webChannelClient).toHaveProperty('delete');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,142 @@
|
||||
import companyAPI, {
|
||||
buildCompanyParams,
|
||||
buildSearchParams,
|
||||
} from '../companies';
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
describe('#CompanyAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(companyAPI).toBeInstanceOf(ApiClient);
|
||||
expect(companyAPI).toHaveProperty('get');
|
||||
expect(companyAPI).toHaveProperty('show');
|
||||
expect(companyAPI).toHaveProperty('create');
|
||||
expect(companyAPI).toHaveProperty('update');
|
||||
expect(companyAPI).toHaveProperty('delete');
|
||||
expect(companyAPI).toHaveProperty('search');
|
||||
});
|
||||
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#get with default params', () => {
|
||||
companyAPI.get({});
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/companies?page=1&sort=name'
|
||||
);
|
||||
});
|
||||
|
||||
it('#get with page and sort params', () => {
|
||||
companyAPI.get({ page: 2, sort: 'domain' });
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/companies?page=2&sort=domain'
|
||||
);
|
||||
});
|
||||
|
||||
it('#get with descending sort', () => {
|
||||
companyAPI.get({ page: 1, sort: '-created_at' });
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/companies?page=1&sort=-created_at'
|
||||
);
|
||||
});
|
||||
|
||||
it('#search with query', () => {
|
||||
companyAPI.search('acme', 1, 'name');
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/companies/search?q=acme&page=1&sort=name'
|
||||
);
|
||||
});
|
||||
|
||||
it('#search with special characters in query', () => {
|
||||
companyAPI.search('acme & co', 2, 'domain');
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/companies/search?q=acme%20%26%20co&page=2&sort=domain'
|
||||
);
|
||||
});
|
||||
|
||||
it('#search with descending sort', () => {
|
||||
companyAPI.search('test', 1, '-created_at');
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/companies/search?q=test&page=1&sort=-created_at'
|
||||
);
|
||||
});
|
||||
|
||||
it('#search with empty query', () => {
|
||||
companyAPI.search('', 1, 'name');
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/companies/search?q=&page=1&sort=name'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#buildCompanyParams', () => {
|
||||
it('returns correct string with page only', () => {
|
||||
expect(buildCompanyParams(1)).toBe('page=1');
|
||||
});
|
||||
|
||||
it('returns correct string with page and sort', () => {
|
||||
expect(buildCompanyParams(1, 'name')).toBe('page=1&sort=name');
|
||||
});
|
||||
|
||||
it('returns correct string with different page', () => {
|
||||
expect(buildCompanyParams(3, 'domain')).toBe('page=3&sort=domain');
|
||||
});
|
||||
|
||||
it('returns correct string with descending sort', () => {
|
||||
expect(buildCompanyParams(1, '-created_at')).toBe(
|
||||
'page=1&sort=-created_at'
|
||||
);
|
||||
});
|
||||
|
||||
it('returns correct string without sort parameter', () => {
|
||||
expect(buildCompanyParams(2, '')).toBe('page=2');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#buildSearchParams', () => {
|
||||
it('returns correct string with all parameters', () => {
|
||||
expect(buildSearchParams('acme', 1, 'name')).toBe(
|
||||
'q=acme&page=1&sort=name'
|
||||
);
|
||||
});
|
||||
|
||||
it('returns correct string with special characters', () => {
|
||||
expect(buildSearchParams('acme & co', 2, 'domain')).toBe(
|
||||
'q=acme%20%26%20co&page=2&sort=domain'
|
||||
);
|
||||
});
|
||||
|
||||
it('returns correct string with empty query', () => {
|
||||
expect(buildSearchParams('', 1, 'name')).toBe('q=&page=1&sort=name');
|
||||
});
|
||||
|
||||
it('returns correct string without sort parameter', () => {
|
||||
expect(buildSearchParams('test', 1, '')).toBe('q=test&page=1');
|
||||
});
|
||||
|
||||
it('returns correct string with descending sort', () => {
|
||||
expect(buildSearchParams('company', 3, '-created_at')).toBe(
|
||||
'q=company&page=3&sort=-created_at'
|
||||
);
|
||||
});
|
||||
|
||||
it('encodes special characters correctly', () => {
|
||||
expect(buildSearchParams('test@example.com', 1, 'name')).toBe(
|
||||
'q=test%40example.com&page=1&sort=name'
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,138 @@
|
||||
import contactAPI, { buildContactParams } from '../contacts';
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
describe('#ContactsAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(contactAPI).toBeInstanceOf(ApiClient);
|
||||
expect(contactAPI).toHaveProperty('get');
|
||||
expect(contactAPI).toHaveProperty('show');
|
||||
expect(contactAPI).toHaveProperty('create');
|
||||
expect(contactAPI).toHaveProperty('update');
|
||||
expect(contactAPI).toHaveProperty('delete');
|
||||
expect(contactAPI).toHaveProperty('getConversations');
|
||||
expect(contactAPI).toHaveProperty('filter');
|
||||
expect(contactAPI).toHaveProperty('destroyAvatar');
|
||||
});
|
||||
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#get', () => {
|
||||
contactAPI.get(1, 'name', 'customer-support');
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/contacts?include_contact_inboxes=false&page=1&sort=name&labels[]=customer-support'
|
||||
);
|
||||
});
|
||||
|
||||
it('#getConversations', () => {
|
||||
contactAPI.getConversations(1);
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/contacts/1/conversations'
|
||||
);
|
||||
});
|
||||
|
||||
it('#getContactableInboxes', () => {
|
||||
contactAPI.getContactableInboxes(1);
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/contacts/1/contactable_inboxes'
|
||||
);
|
||||
});
|
||||
|
||||
it('#getContactLabels', () => {
|
||||
contactAPI.getContactLabels(1);
|
||||
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/contacts/1/labels');
|
||||
});
|
||||
|
||||
it('#updateContactLabels', () => {
|
||||
const labels = ['support-query'];
|
||||
contactAPI.updateContactLabels(1, labels);
|
||||
expect(axiosMock.post).toHaveBeenCalledWith('/api/v1/contacts/1/labels', {
|
||||
labels,
|
||||
});
|
||||
});
|
||||
|
||||
it('#search', () => {
|
||||
contactAPI.search('leads', 1, 'date', 'customer-support');
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/contacts/search?include_contact_inboxes=false&page=1&sort=date&q=leads&labels[]=customer-support'
|
||||
);
|
||||
});
|
||||
|
||||
it('#destroyCustomAttributes', () => {
|
||||
contactAPI.destroyCustomAttributes(1, ['cloudCustomer']);
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/contacts/1/destroy_custom_attributes',
|
||||
{
|
||||
custom_attributes: ['cloudCustomer'],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('#importContacts', () => {
|
||||
const file = 'file';
|
||||
contactAPI.importContacts(file);
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/contacts/import',
|
||||
expect.any(FormData),
|
||||
{
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('#filter', () => {
|
||||
const queryPayload = {
|
||||
payload: [
|
||||
{
|
||||
attribute_key: 'email',
|
||||
filter_operator: 'contains',
|
||||
values: ['fayaz'],
|
||||
query_operator: null,
|
||||
},
|
||||
],
|
||||
};
|
||||
contactAPI.filter(1, 'name', queryPayload);
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/contacts/filter?include_contact_inboxes=false&page=1&sort=name',
|
||||
queryPayload
|
||||
);
|
||||
});
|
||||
|
||||
it('#destroyAvatar', () => {
|
||||
contactAPI.destroyAvatar(1);
|
||||
expect(axiosMock.delete).toHaveBeenCalledWith(
|
||||
'/api/v1/contacts/1/avatar'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#buildContactParams', () => {
|
||||
it('returns correct string', () => {
|
||||
expect(buildContactParams(1, 'name', '', '')).toBe(
|
||||
'include_contact_inboxes=false&page=1&sort=name'
|
||||
);
|
||||
expect(buildContactParams(1, 'name', 'customer-support', '')).toBe(
|
||||
'include_contact_inboxes=false&page=1&sort=name&labels[]=customer-support'
|
||||
);
|
||||
expect(
|
||||
buildContactParams(1, 'name', 'customer-support', 'message-content')
|
||||
).toBe(
|
||||
'include_contact_inboxes=false&page=1&sort=name&q=message-content&labels[]=customer-support'
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
import conversationsAPI from '../conversations';
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
describe('#ConversationApi', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(conversationsAPI).toBeInstanceOf(ApiClient);
|
||||
expect(conversationsAPI).toHaveProperty('get');
|
||||
expect(conversationsAPI).toHaveProperty('show');
|
||||
expect(conversationsAPI).toHaveProperty('create');
|
||||
expect(conversationsAPI).toHaveProperty('update');
|
||||
expect(conversationsAPI).toHaveProperty('delete');
|
||||
expect(conversationsAPI).toHaveProperty('getLabels');
|
||||
expect(conversationsAPI).toHaveProperty('updateLabels');
|
||||
});
|
||||
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#getLabels', () => {
|
||||
conversationsAPI.getLabels(1);
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/conversations/1/labels'
|
||||
);
|
||||
});
|
||||
|
||||
it('#updateLabels', () => {
|
||||
const labels = ['support-query'];
|
||||
conversationsAPI.updateLabels(1, labels);
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/conversations/1/labels',
|
||||
{
|
||||
labels,
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
import csatReportsAPI from '../csatReports';
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
describe('#Reports API', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(csatReportsAPI).toBeInstanceOf(ApiClient);
|
||||
expect(csatReportsAPI.apiVersion).toBe('/api/v1');
|
||||
expect(csatReportsAPI).toHaveProperty('get');
|
||||
expect(csatReportsAPI).toHaveProperty('getMetrics');
|
||||
});
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#get', () => {
|
||||
csatReportsAPI.get({ page: 1, from: 1622485800, to: 1623695400 });
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/csat_survey_responses',
|
||||
{
|
||||
params: {
|
||||
page: 1,
|
||||
since: 1622485800,
|
||||
until: 1623695400,
|
||||
sort: '-created_at',
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
it('#getMetrics', () => {
|
||||
csatReportsAPI.getMetrics({ from: 1622485800, to: 1623695400 });
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/csat_survey_responses/metrics',
|
||||
{
|
||||
params: { since: 1622485800, until: 1623695400 },
|
||||
}
|
||||
);
|
||||
});
|
||||
it('#download', () => {
|
||||
csatReportsAPI.download({
|
||||
from: 1622485800,
|
||||
to: 1623695400,
|
||||
user_ids: 1,
|
||||
});
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/csat_survey_responses/download',
|
||||
{
|
||||
params: {
|
||||
since: 1622485800,
|
||||
until: 1623695400,
|
||||
user_ids: 1,
|
||||
sort: '-created_at',
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
import dashboardAppsAPI from '../dashboardApps';
|
||||
import ApiClient from '../ApiClient';
|
||||
|
||||
describe('#dashboardAppsAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(dashboardAppsAPI).toBeInstanceOf(ApiClient);
|
||||
expect(dashboardAppsAPI).toHaveProperty('get');
|
||||
expect(dashboardAppsAPI).toHaveProperty('show');
|
||||
expect(dashboardAppsAPI).toHaveProperty('create');
|
||||
expect(dashboardAppsAPI).toHaveProperty('update');
|
||||
expect(dashboardAppsAPI).toHaveProperty('delete');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
import endPoints from '../endPoints';
|
||||
|
||||
describe('#endPoints', () => {
|
||||
it('it should return register url details if register page passed ', () => {
|
||||
expect(endPoints('register')).toEqual({ url: 'api/v1/accounts.json' });
|
||||
});
|
||||
it('it should inbox url details if getInbox page passed', () => {
|
||||
expect(endPoints('getInbox')).toEqual({
|
||||
url: 'api/v1/conversations.json',
|
||||
params: { inbox_id: null },
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
import categoriesAPI from '../../helpCenter/categories';
|
||||
import ApiClient from '../../ApiClient';
|
||||
|
||||
describe('#BulkActionsAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(categoriesAPI).toBeInstanceOf(ApiClient);
|
||||
expect(categoriesAPI).toHaveProperty('get');
|
||||
expect(categoriesAPI).toHaveProperty('create');
|
||||
expect(categoriesAPI).toHaveProperty('update');
|
||||
expect(categoriesAPI).toHaveProperty('delete');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,232 @@
|
||||
import conversationAPI from '../../inbox/conversation';
|
||||
import ApiClient from '../../ApiClient';
|
||||
|
||||
describe('#ConversationAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(conversationAPI).toBeInstanceOf(ApiClient);
|
||||
expect(conversationAPI).toHaveProperty('get');
|
||||
expect(conversationAPI).toHaveProperty('show');
|
||||
expect(conversationAPI).toHaveProperty('create');
|
||||
expect(conversationAPI).toHaveProperty('update');
|
||||
expect(conversationAPI).toHaveProperty('delete');
|
||||
expect(conversationAPI).toHaveProperty('toggleStatus');
|
||||
expect(conversationAPI).toHaveProperty('assignAgent');
|
||||
expect(conversationAPI).toHaveProperty('assignTeam');
|
||||
expect(conversationAPI).toHaveProperty('markMessageRead');
|
||||
expect(conversationAPI).toHaveProperty('toggleTyping');
|
||||
expect(conversationAPI).toHaveProperty('mute');
|
||||
expect(conversationAPI).toHaveProperty('unmute');
|
||||
expect(conversationAPI).toHaveProperty('meta');
|
||||
expect(conversationAPI).toHaveProperty('sendEmailTranscript');
|
||||
expect(conversationAPI).toHaveProperty('filter');
|
||||
});
|
||||
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#get conversations', () => {
|
||||
conversationAPI.get({
|
||||
inboxId: 1,
|
||||
status: 'open',
|
||||
assigneeType: 'me',
|
||||
page: 1,
|
||||
labels: [],
|
||||
teamId: 1,
|
||||
updatedWithin: 20,
|
||||
});
|
||||
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/conversations', {
|
||||
params: {
|
||||
inbox_id: 1,
|
||||
team_id: 1,
|
||||
status: 'open',
|
||||
assignee_type: 'me',
|
||||
page: 1,
|
||||
labels: [],
|
||||
updated_within: 20,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('#search', () => {
|
||||
conversationAPI.search({
|
||||
q: 'leads',
|
||||
page: 1,
|
||||
});
|
||||
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/conversations/search',
|
||||
{
|
||||
params: {
|
||||
q: 'leads',
|
||||
page: 1,
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('#toggleStatus', () => {
|
||||
conversationAPI.toggleStatus({ conversationId: 12, status: 'online' });
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
`/api/v1/conversations/12/toggle_status`,
|
||||
{
|
||||
status: 'online',
|
||||
snoozed_until: null,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('#assignAgent', () => {
|
||||
conversationAPI.assignAgent({ conversationId: 12, agentId: 34 });
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
`/api/v1/conversations/12/assignments`,
|
||||
{
|
||||
assignee_id: 34,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('#assignTeam', () => {
|
||||
conversationAPI.assignTeam({ conversationId: 12, teamId: 1 });
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
`/api/v1/conversations/12/assignments`,
|
||||
{
|
||||
team_id: 1,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('#markMessageRead', () => {
|
||||
conversationAPI.markMessageRead({ id: 12 });
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
`/api/v1/conversations/12/update_last_seen`
|
||||
);
|
||||
});
|
||||
|
||||
it('#toggleTyping', () => {
|
||||
conversationAPI.toggleTyping({
|
||||
conversationId: 12,
|
||||
status: 'typing_on',
|
||||
});
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
`/api/v1/conversations/12/toggle_typing_status`,
|
||||
{
|
||||
typing_status: 'typing_on',
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('#mute', () => {
|
||||
conversationAPI.mute(45);
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/conversations/45/mute'
|
||||
);
|
||||
});
|
||||
|
||||
it('#unmute', () => {
|
||||
conversationAPI.unmute(45);
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/conversations/45/unmute'
|
||||
);
|
||||
});
|
||||
|
||||
it('#meta', () => {
|
||||
conversationAPI.meta({
|
||||
inboxId: 1,
|
||||
status: 'open',
|
||||
assigneeType: 'me',
|
||||
labels: [],
|
||||
teamId: 1,
|
||||
});
|
||||
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/conversations/meta', {
|
||||
params: {
|
||||
inbox_id: 1,
|
||||
team_id: 1,
|
||||
status: 'open',
|
||||
assignee_type: 'me',
|
||||
labels: [],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('#sendEmailTranscript', () => {
|
||||
conversationAPI.sendEmailTranscript({
|
||||
conversationId: 45,
|
||||
email: 'john@acme.inc',
|
||||
});
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/conversations/45/transcript',
|
||||
{
|
||||
email: 'john@acme.inc',
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('#updateCustomAttributes', () => {
|
||||
conversationAPI.updateCustomAttributes({
|
||||
conversationId: 45,
|
||||
customAttributes: { order_d: '1001' },
|
||||
});
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/conversations/45/custom_attributes',
|
||||
{
|
||||
custom_attributes: { order_d: '1001' },
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('#filter', () => {
|
||||
const payload = {
|
||||
page: 1,
|
||||
queryData: {
|
||||
payload: [
|
||||
{
|
||||
attribute_key: 'status',
|
||||
filter_operator: 'equal_to',
|
||||
values: ['pending', 'resolved'],
|
||||
query_operator: 'and',
|
||||
},
|
||||
{
|
||||
attribute_key: 'assignee',
|
||||
filter_operator: 'equal_to',
|
||||
values: [3],
|
||||
query_operator: 'and',
|
||||
},
|
||||
{
|
||||
attribute_key: 'id',
|
||||
filter_operator: 'equal_to',
|
||||
values: ['This is a test'],
|
||||
query_operator: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
conversationAPI.filter(payload);
|
||||
expect(axiosMock.post).toHaveBeenCalledWith(
|
||||
'/api/v1/conversations/filter',
|
||||
payload.queryData,
|
||||
{ params: { page: payload.page } }
|
||||
);
|
||||
});
|
||||
|
||||
it('#getAllAttachments', () => {
|
||||
conversationAPI.getAllAttachments(1);
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/conversations/1/attachments'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,87 @@
|
||||
import messageAPI, { buildCreatePayload } from '../../inbox/message';
|
||||
import ApiClient from '../../ApiClient';
|
||||
|
||||
describe('#ConversationAPI', () => {
|
||||
it('creates correct instance', () => {
|
||||
expect(messageAPI).toBeInstanceOf(ApiClient);
|
||||
expect(messageAPI).toHaveProperty('get');
|
||||
expect(messageAPI).toHaveProperty('show');
|
||||
expect(messageAPI).toHaveProperty('create');
|
||||
expect(messageAPI).toHaveProperty('update');
|
||||
expect(messageAPI).toHaveProperty('delete');
|
||||
expect(messageAPI).toHaveProperty('getPreviousMessages');
|
||||
});
|
||||
|
||||
describe('API calls', () => {
|
||||
const originalAxios = window.axios;
|
||||
const axiosMock = {
|
||||
post: vi.fn(() => Promise.resolve()),
|
||||
get: vi.fn(() => Promise.resolve()),
|
||||
patch: vi.fn(() => Promise.resolve()),
|
||||
delete: vi.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.axios = axiosMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#getPreviousMessages', () => {
|
||||
messageAPI.getPreviousMessages({
|
||||
conversationId: 12,
|
||||
before: 4573,
|
||||
});
|
||||
expect(axiosMock.get).toHaveBeenCalledWith(
|
||||
`/api/v1/conversations/12/messages`,
|
||||
{
|
||||
params: {
|
||||
before: 4573,
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('#buildCreatePayload', () => {
|
||||
it('builds form payload if file is available', () => {
|
||||
const formPayload = buildCreatePayload({
|
||||
message: 'test content',
|
||||
echoId: 12,
|
||||
isPrivate: true,
|
||||
contentAttributes: { in_reply_to: 12 },
|
||||
files: [new Blob(['test-content'], { type: 'application/pdf' })],
|
||||
});
|
||||
expect(formPayload).toBeInstanceOf(FormData);
|
||||
expect(formPayload.get('content')).toEqual('test content');
|
||||
expect(formPayload.get('echo_id')).toEqual('12');
|
||||
expect(formPayload.get('private')).toEqual('true');
|
||||
expect(formPayload.get('cc_emails')).toEqual('');
|
||||
expect(formPayload.get('bcc_emails')).toEqual('');
|
||||
expect(formPayload.get('content_attributes')).toEqual(
|
||||
'{"in_reply_to":12}'
|
||||
);
|
||||
});
|
||||
|
||||
it('builds object payload if file is not available', () => {
|
||||
expect(
|
||||
buildCreatePayload({
|
||||
message: 'test content',
|
||||
isPrivate: false,
|
||||
echoId: 12,
|
||||
contentAttributes: { in_reply_to: 12 },
|
||||
})
|
||||
).toEqual({
|
||||
content: 'test content',
|
||||
private: false,
|
||||
echo_id: 12,
|
||||
content_attributes: { in_reply_to: 12 },
|
||||
cc_emails: '',
|
||||
bcc_emails: '',
|
||||
to_emails: '',
|
||||
template_params: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user