Split conversation module into getters and actions

This commit is contained in:
Pranav Raj Sreepuram
2019-09-05 13:01:36 +05:30
parent f9d4c2af90
commit 3549fc5fdd
5 changed files with 423 additions and 441 deletions

View File

@@ -4,8 +4,6 @@ import Pusher from 'pusher-js';
import AuthAPI from '../api/auth';
import CONSTANTS from '../constants';
const ding = require('../assets/audio/ding.mp3');
class VuePusher {
constructor(apiKey, options) {
this.app = options.app;
@@ -27,9 +25,6 @@ class VuePusher {
bindEvent(channel) {
channel.bind('message.created', data => {
if (!data.message_type) {
new Audio(ding).play();
}
this.app.$store.dispatch('addMessage', data);
});

View File

@@ -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,
};

View 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;

View 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;

View 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,
};