Split conversation module into getters and actions
This commit is contained in:
@@ -4,8 +4,6 @@ import Pusher from 'pusher-js';
|
|||||||
import AuthAPI from '../api/auth';
|
import AuthAPI from '../api/auth';
|
||||||
import CONSTANTS from '../constants';
|
import CONSTANTS from '../constants';
|
||||||
|
|
||||||
const ding = require('../assets/audio/ding.mp3');
|
|
||||||
|
|
||||||
class VuePusher {
|
class VuePusher {
|
||||||
constructor(apiKey, options) {
|
constructor(apiKey, options) {
|
||||||
this.app = options.app;
|
this.app = options.app;
|
||||||
@@ -27,9 +25,6 @@ class VuePusher {
|
|||||||
|
|
||||||
bindEvent(channel) {
|
bindEvent(channel) {
|
||||||
channel.bind('message.created', data => {
|
channel.bind('message.created', data => {
|
||||||
if (!data.message_type) {
|
|
||||||
new Audio(ding).play();
|
|
||||||
}
|
|
||||||
this.app.$store.dispatch('addMessage', data);
|
this.app.$store.dispatch('addMessage', data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,436 +0,0 @@
|
|||||||
/* eslint no-console: 0 */
|
|
||||||
/* eslint no-param-reassign: 0 */
|
|
||||||
import Vue from 'vue';
|
|
||||||
import * as types from '../mutation-types';
|
|
||||||
import ChatList from '../../api/inbox';
|
|
||||||
import ConversationApi from '../../api/inbox/conversation';
|
|
||||||
import messageApi from '../../api/inbox/message';
|
|
||||||
import authAPI from '../../api/auth';
|
|
||||||
import wootConstants from '../../constants';
|
|
||||||
|
|
||||||
// const chatType = 'all';
|
|
||||||
// initial state
|
|
||||||
const state = {
|
|
||||||
allConversations: [],
|
|
||||||
convTabStats: {
|
|
||||||
mineCount: 0,
|
|
||||||
unAssignedCount: 0,
|
|
||||||
allCount: 0,
|
|
||||||
},
|
|
||||||
selectedChat: {
|
|
||||||
id: null,
|
|
||||||
meta: {},
|
|
||||||
status: null,
|
|
||||||
seen: false,
|
|
||||||
agentTyping: 'off',
|
|
||||||
dataFetched: false,
|
|
||||||
},
|
|
||||||
listLoadingStatus: true,
|
|
||||||
chatStatusFilter: wootConstants.ASSIGNEE_TYPE_SLUG.OPEN,
|
|
||||||
currentInbox: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
// getters
|
|
||||||
const getters = {
|
|
||||||
getAllConversations(_state) {
|
|
||||||
return _state.allConversations;
|
|
||||||
},
|
|
||||||
getSelectedChat(_state) {
|
|
||||||
return _state.selectedChat;
|
|
||||||
},
|
|
||||||
getMineChats(_state) {
|
|
||||||
const currentUserID = authAPI.getCurrentUser().id;
|
|
||||||
return _state.allConversations.filter(chat =>
|
|
||||||
chat.meta.assignee === null
|
|
||||||
? false
|
|
||||||
: chat.status === _state.chatStatusFilter &&
|
|
||||||
chat.meta.assignee.id === currentUserID
|
|
||||||
);
|
|
||||||
},
|
|
||||||
getUnAssignedChats(_state) {
|
|
||||||
return _state.allConversations.filter(
|
|
||||||
chat =>
|
|
||||||
chat.meta.assignee === null && chat.status === _state.chatStatusFilter
|
|
||||||
);
|
|
||||||
},
|
|
||||||
getAllStatusChats(_state) {
|
|
||||||
return _state.allConversations.filter(
|
|
||||||
chat => chat.status === _state.chatStatusFilter
|
|
||||||
);
|
|
||||||
},
|
|
||||||
getChatListLoadingStatus(_state) {
|
|
||||||
return _state.listLoadingStatus;
|
|
||||||
},
|
|
||||||
getAllMessagesLoaded(_state) {
|
|
||||||
const [chat] = _state.allConversations.filter(
|
|
||||||
c => c.id === _state.selectedChat.id
|
|
||||||
);
|
|
||||||
return chat.allMessagesLoaded === undefined
|
|
||||||
? false
|
|
||||||
: chat.allMessagesLoaded;
|
|
||||||
},
|
|
||||||
getUnreadCount(_state) {
|
|
||||||
const [chat] = _state.allConversations.filter(
|
|
||||||
c => c.id === _state.selectedChat.id
|
|
||||||
);
|
|
||||||
return chat.messages.filter(
|
|
||||||
chatMessage =>
|
|
||||||
chatMessage.created_at * 1000 > chat.agent_last_seen_at * 1000 &&
|
|
||||||
(chatMessage.message_type === 0 && chatMessage.private !== true)
|
|
||||||
).length;
|
|
||||||
},
|
|
||||||
getChatStatusFilter(_state) {
|
|
||||||
return _state.chatStatusFilter;
|
|
||||||
},
|
|
||||||
getSelectedInbox(_state) {
|
|
||||||
return _state.currentInbox;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// actions
|
|
||||||
const actions = {
|
|
||||||
fetchAllConversations({ commit }, fetchParams) {
|
|
||||||
commit(types.default.SET_LIST_LOADING_STATUS);
|
|
||||||
ChatList.fetchAllConversations(fetchParams, response => {
|
|
||||||
commit(types.default.SET_ALL_CONVERSATION, {
|
|
||||||
chats: response.data.data.payload,
|
|
||||||
});
|
|
||||||
commit(types.default.SET_CONV_TAB_META, {
|
|
||||||
meta: response.data.data.meta,
|
|
||||||
});
|
|
||||||
commit(types.default.CLEAR_LIST_LOADING_STATUS);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
emptyAllConversations({ commit }) {
|
|
||||||
commit(types.default.EMPTY_ALL_CONVERSATION);
|
|
||||||
},
|
|
||||||
|
|
||||||
clearSelectedState({ commit }) {
|
|
||||||
commit(types.default.CLEAR_CURRENT_CHAT_WINDOW);
|
|
||||||
},
|
|
||||||
|
|
||||||
fetchPreviousMessages({ commit }, data) {
|
|
||||||
const donePromise = new Promise(resolve => {
|
|
||||||
messageApi
|
|
||||||
.fetchPreviousMessages(data)
|
|
||||||
.then(response => {
|
|
||||||
commit(types.default.SET_PREVIOUS_CONVERSATIONS, {
|
|
||||||
id: data.id,
|
|
||||||
data: response.data.payload,
|
|
||||||
});
|
|
||||||
if (response.data.payload.length < 20) {
|
|
||||||
commit(types.default.SET_ALL_MESSAGES_LOADED);
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return donePromise;
|
|
||||||
},
|
|
||||||
|
|
||||||
setActiveChat(store, data) {
|
|
||||||
const { commit } = store;
|
|
||||||
const localDispatch = store.dispatch;
|
|
||||||
let donePromise = null;
|
|
||||||
|
|
||||||
commit(types.default.CURRENT_CHAT_WINDOW, data);
|
|
||||||
commit(types.default.CLEAR_ALL_MESSAGES_LOADED);
|
|
||||||
|
|
||||||
if (data.dataFetched === undefined) {
|
|
||||||
donePromise = new Promise(resolve => {
|
|
||||||
localDispatch('fetchPreviousMessages', {
|
|
||||||
id: data.id,
|
|
||||||
before: data.messages[0].id,
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
Vue.set(data, 'dataFetched', true);
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
donePromise = new Promise(resolve => {
|
|
||||||
commit(types.default.SET_CHAT_META, { id: data.id });
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return donePromise;
|
|
||||||
},
|
|
||||||
|
|
||||||
assignAgent({ commit }, data) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
ConversationApi.assignAgent(data).then(response => {
|
|
||||||
commit(types.default.ASSIGN_AGENT, response.data);
|
|
||||||
resolve(response.data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
toggleStatus({ commit }, data) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
ConversationApi.toggleStatus(data).then(response => {
|
|
||||||
commit(
|
|
||||||
types.default.RESOLVE_CONVERSATION,
|
|
||||||
response.data.payload.current_status
|
|
||||||
);
|
|
||||||
resolve(response.data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// toggleStatusPusher({ commit }, data) {
|
|
||||||
// commit(types.default.RESOLVE_CONVERSATION, response.data.payload.current_status);
|
|
||||||
// },
|
|
||||||
|
|
||||||
sendMessage({ commit }, data) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
messageApi
|
|
||||||
.sendMessage(data)
|
|
||||||
.then(response => {
|
|
||||||
commit(types.default.SEND_MESSAGE, response);
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.catch();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
addPrivateNote({ commit }, data) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
messageApi
|
|
||||||
.addPrivateNote(data)
|
|
||||||
.then(response => {
|
|
||||||
commit(types.default.SEND_MESSAGE, response);
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.catch();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
addMessage({ commit }, message) {
|
|
||||||
commit(types.default.ADD_MESSAGE, message);
|
|
||||||
},
|
|
||||||
|
|
||||||
addConversation({ commit }, conversation) {
|
|
||||||
commit(types.default.ADD_CONVERSATION, conversation);
|
|
||||||
},
|
|
||||||
|
|
||||||
toggleTyping({ commit }, data) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
ConversationApi.fbTyping(data)
|
|
||||||
.then(() => {
|
|
||||||
commit(types.default.FB_TYPING, data);
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.catch();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
markSeen({ commit }, data) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
ConversationApi.markSeen(data)
|
|
||||||
.then(response => {
|
|
||||||
commit(types.default.MARK_SEEN, response);
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.catch();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
markMessagesRead({ commit }, data) {
|
|
||||||
setTimeout(() => {
|
|
||||||
commit(types.default.MARK_MESSAGE_READ, data);
|
|
||||||
}, 4000);
|
|
||||||
return new Promise(resolve => {
|
|
||||||
ConversationApi.markMessageRead(data)
|
|
||||||
.then(() => {
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.catch();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
setChatFilter({ commit }, data) {
|
|
||||||
commit(types.default.CHANGE_CHAT_STATUS_FILTER, data);
|
|
||||||
},
|
|
||||||
|
|
||||||
updateAssignee({ commit }, data) {
|
|
||||||
commit(types.default.UPDATE_ASSIGNEE, data);
|
|
||||||
},
|
|
||||||
|
|
||||||
setActiveInbox({ commit }, inboxId) {
|
|
||||||
commit(types.default.SET_ACTIVE_INBOX, inboxId);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// mutations
|
|
||||||
const mutations = {
|
|
||||||
[types.default.SET_ALL_CONVERSATION](_state, data) {
|
|
||||||
if (data) {
|
|
||||||
_state.allConversations.push(...data.chats);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.EMPTY_ALL_CONVERSATION](_state) {
|
|
||||||
_state.allConversations = [];
|
|
||||||
_state.selectedChat = {
|
|
||||||
id: null,
|
|
||||||
meta: {},
|
|
||||||
status: null,
|
|
||||||
seen: false,
|
|
||||||
agentTyping: 'off',
|
|
||||||
dataFetched: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.SET_ALL_MESSAGES_LOADED](_state) {
|
|
||||||
const [chat] = _state.allConversations.filter(
|
|
||||||
c => c.id === _state.selectedChat.id
|
|
||||||
);
|
|
||||||
Vue.set(chat, 'allMessagesLoaded', true);
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.CLEAR_ALL_MESSAGES_LOADED](_state) {
|
|
||||||
const [chat] = _state.allConversations.filter(
|
|
||||||
c => c.id === _state.selectedChat.id
|
|
||||||
);
|
|
||||||
Vue.set(chat, 'allMessagesLoaded', false);
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.CLEAR_CURRENT_CHAT_WINDOW](_state) {
|
|
||||||
_state.selectedChat.id = null;
|
|
||||||
_state.selectedChat.agentTyping = 'off';
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.SET_PREVIOUS_CONVERSATIONS](_state, { id, data }) {
|
|
||||||
if (data.length) {
|
|
||||||
const [chat] = _state.allConversations.filter(c => c.id === id);
|
|
||||||
chat.messages.unshift(...data);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.SET_CONV_TAB_META](_state, { meta }) {
|
|
||||||
if (meta) {
|
|
||||||
Vue.set(_state.convTabStats, 'overdueCount', meta.overdue_count);
|
|
||||||
Vue.set(_state.convTabStats, 'allConvCount', meta.all_count);
|
|
||||||
Vue.set(_state.convTabStats, 'openCount', meta.open_count);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.CURRENT_CHAT_WINDOW](_state, activeChat) {
|
|
||||||
if (activeChat) {
|
|
||||||
Object.assign(_state.selectedChat, activeChat);
|
|
||||||
Vue.set(_state.selectedChat.meta, 'assignee', activeChat.meta.assignee);
|
|
||||||
Vue.set(_state.selectedChat.meta, 'status', activeChat.meta.status);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.APPEND_MESSAGES](_state, { id, data }) {
|
|
||||||
if (data.length) {
|
|
||||||
const [chat] = _state.allConversations.filter(c => c.id === id);
|
|
||||||
chat.messages = data;
|
|
||||||
Vue.set(chat, 'dataFetched', true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.SET_CHAT_META](_state, { id, data }) {
|
|
||||||
const [chat] = _state.allConversations.filter(c => c.id === id);
|
|
||||||
if (data !== undefined) {
|
|
||||||
Vue.set(chat, 'labels', data.labels);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.ASSIGN_AGENT](_state, assignee) {
|
|
||||||
const [chat] = _state.allConversations.filter(
|
|
||||||
c => c.id === _state.selectedChat.id
|
|
||||||
);
|
|
||||||
chat.meta.assignee = assignee;
|
|
||||||
if (assignee === null) {
|
|
||||||
Object.assign(_state.selectedChat.meta.assignee, assignee);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.RESOLVE_CONVERSATION](_state, status) {
|
|
||||||
const [chat] = _state.allConversations.filter(
|
|
||||||
c => c.id === _state.selectedChat.id
|
|
||||||
);
|
|
||||||
chat.status = status;
|
|
||||||
_state.selectedChat.status = status;
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.SEND_MESSAGE](_state, response) {
|
|
||||||
const [chat] = _state.allConversations.filter(
|
|
||||||
c => c.id === _state.selectedChat.id
|
|
||||||
);
|
|
||||||
const previousMessageIds = chat.messages.map(m => m.id);
|
|
||||||
if (!previousMessageIds.includes(response.data.id)) {
|
|
||||||
chat.messages.push(response.data);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.ADD_MESSAGE](_state, message) {
|
|
||||||
const [chat] = _state.allConversations.filter(
|
|
||||||
c => c.id === message.conversation_id
|
|
||||||
);
|
|
||||||
if (!chat) return;
|
|
||||||
const previousMessageIds = chat.messages.map(m => m.id);
|
|
||||||
if (!previousMessageIds.includes(message.id)) {
|
|
||||||
chat.messages.push(message);
|
|
||||||
if (_state.selectedChat.id === message.conversation_id) {
|
|
||||||
window.bus.$emit('scrollToMessage');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.ADD_CONVERSATION](_state, conversation) {
|
|
||||||
_state.allConversations.push(conversation);
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.MARK_SEEN](_state, response) {
|
|
||||||
if (response.status === 200) {
|
|
||||||
_state.selectedChat.seen = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.FB_TYPING](_state, { flag }) {
|
|
||||||
_state.selectedChat.agentTyping = flag;
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.SET_LIST_LOADING_STATUS](_state) {
|
|
||||||
_state.listLoadingStatus = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.CLEAR_LIST_LOADING_STATUS](_state) {
|
|
||||||
_state.listLoadingStatus = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.MARK_MESSAGE_READ](_state, { id, lastSeen }) {
|
|
||||||
const [chat] = _state.allConversations.filter(c => c.id === id);
|
|
||||||
chat.agent_last_seen_at = lastSeen;
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.CHANGE_CHAT_STATUS_FILTER](_state, data) {
|
|
||||||
_state.chatStatusFilter = data;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Update assignee on pusher message
|
|
||||||
[types.default.UPDATE_ASSIGNEE](_state, payload) {
|
|
||||||
const [chat] = _state.allConversations.filter(c => c.id === payload.id);
|
|
||||||
chat.meta.assignee = payload.assignee;
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.default.SET_ACTIVE_INBOX](_state, inboxId) {
|
|
||||||
_state.currentInbox = inboxId;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
|
||||||
state,
|
|
||||||
getters,
|
|
||||||
actions,
|
|
||||||
mutations,
|
|
||||||
};
|
|
||||||
184
app/javascript/src/store/modules/conversations/actions.js
Normal file
184
app/javascript/src/store/modules/conversations/actions.js
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
import Vue from 'vue';
|
||||||
|
import * as types from '../../mutation-types';
|
||||||
|
|
||||||
|
import ChatList from '../../../api/inbox';
|
||||||
|
import ConversationApi from '../../../api/inbox/conversation';
|
||||||
|
import messageApi from '../../../api/inbox/message';
|
||||||
|
|
||||||
|
// actions
|
||||||
|
const actions = {
|
||||||
|
fetchAllConversations({ commit }, fetchParams) {
|
||||||
|
commit(types.default.SET_LIST_LOADING_STATUS);
|
||||||
|
ChatList.fetchAllConversations(fetchParams, response => {
|
||||||
|
commit(types.default.SET_ALL_CONVERSATION, {
|
||||||
|
chats: response.data.data.payload,
|
||||||
|
});
|
||||||
|
commit(types.default.SET_CONV_TAB_META, {
|
||||||
|
meta: response.data.data.meta,
|
||||||
|
});
|
||||||
|
commit(types.default.CLEAR_LIST_LOADING_STATUS);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
emptyAllConversations({ commit }) {
|
||||||
|
commit(types.default.EMPTY_ALL_CONVERSATION);
|
||||||
|
},
|
||||||
|
|
||||||
|
clearSelectedState({ commit }) {
|
||||||
|
commit(types.default.CLEAR_CURRENT_CHAT_WINDOW);
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchPreviousMessages({ commit }, data) {
|
||||||
|
const donePromise = new Promise(resolve => {
|
||||||
|
messageApi
|
||||||
|
.fetchPreviousMessages(data)
|
||||||
|
.then(response => {
|
||||||
|
commit(types.default.SET_PREVIOUS_CONVERSATIONS, {
|
||||||
|
id: data.id,
|
||||||
|
data: response.data.payload,
|
||||||
|
});
|
||||||
|
if (response.data.payload.length < 20) {
|
||||||
|
commit(types.default.SET_ALL_MESSAGES_LOADED);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return donePromise;
|
||||||
|
},
|
||||||
|
|
||||||
|
setActiveChat(store, data) {
|
||||||
|
const { commit } = store;
|
||||||
|
const localDispatch = store.dispatch;
|
||||||
|
let donePromise = null;
|
||||||
|
|
||||||
|
commit(types.default.CURRENT_CHAT_WINDOW, data);
|
||||||
|
commit(types.default.CLEAR_ALL_MESSAGES_LOADED);
|
||||||
|
|
||||||
|
if (data.dataFetched === undefined) {
|
||||||
|
donePromise = new Promise(resolve => {
|
||||||
|
localDispatch('fetchPreviousMessages', {
|
||||||
|
id: data.id,
|
||||||
|
before: data.messages[0].id,
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
Vue.set(data, 'dataFetched', true);
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
donePromise = new Promise(resolve => {
|
||||||
|
commit(types.default.SET_CHAT_META, { id: data.id });
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return donePromise;
|
||||||
|
},
|
||||||
|
|
||||||
|
assignAgent({ commit }, data) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
ConversationApi.assignAgent(data).then(response => {
|
||||||
|
commit(types.default.ASSIGN_AGENT, response.data);
|
||||||
|
resolve(response.data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleStatus({ commit }, data) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
ConversationApi.toggleStatus(data).then(response => {
|
||||||
|
commit(
|
||||||
|
types.default.RESOLVE_CONVERSATION,
|
||||||
|
response.data.payload.current_status
|
||||||
|
);
|
||||||
|
resolve(response.data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
sendMessage({ commit }, data) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
messageApi
|
||||||
|
.sendMessage(data)
|
||||||
|
.then(response => {
|
||||||
|
commit(types.default.SEND_MESSAGE, response);
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
addPrivateNote({ commit }, data) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
messageApi
|
||||||
|
.addPrivateNote(data)
|
||||||
|
.then(response => {
|
||||||
|
commit(types.default.SEND_MESSAGE, response);
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
addMessage({ commit }, message) {
|
||||||
|
commit(types.default.ADD_MESSAGE, message);
|
||||||
|
},
|
||||||
|
|
||||||
|
addConversation({ commit }, conversation) {
|
||||||
|
commit(types.default.ADD_CONVERSATION, conversation);
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleTyping({ commit }, data) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
ConversationApi.fbTyping(data)
|
||||||
|
.then(() => {
|
||||||
|
commit(types.default.FB_TYPING, data);
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
markSeen({ commit }, data) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
ConversationApi.markSeen(data)
|
||||||
|
.then(response => {
|
||||||
|
commit(types.default.MARK_SEEN, response);
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
markMessagesRead({ commit }, data) {
|
||||||
|
setTimeout(() => {
|
||||||
|
commit(types.default.MARK_MESSAGE_READ, data);
|
||||||
|
}, 4000);
|
||||||
|
return new Promise(resolve => {
|
||||||
|
ConversationApi.markMessageRead(data)
|
||||||
|
.then(() => {
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setChatFilter({ commit }, data) {
|
||||||
|
commit(types.default.CHANGE_CHAT_STATUS_FILTER, data);
|
||||||
|
},
|
||||||
|
|
||||||
|
updateAssignee({ commit }, data) {
|
||||||
|
commit(types.default.UPDATE_ASSIGNEE, data);
|
||||||
|
},
|
||||||
|
|
||||||
|
setActiveInbox({ commit }, inboxId) {
|
||||||
|
commit(types.default.SET_ACTIVE_INBOX, inboxId);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default actions;
|
||||||
52
app/javascript/src/store/modules/conversations/getters.js
Normal file
52
app/javascript/src/store/modules/conversations/getters.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import authAPI from '../../../api/auth';
|
||||||
|
|
||||||
|
export const getSelectedChatConversation = ({
|
||||||
|
allConversations,
|
||||||
|
selectedChat,
|
||||||
|
}) =>
|
||||||
|
allConversations.filter(conversation => conversation.id === selectedChat.id);
|
||||||
|
|
||||||
|
// getters
|
||||||
|
const getters = {
|
||||||
|
getAllConversations: ({ allConversations }) => allConversations,
|
||||||
|
getSelectedChat: ({ selectedChat }) => selectedChat,
|
||||||
|
getMineChats(_state) {
|
||||||
|
const currentUserID = authAPI.getCurrentUser().id;
|
||||||
|
return _state.allConversations.filter(chat =>
|
||||||
|
chat.meta.assignee === null
|
||||||
|
? false
|
||||||
|
: chat.status === _state.chatStatusFilter &&
|
||||||
|
chat.meta.assignee.id === currentUserID
|
||||||
|
);
|
||||||
|
},
|
||||||
|
getUnAssignedChats(_state) {
|
||||||
|
return _state.allConversations.filter(
|
||||||
|
chat =>
|
||||||
|
chat.meta.assignee === null && chat.status === _state.chatStatusFilter
|
||||||
|
);
|
||||||
|
},
|
||||||
|
getAllStatusChats(_state) {
|
||||||
|
return _state.allConversations.filter(
|
||||||
|
chat => chat.status === _state.chatStatusFilter
|
||||||
|
);
|
||||||
|
},
|
||||||
|
getChatListLoadingStatus: ({ listLoadingStatus }) => listLoadingStatus,
|
||||||
|
getAllMessagesLoaded(_state) {
|
||||||
|
const [chat] = getSelectedChatConversation(_state);
|
||||||
|
return chat.allMessagesLoaded === undefined
|
||||||
|
? false
|
||||||
|
: chat.allMessagesLoaded;
|
||||||
|
},
|
||||||
|
getUnreadCount(_state) {
|
||||||
|
const [chat] = getSelectedChatConversation(_state);
|
||||||
|
return chat.messages.filter(
|
||||||
|
chatMessage =>
|
||||||
|
chatMessage.created_at * 1000 > chat.agent_last_seen_at * 1000 &&
|
||||||
|
(chatMessage.message_type === 0 && chatMessage.private !== true)
|
||||||
|
).length;
|
||||||
|
},
|
||||||
|
getChatStatusFilter: ({ chatStatusFilter }) => chatStatusFilter,
|
||||||
|
getSelectedInbox: ({ currentInbox }) => currentInbox,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getters;
|
||||||
187
app/javascript/src/store/modules/conversations/index.js
Normal file
187
app/javascript/src/store/modules/conversations/index.js
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
/* eslint no-console: 0 */
|
||||||
|
/* eslint no-param-reassign: 0 */
|
||||||
|
import Vue from 'vue';
|
||||||
|
import * as types from '../../mutation-types';
|
||||||
|
import wootConstants from '../../../constants';
|
||||||
|
import getters, { getSelectedChatConversation } from './getters';
|
||||||
|
import actions from './actions';
|
||||||
|
|
||||||
|
// const chatType = 'all';
|
||||||
|
// initial state
|
||||||
|
const state = {
|
||||||
|
allConversations: [],
|
||||||
|
convTabStats: {
|
||||||
|
mineCount: 0,
|
||||||
|
unAssignedCount: 0,
|
||||||
|
allCount: 0,
|
||||||
|
},
|
||||||
|
selectedChat: {
|
||||||
|
id: null,
|
||||||
|
meta: {},
|
||||||
|
status: null,
|
||||||
|
seen: false,
|
||||||
|
agentTyping: 'off',
|
||||||
|
dataFetched: false,
|
||||||
|
},
|
||||||
|
listLoadingStatus: true,
|
||||||
|
chatStatusFilter: wootConstants.ASSIGNEE_TYPE_SLUG.OPEN,
|
||||||
|
currentInbox: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
// mutations
|
||||||
|
const mutations = {
|
||||||
|
[types.default.SET_ALL_CONVERSATION](_state, data) {
|
||||||
|
if (data) {
|
||||||
|
_state.allConversations.push(...data.chats);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.EMPTY_ALL_CONVERSATION](_state) {
|
||||||
|
_state.allConversations = [];
|
||||||
|
_state.selectedChat = {
|
||||||
|
id: null,
|
||||||
|
meta: {},
|
||||||
|
status: null,
|
||||||
|
seen: false,
|
||||||
|
agentTyping: 'off',
|
||||||
|
dataFetched: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.SET_ALL_MESSAGES_LOADED](_state) {
|
||||||
|
const [chat] = getSelectedChatConversation(_state);
|
||||||
|
Vue.set(chat, 'allMessagesLoaded', true);
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.CLEAR_ALL_MESSAGES_LOADED](_state) {
|
||||||
|
const [chat] = getSelectedChatConversation(_state);
|
||||||
|
Vue.set(chat, 'allMessagesLoaded', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.CLEAR_CURRENT_CHAT_WINDOW](_state) {
|
||||||
|
_state.selectedChat.id = null;
|
||||||
|
_state.selectedChat.agentTyping = 'off';
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.SET_PREVIOUS_CONVERSATIONS](_state, { id, data }) {
|
||||||
|
if (data.length) {
|
||||||
|
const [chat] = _state.allConversations.filter(c => c.id === id);
|
||||||
|
chat.messages.unshift(...data);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.SET_CONV_TAB_META](_state, { meta }) {
|
||||||
|
if (meta) {
|
||||||
|
Vue.set(_state.convTabStats, 'overdueCount', meta.overdue_count);
|
||||||
|
Vue.set(_state.convTabStats, 'allConvCount', meta.all_count);
|
||||||
|
Vue.set(_state.convTabStats, 'openCount', meta.open_count);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.CURRENT_CHAT_WINDOW](_state, activeChat) {
|
||||||
|
if (activeChat) {
|
||||||
|
Object.assign(_state.selectedChat, activeChat);
|
||||||
|
Vue.set(_state.selectedChat.meta, 'assignee', activeChat.meta.assignee);
|
||||||
|
Vue.set(_state.selectedChat.meta, 'status', activeChat.meta.status);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.APPEND_MESSAGES](_state, { id, data }) {
|
||||||
|
if (data.length) {
|
||||||
|
const [chat] = _state.allConversations.filter(c => c.id === id);
|
||||||
|
chat.messages = data;
|
||||||
|
Vue.set(chat, 'dataFetched', true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.SET_CHAT_META](_state, { id, data }) {
|
||||||
|
const [chat] = _state.allConversations.filter(c => c.id === id);
|
||||||
|
if (data !== undefined) {
|
||||||
|
Vue.set(chat, 'labels', data.labels);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.ASSIGN_AGENT](_state, assignee) {
|
||||||
|
const [chat] = getSelectedChatConversation(_state);
|
||||||
|
chat.meta.assignee = assignee;
|
||||||
|
if (assignee === null) {
|
||||||
|
Object.assign(_state.selectedChat.meta.assignee, assignee);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.RESOLVE_CONVERSATION](_state, status) {
|
||||||
|
const [chat] = getSelectedChatConversation(_state);
|
||||||
|
chat.status = status;
|
||||||
|
_state.selectedChat.status = status;
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.SEND_MESSAGE](_state, response) {
|
||||||
|
const [chat] = getSelectedChatConversation(_state);
|
||||||
|
const previousMessageIds = chat.messages.map(m => m.id);
|
||||||
|
if (!previousMessageIds.includes(response.data.id)) {
|
||||||
|
chat.messages.push(response.data);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.ADD_MESSAGE](_state, message) {
|
||||||
|
const [chat] = _state.allConversations.filter(
|
||||||
|
c => c.id === message.conversation_id
|
||||||
|
);
|
||||||
|
if (!chat) return;
|
||||||
|
const previousMessageIds = chat.messages.map(m => m.id);
|
||||||
|
if (!previousMessageIds.includes(message.id)) {
|
||||||
|
chat.messages.push(message);
|
||||||
|
if (_state.selectedChat.id === message.conversation_id) {
|
||||||
|
window.bus.$emit('scrollToMessage');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.ADD_CONVERSATION](_state, conversation) {
|
||||||
|
_state.allConversations.push(conversation);
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.MARK_SEEN](_state, response) {
|
||||||
|
if (response.status === 200) {
|
||||||
|
_state.selectedChat.seen = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.FB_TYPING](_state, { flag }) {
|
||||||
|
_state.selectedChat.agentTyping = flag;
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.SET_LIST_LOADING_STATUS](_state) {
|
||||||
|
_state.listLoadingStatus = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.CLEAR_LIST_LOADING_STATUS](_state) {
|
||||||
|
_state.listLoadingStatus = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.MARK_MESSAGE_READ](_state, { id, lastSeen }) {
|
||||||
|
const [chat] = _state.allConversations.filter(c => c.id === id);
|
||||||
|
chat.agent_last_seen_at = lastSeen;
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.CHANGE_CHAT_STATUS_FILTER](_state, data) {
|
||||||
|
_state.chatStatusFilter = data;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Update assignee on pusher message
|
||||||
|
[types.default.UPDATE_ASSIGNEE](_state, payload) {
|
||||||
|
const [chat] = _state.allConversations.filter(c => c.id === payload.id);
|
||||||
|
chat.meta.assignee = payload.assignee;
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.default.SET_ACTIVE_INBOX](_state, inboxId) {
|
||||||
|
_state.currentInbox = inboxId;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
state,
|
||||||
|
getters,
|
||||||
|
actions,
|
||||||
|
mutations,
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user