diff --git a/app/javascript/dashboard/api/channel/fbChannel.js b/app/javascript/dashboard/api/channel/fbChannel.js index e53885b4a..2e86cb927 100644 --- a/app/javascript/dashboard/api/channel/fbChannel.js +++ b/app/javascript/dashboard/api/channel/fbChannel.js @@ -6,20 +6,6 @@ class FBChannel extends ApiClient { super('facebook_indicators', { accountScoped: true }); } - markSeen({ inboxId, contactId }) { - return axios.post(`${this.url}/mark_seen`, { - inbox_id: inboxId, - contact_id: contactId, - }); - } - - toggleTyping({ status, inboxId, contactId }) { - return axios.post(`${this.url}/typing_${status}`, { - inbox_id: inboxId, - contact_id: contactId, - }); - } - create(params) { return axios.post( `${this.url.replace(this.resource, '')}callbacks/register_facebook_page`, diff --git a/app/javascript/dashboard/api/specs/channel/fbChannel.spec.js b/app/javascript/dashboard/api/specs/channel/fbChannel.spec.js index 63ae1492d..03f1cb649 100644 --- a/app/javascript/dashboard/api/specs/channel/fbChannel.spec.js +++ b/app/javascript/dashboard/api/specs/channel/fbChannel.spec.js @@ -9,7 +9,5 @@ describe('#FBChannel', () => { expect(fbChannel).toHaveProperty('create'); expect(fbChannel).toHaveProperty('update'); expect(fbChannel).toHaveProperty('delete'); - expect(fbChannel).toHaveProperty('markSeen'); - expect(fbChannel).toHaveProperty('toggleTyping'); }); }); diff --git a/app/javascript/dashboard/api/specs/contacts.spec.js b/app/javascript/dashboard/api/specs/contacts.spec.js index 1021c0409..2cc89ccc8 100644 --- a/app/javascript/dashboard/api/specs/contacts.spec.js +++ b/app/javascript/dashboard/api/specs/contacts.spec.js @@ -1,14 +1,14 @@ -import agents from '../contacts'; +import contacts from '../contacts'; import ApiClient from '../ApiClient'; describe('#ContactsAPI', () => { 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'); - expect(agents).toHaveProperty('getConversations'); + expect(contacts).toBeInstanceOf(ApiClient); + expect(contacts).toHaveProperty('get'); + expect(contacts).toHaveProperty('show'); + expect(contacts).toHaveProperty('create'); + expect(contacts).toHaveProperty('update'); + expect(contacts).toHaveProperty('delete'); + expect(contacts).toHaveProperty('getConversations'); }); }); diff --git a/app/javascript/dashboard/components/ChatList.vue b/app/javascript/dashboard/components/ChatList.vue index a4cec45e3..9adb05dcc 100644 --- a/app/javascript/dashboard/components/ChatList.vue +++ b/app/javascript/dashboard/components/ChatList.vue @@ -88,14 +88,17 @@ export default { chatListLoading: 'getChatListLoadingStatus', currentUserID: 'getCurrentUserID', activeInbox: 'getSelectedInbox', - convStats: 'getConvTabStats', + conversationStats: 'conversationStats/getStats', }), assigneeTabItems() { - return this.$t('CHAT_LIST.ASSIGNEE_TYPE_TABS').map(item => ({ - key: item.KEY, - name: item.NAME, - count: this.convStats[item.COUNT_KEY] || 0, - })); + return this.$t('CHAT_LIST.ASSIGNEE_TYPE_TABS').map(item => { + const count = this.conversationStats[item.COUNT_KEY] || 0; + return { + key: item.KEY, + name: item.NAME, + count, + }; + }); }, inbox() { return this.$store.getters['inboxes/getInbox'](this.activeInbox); @@ -130,7 +133,7 @@ export default { this.$store.dispatch('agents/get'); bus.$on('fetch_conversation_stats', () => { - this.$store.dispatch('getConversationStats', this.conversationFilters); + this.$store.dispatch('conversationStats/get', this.conversationFilters); }); }, methods: { diff --git a/app/javascript/dashboard/components/widgets/ChatTypeTabs.vue b/app/javascript/dashboard/components/widgets/ChatTypeTabs.vue index 0ed5e542b..e57f63fbf 100644 --- a/app/javascript/dashboard/components/widgets/ChatTypeTabs.vue +++ b/app/javascript/dashboard/components/widgets/ChatTypeTabs.vue @@ -22,11 +22,6 @@ export default { default: wootConstants.ASSIGNEE_TYPE.ME, }, }, - data() { - return { - tabsIndex: wootConstants.ASSIGNEE_TYPE.ME, - }; - }, computed: { activeTabIndex() { return this.items.findIndex(item => item.key === this.activeTab); diff --git a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue index 8a2a836ba..df2e03398 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue @@ -269,7 +269,7 @@ export default { toggleTyping(status) { if (this.channelType === 'Channel::WebWidget' && !this.isPrivate) { const conversationId = this.currentChat.id; - this.$store.dispatch('toggleTyping', { + this.$store.dispatch('conversationTypingStatus/toggleTyping', { status, conversationId, }); diff --git a/app/javascript/dashboard/store/index.js b/app/javascript/dashboard/store/index.js index 9df653765..be0328178 100755 --- a/app/javascript/dashboard/store/index.js +++ b/app/javascript/dashboard/store/index.js @@ -12,6 +12,7 @@ import conversationLabels from './modules/conversationLabels'; import conversationMetadata from './modules/conversationMetadata'; import conversationPage from './modules/conversationPage'; import conversations from './modules/conversations'; +import conversationStats from './modules/conversationStats'; import conversationTypingStatus from './modules/conversationTypingStatus'; import globalConfig from 'shared/store/globalConfig'; import inboxes from './modules/inboxes'; @@ -33,6 +34,7 @@ export default new Vuex.Store({ conversationLabels, conversationMetadata, conversationPage, + conversationStats, conversations, conversationTypingStatus, globalConfig, diff --git a/app/javascript/dashboard/store/modules/conversationStats.js b/app/javascript/dashboard/store/modules/conversationStats.js new file mode 100644 index 000000000..b7be14f28 --- /dev/null +++ b/app/javascript/dashboard/store/modules/conversationStats.js @@ -0,0 +1,53 @@ +import Vue from 'vue'; +import types from '../mutation-types'; +import ConversationApi from '../../api/inbox/conversation'; + +const state = { + mineCount: 0, + unAssignedCount: 0, + allCount: 0, +}; + +export const getters = { + getStats: $state => $state, +}; + +export const actions = { + get: async ({ commit }, params) => { + try { + const response = await ConversationApi.meta(params); + const { + data: { meta }, + } = response; + commit(types.SET_CONV_TAB_META, meta); + } catch (error) { + // Ignore error + } + }, + set({ commit }, meta) { + commit(types.SET_CONV_TAB_META, meta); + }, +}; + +export const mutations = { + [types.SET_CONV_TAB_META]( + $state, + { + mine_count: mineCount, + unassigned_count: unAssignedCount, + all_count: allCount, + } = {} + ) { + Vue.set($state, 'mineCount', mineCount); + Vue.set($state, 'allCount', allCount); + Vue.set($state, 'unAssignedCount', unAssignedCount); + }, +}; + +export default { + namespaced: true, + state, + getters, + actions, + mutations, +}; diff --git a/app/javascript/dashboard/store/modules/conversationTypingStatus.js b/app/javascript/dashboard/store/modules/conversationTypingStatus.js index 4ad9f3cb4..27badb668 100644 --- a/app/javascript/dashboard/store/modules/conversationTypingStatus.js +++ b/app/javascript/dashboard/store/modules/conversationTypingStatus.js @@ -1,6 +1,6 @@ import Vue from 'vue'; import * as types from '../mutation-types'; - +import ConversationAPI from '../../api/inbox/conversation'; const state = { records: {}, }; @@ -12,6 +12,13 @@ export const getters = { }; export const actions = { + toggleTyping: async (_, { status, conversationId }) => { + try { + await ConversationAPI.toggleTyping({ status, conversationId }); + } catch (error) { + // Handle error + } + }, create: ({ commit }, { conversationId, user }) => { commit(types.default.ADD_USER_TYPING_TO_CONVERSATION, { conversationId, diff --git a/app/javascript/dashboard/store/modules/conversations/actions.js b/app/javascript/dashboard/store/modules/conversations/actions.js index d1e742728..72b46e850 100644 --- a/app/javascript/dashboard/store/modules/conversations/actions.js +++ b/app/javascript/dashboard/store/modules/conversations/actions.js @@ -2,7 +2,6 @@ import Vue from 'vue'; import * as types from '../../mutation-types'; import ConversationApi from '../../../api/inbox/conversation'; import MessageApi from '../../../api/inbox/message'; -import FBChannel from '../../../api/channel/fbChannel'; // actions const actions = { @@ -26,7 +25,7 @@ const actions = { const { data } = response.data; const { payload: chatList, meta: metaData } = data; commit(types.default.SET_ALL_CONVERSATION, chatList); - commit(types.default.SET_CONV_TAB_META, metaData); + dispatch('conversationStats/set', metaData); commit(types.default.CLEAR_LIST_LOADING_STATUS); commit( `contacts/${types.default.SET_CONTACTS}`, @@ -171,24 +170,6 @@ const actions = { commit(types.default.UPDATE_CONVERSATION, conversation); }, - toggleTyping: async ({ commit }, { status, conversationId }) => { - try { - commit(types.default.SET_AGENT_TYPING, { status }); - await ConversationApi.toggleTyping({ status, conversationId }); - } catch (error) { - // Handle error - } - }, - - markSeen: async ({ commit }, data) => { - try { - await FBChannel.markSeen(data); - commit(types.default.MARK_SEEN); - } catch (error) { - // Handle error - } - }, - markMessagesRead: async ({ commit }, data) => { setTimeout(() => { commit(types.default.MARK_MESSAGE_READ, data); @@ -236,15 +217,6 @@ const actions = { // } }, - - getConversationStats: async ({ commit }, params) => { - try { - const response = await ConversationApi.meta(params); - commit(types.default.SET_CONV_TAB_META, response.data.meta); - } catch (error) { - // Ignore error - } - }, }; export default actions; diff --git a/app/javascript/dashboard/store/modules/conversations/getters.js b/app/javascript/dashboard/store/modules/conversations/getters.js index 311342941..cfea74813 100644 --- a/app/javascript/dashboard/store/modules/conversations/getters.js +++ b/app/javascript/dashboard/store/modules/conversations/getters.js @@ -52,7 +52,6 @@ const getters = { }, getChatStatusFilter: ({ chatStatusFilter }) => chatStatusFilter, getSelectedInbox: ({ currentInbox }) => currentInbox, - getConvTabStats: ({ convTabStats }) => convTabStats, getNextChatConversation: _state => { const { selectedChat } = _state; const conversations = getters.getAllStatusChats(_state); diff --git a/app/javascript/dashboard/store/modules/conversations/index.js b/app/javascript/dashboard/store/modules/conversations/index.js index 71c226c40..5896405ec 100644 --- a/app/javascript/dashboard/store/modules/conversations/index.js +++ b/app/javascript/dashboard/store/modules/conversations/index.js @@ -12,16 +12,10 @@ const initialSelectedChat = { status: null, muted: false, seen: false, - agentTyping: 'off', dataFetched: false, }; const state = { allConversations: [], - convTabStats: { - mineCount: 0, - unAssignedCount: 0, - allCount: 0, - }, selectedChat: { ...initialSelectedChat }, listLoadingStatus: true, chatStatusFilter: wootConstants.STATUS_TYPE.OPEN, @@ -57,7 +51,6 @@ const mutations = { }, [types.default.CLEAR_CURRENT_CHAT_WINDOW](_state) { _state.selectedChat.id = null; - _state.selectedChat.agentTyping = 'off'; }, [types.default.SET_PREVIOUS_CONVERSATIONS](_state, { id, data }) { @@ -67,19 +60,6 @@ const mutations = { } }, - [types.default.SET_CONV_TAB_META]( - _state, - { - mine_count: mineCount, - unassigned_count: unAssignedCount, - all_count: allCount, - } = {} - ) { - Vue.set(_state.convTabStats, 'mineCount', mineCount); - Vue.set(_state.convTabStats, 'allCount', allCount); - Vue.set(_state.convTabStats, 'unAssignedCount', unAssignedCount); - }, - [types.default.CURRENT_CHAT_WINDOW](_state, activeChat) { if (activeChat) { Object.assign(_state.selectedChat, activeChat); @@ -176,10 +156,6 @@ const mutations = { _state.selectedChat.seen = true; }, - [types.default.SET_AGENT_TYPING](_state, { status }) { - _state.selectedChat.agentTyping = status; - }, - [types.default.SET_LIST_LOADING_STATUS](_state) { _state.listLoadingStatus = true; }, diff --git a/app/javascript/dashboard/store/modules/conversations/specs/actions.spec.js b/app/javascript/dashboard/store/modules/specs/conversationStats/actions.spec.js similarity index 56% rename from app/javascript/dashboard/store/modules/conversations/specs/actions.spec.js rename to app/javascript/dashboard/store/modules/specs/conversationStats/actions.spec.js index 4693e0a62..e357204d2 100644 --- a/app/javascript/dashboard/store/modules/conversations/specs/actions.spec.js +++ b/app/javascript/dashboard/store/modules/specs/conversationStats/actions.spec.js @@ -1,5 +1,5 @@ import axios from 'axios'; -import actions from '../actions'; +import { actions } from '../../conversationStats'; import * as types from '../../../mutation-types'; const commit = jest.fn(); @@ -7,10 +7,10 @@ global.axios = axios; jest.mock('axios'); describe('#actions', () => { - describe('#getConversationStats', () => { - it('sends correct actions if API is success', async () => { + describe('#get', () => { + it('sends correct mutations if API is success', async () => { axios.get.mockResolvedValue({ data: { meta: { mine_count: 1 } } }); - await actions.getConversationStats( + await actions.get( { commit }, { inboxId: 1, assigneeTpe: 'me', status: 'open' } ); @@ -20,11 +20,26 @@ describe('#actions', () => { }); it('sends correct actions if API is error', async () => { axios.get.mockRejectedValue({ message: 'Incorrect header' }); - await actions.getConversationStats( + await actions.get( { commit }, { inboxId: 1, assigneeTpe: 'me', status: 'open' } ); expect(commit.mock.calls).toEqual([]); }); }); + + describe('#set', () => { + it('sends correct mutations', async () => { + actions.set( + { commit }, + { mine_count: 1, unassigned_count: 1, all_count: 2 } + ); + expect(commit.mock.calls).toEqual([ + [ + types.default.SET_CONV_TAB_META, + { mine_count: 1, unassigned_count: 1, all_count: 2 }, + ], + ]); + }); + }); }); diff --git a/app/javascript/dashboard/store/modules/specs/conversationStats/getters.spec.js b/app/javascript/dashboard/store/modules/specs/conversationStats/getters.spec.js new file mode 100644 index 000000000..38b7a88bc --- /dev/null +++ b/app/javascript/dashboard/store/modules/specs/conversationStats/getters.spec.js @@ -0,0 +1,16 @@ +import { getters } from '../../conversationStats'; + +describe('#getters', () => { + it('getCurrentPage', () => { + const state = { + mineCount: 1, + unAssignedCount: 1, + allCount: 2, + }; + expect(getters.getStats(state)).toEqual({ + mineCount: 1, + unAssignedCount: 1, + allCount: 2, + }); + }); +}); diff --git a/app/javascript/dashboard/store/modules/specs/conversationStats/mutations.spec.js b/app/javascript/dashboard/store/modules/specs/conversationStats/mutations.spec.js new file mode 100644 index 000000000..e49d938e3 --- /dev/null +++ b/app/javascript/dashboard/store/modules/specs/conversationStats/mutations.spec.js @@ -0,0 +1,20 @@ +import types from '../../../mutation-types'; +import { mutations } from '../../conversationStats'; + +describe('#mutations', () => { + describe('#SET_CONV_TAB_META', () => { + it('set conversation stats correctly', () => { + const state = {}; + mutations[types.SET_CONV_TAB_META](state, { + mine_count: 1, + unassigned_count: 1, + all_count: 2, + }); + expect(state).toEqual({ + mineCount: 1, + unAssignedCount: 1, + allCount: 2, + }); + }); + }); +}); diff --git a/app/javascript/dashboard/store/mutation-types.js b/app/javascript/dashboard/store/mutation-types.js index 15c5fe577..98731d2bc 100755 --- a/app/javascript/dashboard/store/mutation-types.js +++ b/app/javascript/dashboard/store/mutation-types.js @@ -32,7 +32,6 @@ export default { ADD_MESSAGE: 'ADD_MESSAGE', MARK_SEEN: 'MARK_SEEN', MARK_MESSAGE_READ: 'MARK_MESSAGE_READ', - SET_AGENT_TYPING: 'SET_AGENT_TYPING', SET_PREVIOUS_CONVERSATIONS: 'SET_PREVIOUS_CONVERSATIONS', SET_ACTIVE_INBOX: 'SET_ACTIVE_INBOX',