feat: Add store for conversation watchers (#5808)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
parent
6ff0c93659
commit
0d9ed0674b
8 changed files with 240 additions and 0 deletions
|
@ -105,6 +105,16 @@ class ConversationApi extends ApiClient {
|
|||
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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new ConversationApi();
|
||||
|
|
|
@ -23,6 +23,7 @@ import conversations from './modules/conversations';
|
|||
import conversationSearch from './modules/conversationSearch';
|
||||
import conversationStats from './modules/conversationStats';
|
||||
import conversationTypingStatus from './modules/conversationTypingStatus';
|
||||
import conversationWatchers from './modules/conversationWatchers';
|
||||
import csat from './modules/csat';
|
||||
import customViews from './modules/customViews';
|
||||
import dashboardApps from './modules/dashboardApps';
|
||||
|
@ -66,6 +67,7 @@ export default new Vuex.Store({
|
|||
conversationSearch,
|
||||
conversationStats,
|
||||
conversationTypingStatus,
|
||||
conversationWatchers,
|
||||
csat,
|
||||
customViews,
|
||||
dashboardApps,
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
import Vue from 'vue';
|
||||
import types from '../mutation-types';
|
||||
import { throwErrorMessage } from 'dashboard/store/utils/api';
|
||||
|
||||
import ConversationInboxApi from '../../api/inbox/conversation';
|
||||
|
||||
const state = {
|
||||
records: {},
|
||||
uiFlags: {
|
||||
isFetching: false,
|
||||
isUpdating: false,
|
||||
},
|
||||
};
|
||||
|
||||
export const getters = {
|
||||
getUIFlags($state) {
|
||||
return $state.uiFlags;
|
||||
},
|
||||
getByConversationId: _state => conversationId => {
|
||||
return _state.records[conversationId];
|
||||
},
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
show: async ({ commit }, { conversationId }) => {
|
||||
commit(types.SET_CONVERSATION_WATCHERS_UI_FLAG, {
|
||||
isFetching: true,
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await ConversationInboxApi.fetchParticipants(
|
||||
conversationId
|
||||
);
|
||||
commit(types.SET_CONVERSATION_WATCHERS, {
|
||||
conversationId,
|
||||
data: response.data,
|
||||
});
|
||||
} catch (error) {
|
||||
throwErrorMessage(error);
|
||||
} finally {
|
||||
commit(types.SET_CONVERSATION_WATCHERS_UI_FLAG, {
|
||||
isFetching: false,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
update: async ({ commit }, { conversationId, userIds }) => {
|
||||
commit(types.SET_CONVERSATION_WATCHERS_UI_FLAG, {
|
||||
isUpdating: true,
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await ConversationInboxApi.updateParticipants({
|
||||
conversationId,
|
||||
userIds,
|
||||
});
|
||||
commit(types.SET_CONVERSATION_WATCHERS, {
|
||||
conversationId,
|
||||
data: response.data,
|
||||
});
|
||||
} catch (error) {
|
||||
throwErrorMessage(error);
|
||||
} finally {
|
||||
commit(types.SET_CONVERSATION_WATCHERS_UI_FLAG, {
|
||||
isUpdating: false,
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export const mutations = {
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG]($state, data) {
|
||||
$state.uiFlags = {
|
||||
...$state.uiFlags,
|
||||
...data,
|
||||
};
|
||||
},
|
||||
|
||||
[types.SET_CONVERSATION_WATCHERS]($state, { data, conversationId }) {
|
||||
Vue.set($state.records, conversationId, data);
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations,
|
||||
};
|
|
@ -0,0 +1,62 @@
|
|||
import axios from 'axios';
|
||||
import { actions } from '../../conversationWatchers';
|
||||
import types from '../../../mutation-types';
|
||||
|
||||
const commit = jest.fn();
|
||||
global.axios = axios;
|
||||
jest.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: { id: 1 } });
|
||||
await actions.show({ commit }, { conversationId: 1 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isFetching: true }],
|
||||
[
|
||||
types.SET_CONVERSATION_WATCHERS,
|
||||
{ conversationId: 1, data: { id: 1 } },
|
||||
],
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.show({ commit }, { conversationId: 1 })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.patch.mockResolvedValue({ data: [{ id: 2 }] });
|
||||
await actions.update(
|
||||
{ commit },
|
||||
{ conversationId: 2, userIds: [{ id: 2 }] }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isUpdating: true }],
|
||||
[
|
||||
types.SET_CONVERSATION_WATCHERS,
|
||||
{ conversationId: 2, data: [{ id: 2 }] },
|
||||
],
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.update({ commit }, { conversationId: 1, content: 'hi' })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isUpdating: true }],
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,14 @@
|
|||
export const data = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Uno',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Dos',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Tres',
|
||||
},
|
||||
];
|
|
@ -0,0 +1,22 @@
|
|||
import { getters } from '../../conversationWatchers';
|
||||
import watchersData from './fixtures';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getByConversationId', () => {
|
||||
const state = { records: { 1: watchersData } };
|
||||
expect(getters.getByConversationId(state)(1)).toEqual(watchersData);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: false,
|
||||
isUpdating: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: false,
|
||||
isUpdating: false,
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,37 @@
|
|||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../conversationWatchers';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CONVERSATION_WATCHERS', () => {
|
||||
it('sets an individual record', () => {
|
||||
let state = {
|
||||
records: {},
|
||||
};
|
||||
|
||||
mutations[types.SET_CONVERSATION_WATCHERS](state, {
|
||||
data: [],
|
||||
conversationId: 1,
|
||||
});
|
||||
expect(state.records).toEqual({ 1: [] });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CONVERSATION_WATCHERS_UI_FLAG', () => {
|
||||
it('set ui flags', () => {
|
||||
let state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
isUpdating: false,
|
||||
},
|
||||
};
|
||||
|
||||
mutations[types.SET_CONVERSATION_WATCHERS_UI_FLAG](state, {
|
||||
isFetching: false,
|
||||
});
|
||||
expect(state.uiFlags).toEqual({
|
||||
isFetching: false,
|
||||
isUpdating: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -258,4 +258,7 @@ export default {
|
|||
ADD_MACRO: 'ADD_MACRO',
|
||||
EDIT_MACRO: 'EDIT_MACRO',
|
||||
DELETE_MACRO: 'DELETE_MACRO',
|
||||
|
||||
SET_CONVERSATION_WATCHERS_UI_FLAG: 'SET_CONVERSATION_WATCHERS_UI_FLAG',
|
||||
SET_CONVERSATION_WATCHERS: 'SET_CONVERSATION_WATCHERS',
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue