Initial Commit
Co-authored-by: Subin <subinthattaparambil@gmail.com> Co-authored-by: Manoj <manojmj92@gmail.com> Co-authored-by: Nithin <webofnithin@gmail.com>
This commit is contained in:
0
app/javascript/src/store/actions.js
Executable file
0
app/javascript/src/store/actions.js
Executable file
4
app/javascript/src/store/getters.js
Executable file
4
app/javascript/src/store/getters.js
Executable file
@@ -0,0 +1,4 @@
|
||||
/* eslint arrow-body-style: ["error", "always"] */
|
||||
// export default (state) => {
|
||||
|
||||
// };
|
||||
28
app/javascript/src/store/index.js
Executable file
28
app/javascript/src/store/index.js
Executable file
@@ -0,0 +1,28 @@
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
|
||||
import * as getters from './getters';
|
||||
|
||||
import auth from './modules/auth';
|
||||
import conversations from './modules/conversations';
|
||||
import sideMenuItems from './modules/sidebar';
|
||||
import AccountState from './modules/AccountState';
|
||||
import Channel from './modules/channels';
|
||||
import cannedResponse from './modules/cannedResponse';
|
||||
import reports from './modules/reports';
|
||||
import billing from './modules/billing';
|
||||
|
||||
Vue.use(Vuex);
|
||||
export default new Vuex.Store({
|
||||
getters,
|
||||
modules: {
|
||||
auth,
|
||||
conversations,
|
||||
sideMenuItems,
|
||||
AccountState,
|
||||
Channel,
|
||||
cannedResponse,
|
||||
reports,
|
||||
billing,
|
||||
},
|
||||
});
|
||||
104
app/javascript/src/store/modules/AccountState.js
Normal file
104
app/javascript/src/store/modules/AccountState.js
Normal file
@@ -0,0 +1,104 @@
|
||||
/* eslint no-console: 0 */
|
||||
/* eslint no-param-reassign: 0 */
|
||||
/* eslint no-shadow: 0 */
|
||||
import * as types from '../mutation-types';
|
||||
import Account from '../../api/account';
|
||||
|
||||
const state = {
|
||||
agents: [],
|
||||
fetchAPIloadingStatus: false,
|
||||
};
|
||||
|
||||
const getters = {
|
||||
getAgents(_state) {
|
||||
return _state.agents;
|
||||
},
|
||||
getVerifiedAgents(_state) {
|
||||
return _state.agents.filter(element => element.confirmed);
|
||||
},
|
||||
getAgentFetchStatus(_state) {
|
||||
return _state.fetchAPIloadingStatus;
|
||||
},
|
||||
};
|
||||
|
||||
const actions = {
|
||||
fetchAgents({ commit }) {
|
||||
commit(types.default.SET_AGENT_FETCHING_STATUS, true);
|
||||
Account.getAgents().then((response) => {
|
||||
commit(types.default.SET_AGENT_FETCHING_STATUS, false);
|
||||
commit(types.default.SET_AGENTS, response);
|
||||
}).catch();
|
||||
},
|
||||
addAgent({ commit }, agentInfo) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Account.addAgent(agentInfo).then((response) => {
|
||||
commit(types.default.ADD_AGENT, response);
|
||||
resolve();
|
||||
}).catch((response) => {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
},
|
||||
editAgent({ commit }, agentInfo) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Account.editAgent(agentInfo).then((response) => {
|
||||
commit(types.default.EDIT_AGENT, response, agentInfo.id);
|
||||
resolve();
|
||||
}).catch((response) => {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
},
|
||||
deleteAgent({ commit }, agentId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Account.deleteAgent(agentId).then((response) => {
|
||||
if (response.status === 200) {
|
||||
commit(types.default.DELETE_AGENT, agentId);
|
||||
}
|
||||
resolve();
|
||||
}).catch((response) => {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
// List
|
||||
[types.default.SET_AGENT_FETCHING_STATUS](_state, flag) {
|
||||
_state.fetchAPIloadingStatus = flag;
|
||||
},
|
||||
// List
|
||||
[types.default.SET_AGENTS](_state, response) {
|
||||
_state.agents = response.data;
|
||||
},
|
||||
// Add Agent
|
||||
[types.default.ADD_AGENT](_state, response) {
|
||||
if (response.status === 200) {
|
||||
_state.agents.push(response.data);
|
||||
}
|
||||
},
|
||||
// Edit Agent
|
||||
[types.default.EDIT_AGENT](_state, response) {
|
||||
if (response.status === 200) {
|
||||
_state.agents.forEach((element, index) => {
|
||||
if (element.id === response.data.id) {
|
||||
_state.agents[index] = response.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// Delete Agent
|
||||
[types.default.DELETE_AGENT](_state, { id }) {
|
||||
_state.agents = _state.agents.filter(agent => agent.id !== id);
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations,
|
||||
};
|
||||
101
app/javascript/src/store/modules/auth.js
Normal file
101
app/javascript/src/store/modules/auth.js
Normal file
@@ -0,0 +1,101 @@
|
||||
/* eslint no-console: 0 */
|
||||
/* eslint-env browser */
|
||||
/* eslint no-param-reassign: 0 */
|
||||
import axios from 'axios';
|
||||
import moment from 'moment';
|
||||
import Vue from 'vue';
|
||||
import * as types from '../mutation-types';
|
||||
import router from '../../routes';
|
||||
import authAPI from '../../api/auth';
|
||||
import createAxios from '../../helper/APIHelper';
|
||||
import vuePusher from '../../helper/pusher';
|
||||
// initial state
|
||||
const state = {
|
||||
currentUser: {
|
||||
id: null,
|
||||
account_id: null,
|
||||
channel: null,
|
||||
email: null,
|
||||
name: null,
|
||||
provider: null,
|
||||
uid: null,
|
||||
subscription: {
|
||||
state: null,
|
||||
expiry: null,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// getters
|
||||
const getters = {
|
||||
isLoggedIn(_state) {
|
||||
return _state.currentUser.id !== null;
|
||||
},
|
||||
|
||||
getCurrentUserID(_state) {
|
||||
return _state.currentUser.id;
|
||||
},
|
||||
|
||||
getSubscription(_state) {
|
||||
return _state.currentUser.subscription === undefined ? null : _state.currentUser.subscription;
|
||||
},
|
||||
|
||||
getTrialLeft(_state) {
|
||||
const createdAt = _state.currentUser.subscription === undefined ?
|
||||
moment() : _state.currentUser.subscription.expiry * 1000;
|
||||
const daysLeft = moment(createdAt).diff(moment(), 'days');
|
||||
return daysLeft < 0 ? 0 : daysLeft;
|
||||
},
|
||||
};
|
||||
|
||||
// actions
|
||||
const actions = {
|
||||
login({ commit }, credentials) {
|
||||
return new Promise((resolve, reject) => {
|
||||
authAPI.login(credentials)
|
||||
.then(() => {
|
||||
commit(types.default.SET_CURRENT_USER);
|
||||
window.axios = createAxios(axios);
|
||||
window.pusher = vuePusher.init(Vue);
|
||||
router.replace({ name: 'home' });
|
||||
resolve();
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
validityCheck(context) {
|
||||
if (context.getters.isLoggedIn) {
|
||||
authAPI.validityCheck();
|
||||
}
|
||||
},
|
||||
set_user({ commit }) {
|
||||
if (authAPI.isLoggedIn()) {
|
||||
commit(types.default.SET_CURRENT_USER);
|
||||
} else {
|
||||
commit(types.default.CLEAR_USER);
|
||||
}
|
||||
},
|
||||
logout({ commit }) {
|
||||
commit(types.default.CLEAR_USER);
|
||||
},
|
||||
};
|
||||
|
||||
// mutations
|
||||
const mutations = {
|
||||
[types.default.CLEAR_USER](_state) {
|
||||
_state.currentUser.id = null;
|
||||
},
|
||||
[types.default.SET_CURRENT_USER](_state) {
|
||||
Object.assign(_state.currentUser, authAPI.getAuthData());
|
||||
Object.assign(_state.currentUser, authAPI.getCurrentUser());
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations,
|
||||
};
|
||||
52
app/javascript/src/store/modules/billing.js
Normal file
52
app/javascript/src/store/modules/billing.js
Normal file
@@ -0,0 +1,52 @@
|
||||
/* eslint no-console: 0 */
|
||||
/* eslint no-param-reassign: 0 */
|
||||
/* eslint no-shadow: 0 */
|
||||
import * as types from '../mutation-types';
|
||||
import Billing from '../../api/billing';
|
||||
|
||||
const state = {
|
||||
fetchingStatus: false,
|
||||
billingDetails: {},
|
||||
status: null,
|
||||
};
|
||||
|
||||
const getters = {
|
||||
getBillingDetails(_state) {
|
||||
return _state.billingDetails;
|
||||
},
|
||||
billingFetchStatus(_state) {
|
||||
return _state.fetchingStatus;
|
||||
},
|
||||
};
|
||||
|
||||
const actions = {
|
||||
fetchSubscription({ commit }) {
|
||||
commit(types.default.TOGGLE_SUBSCRIPTION_LOADING, true);
|
||||
Billing.getSubscription()
|
||||
.then((billingDetails) => {
|
||||
commit(types.default.SET_SUBSCRIPTION, billingDetails.data);
|
||||
commit(types.default.TOGGLE_SUBSCRIPTION_LOADING, false, billingDetails.status);
|
||||
})
|
||||
.catch((error) => {
|
||||
const { response } = error;
|
||||
commit(types.default.TOGGLE_SUBSCRIPTION_LOADING, false, response.status);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
[types.default.SET_SUBSCRIPTION](_state, billingDetails) {
|
||||
_state.billingDetails = billingDetails;
|
||||
},
|
||||
[types.default.TOGGLE_SUBSCRIPTION_LOADING](_state, flag, apiStatus) {
|
||||
_state.fetchingStatus = flag;
|
||||
_state.status = apiStatus;
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations,
|
||||
};
|
||||
108
app/javascript/src/store/modules/cannedResponse.js
Normal file
108
app/javascript/src/store/modules/cannedResponse.js
Normal file
@@ -0,0 +1,108 @@
|
||||
/* eslint no-console: 0 */
|
||||
/* eslint no-param-reassign: 0 */
|
||||
/* eslint no-shadow: 0 */
|
||||
import * as types from '../mutation-types';
|
||||
import CannedApi from '../../api/cannedResponse';
|
||||
|
||||
const state = {
|
||||
cannedResponse: [],
|
||||
fetchAPIloadingStatus: false,
|
||||
};
|
||||
|
||||
const getters = {
|
||||
getCannedResponses(_state) {
|
||||
return _state.cannedResponse;
|
||||
},
|
||||
getCannedFetchStatus(_state) {
|
||||
return _state.fetchAPIloadingStatus;
|
||||
},
|
||||
};
|
||||
|
||||
const actions = {
|
||||
fetchCannedResponse({ commit }) {
|
||||
commit(types.default.SET_CANNED_FETCHING_STATUS, true);
|
||||
CannedApi.getAllCannedResponses().then((response) => {
|
||||
commit(types.default.SET_CANNED_FETCHING_STATUS, false);
|
||||
commit(types.default.SET_CANNED, response);
|
||||
}).catch();
|
||||
},
|
||||
searchCannedResponse({ commit }, { searchKey }) {
|
||||
commit(types.default.SET_CANNED_FETCHING_STATUS, true);
|
||||
CannedApi.searchCannedResponse({ searchKey }).then((response) => {
|
||||
commit(types.default.SET_CANNED_FETCHING_STATUS, false);
|
||||
commit(types.default.SET_CANNED, response);
|
||||
}).catch();
|
||||
},
|
||||
addCannedResponse({ commit }, cannedObj) {
|
||||
return new Promise((resolve, reject) => {
|
||||
CannedApi.addCannedResponse(cannedObj).then((response) => {
|
||||
commit(types.default.ADD_CANNED, response);
|
||||
resolve();
|
||||
}).catch((response) => {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
},
|
||||
editCannedResponse({ commit }, cannedObj) {
|
||||
return new Promise((resolve, reject) => {
|
||||
CannedApi.editCannedResponse(cannedObj).then((response) => {
|
||||
commit(types.default.EDIT_CANNED, response, cannedObj.id);
|
||||
resolve();
|
||||
}).catch((response) => {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
},
|
||||
deleteCannedResponse({ commit }, responseId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
CannedApi.deleteCannedResponse(responseId.id).then((response) => {
|
||||
if (response.status === 200) {
|
||||
commit(types.default.DELETE_CANNED, responseId);
|
||||
}
|
||||
resolve();
|
||||
}).catch((response) => {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
// List
|
||||
[types.default.SET_CANNED_FETCHING_STATUS](_state, flag) {
|
||||
_state.fetchAPIloadingStatus = flag;
|
||||
},
|
||||
// List
|
||||
[types.default.SET_CANNED](_state, response) {
|
||||
_state.cannedResponse = response.data;
|
||||
},
|
||||
// Add Agent
|
||||
[types.default.ADD_CANNED](_state, response) {
|
||||
if (response.status === 200) {
|
||||
_state.cannedResponse.push(response.data);
|
||||
}
|
||||
},
|
||||
// Edit Agent
|
||||
[types.default.EDIT_CANNED](_state, response) {
|
||||
if (response.status === 200) {
|
||||
_state.cannedResponse.forEach((element, index) => {
|
||||
if (element.id === response.data.id) {
|
||||
_state.cannedResponse[index] = response.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// Delete CannedResponse
|
||||
[types.default.DELETE_CANNED](_state, { id }) {
|
||||
_state.cannedResponse = _state.cannedResponse.filter(agent => agent.id !== id);
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations,
|
||||
};
|
||||
17
app/javascript/src/store/modules/channels.js
Normal file
17
app/javascript/src/store/modules/channels.js
Normal file
@@ -0,0 +1,17 @@
|
||||
/* eslint no-console: 0 */
|
||||
/* eslint no-param-reassign: 0 */
|
||||
|
||||
// const chatType = 'all';
|
||||
// initial state
|
||||
const state = {
|
||||
};
|
||||
|
||||
// actions
|
||||
const actions = {
|
||||
};
|
||||
|
||||
|
||||
export default {
|
||||
state,
|
||||
actions,
|
||||
};
|
||||
394
app/javascript/src/store/modules/conversations.js
Normal file
394
app/javascript/src/store/modules/conversations.js
Normal file
@@ -0,0 +1,394 @@
|
||||
/* 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.commit;
|
||||
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,
|
||||
};
|
||||
95
app/javascript/src/store/modules/reports.js
Normal file
95
app/javascript/src/store/modules/reports.js
Normal file
@@ -0,0 +1,95 @@
|
||||
/* eslint no-console: 0 */
|
||||
/* eslint no-param-reassign: 0 */
|
||||
/* eslint no-shadow: 0 */
|
||||
import moment from 'moment';
|
||||
|
||||
import * as types from '../mutation-types';
|
||||
import Report from '../../api/reports';
|
||||
|
||||
const state = {
|
||||
fetchingStatus: false,
|
||||
reportData: [],
|
||||
accountReport: {
|
||||
isFetching: false,
|
||||
data: [],
|
||||
},
|
||||
accountSummary: {
|
||||
avg_first_response_time: 0,
|
||||
avg_resolution_time: 0,
|
||||
conversations_count: 0,
|
||||
incoming_messages_count: 0,
|
||||
outgoing_messages_count: 0,
|
||||
resolutions_count: 0,
|
||||
},
|
||||
};
|
||||
|
||||
const getters = {
|
||||
getAccountReports(_state) {
|
||||
return _state.accountReport;
|
||||
},
|
||||
getAccountSummary(_state) {
|
||||
return _state.accountSummary;
|
||||
},
|
||||
};
|
||||
|
||||
const actions = {
|
||||
fetchAccountReport({ commit }, reportObj) {
|
||||
commit(types.default.TOGGLE_ACCOUNT_REPORT_LOADING, true);
|
||||
Report.getAccountReports(reportObj.metric, reportObj.from, reportObj.to)
|
||||
.then((accountReport) => {
|
||||
let { data } = accountReport;
|
||||
data = data.filter(el => moment() > moment.unix(el.timestamp));
|
||||
if (reportObj.metric === 'avg_first_response_time' || reportObj.metric === 'avg_resolution_time') {
|
||||
data = data.map((element) => {
|
||||
/* eslint-disable operator-assignment*/
|
||||
element.value = (element.value / 3600).toFixed(2);
|
||||
return element;
|
||||
});
|
||||
}
|
||||
commit(types.default.SET_ACCOUNT_REPORTS, data);
|
||||
commit(types.default.TOGGLE_ACCOUNT_REPORT_LOADING, false);
|
||||
});
|
||||
},
|
||||
fetchAccountSummary({ commit }, reportObj) {
|
||||
Report.getAccountSummary(1, reportObj.from, reportObj.to)
|
||||
.then((accountSummary) => {
|
||||
commit(types.default.SET_ACCOUNT_SUMMARY, accountSummary.data);
|
||||
})
|
||||
.catch(() => {
|
||||
commit(types.default.TOGGLE_ACCOUNT_REPORT_LOADING, false);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
[types.default.SET_ACCOUNT_REPORTS](_state, accountReport) {
|
||||
_state.accountReport.data = accountReport;
|
||||
},
|
||||
[types.default.TOGGLE_ACCOUNT_REPORT_LOADING](_state, flag) {
|
||||
_state.accountReport.isFetching = flag;
|
||||
},
|
||||
[types.default.SET_ACCOUNT_SUMMARY](_state, summaryData) {
|
||||
_state.accountSummary = summaryData;
|
||||
// Average First Response Time
|
||||
let avgFirstResTimeInHr = 0;
|
||||
if (summaryData.avg_first_response_time) {
|
||||
avgFirstResTimeInHr = (summaryData.avg_first_response_time / 3600).toFixed(2);
|
||||
avgFirstResTimeInHr = `${avgFirstResTimeInHr} Hr`;
|
||||
}
|
||||
// Average Resolution Time
|
||||
let avgResolutionTimeInHr = 0;
|
||||
if (summaryData.avg_resolution_time) {
|
||||
avgResolutionTimeInHr = (summaryData.avg_resolution_time / 3600).toFixed(2);
|
||||
avgResolutionTimeInHr = `${avgResolutionTimeInHr} Hr`;
|
||||
}
|
||||
_state.accountSummary.avg_first_response_time = avgFirstResTimeInHr;
|
||||
_state.accountSummary.avg_resolution_time = avgResolutionTimeInHr;
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations,
|
||||
};
|
||||
174
app/javascript/src/store/modules/sidebar.js
Normal file
174
app/javascript/src/store/modules/sidebar.js
Normal file
@@ -0,0 +1,174 @@
|
||||
/* eslint no-console: 0 */
|
||||
/* eslint-env browser */
|
||||
/* eslint no-param-reassign: 0 */
|
||||
|
||||
// import * as types from '../mutation-types';
|
||||
import defaultState from '../../i18n/default-sidebar';
|
||||
import * as types from '../mutation-types';
|
||||
import Account from '../../api/account';
|
||||
import ChannelApi from '../../api/channels';
|
||||
|
||||
const state = defaultState;
|
||||
// inboxes fetch flag
|
||||
state.inboxesLoading = false;
|
||||
|
||||
const getters = {
|
||||
getMenuItems(_state) {
|
||||
return _state.menuGroup;
|
||||
},
|
||||
getInboxesList(_state) {
|
||||
return _state.menuGroup.common.menuItems.inbox.children;
|
||||
},
|
||||
getInboxLoadingStatus(_state) {
|
||||
return _state.inboxesLoading;
|
||||
},
|
||||
};
|
||||
|
||||
const actions = {
|
||||
// Fetch Labels
|
||||
fetchLabels({ commit }) {
|
||||
Account.getLabels().then((response) => {
|
||||
commit(types.default.SET_LABELS, response.data);
|
||||
}).catch();
|
||||
},
|
||||
// Fetch Inboxes
|
||||
fetchInboxes({ commit }) {
|
||||
commit(types.default.INBOXES_LOADING, true);
|
||||
return new Promise((resolve, reject) => {
|
||||
Account.getInboxes().then((response) => {
|
||||
commit(types.default.INBOXES_LOADING, false);
|
||||
commit(types.default.SET_INBOXES, response.data);
|
||||
resolve();
|
||||
}).catch((error) => {
|
||||
commit(types.default.INBOXES_LOADING, false);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
deleteInbox({ commit }, id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Account.deleteInbox(id)
|
||||
.then((response) => {
|
||||
if (response.status === 200) {
|
||||
commit(types.default.DELETE_INBOX, id);
|
||||
resolve();
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
addInboxItem({ commit }, { channel, params }) {
|
||||
const donePromise = new Promise((resolve) => {
|
||||
ChannelApi.createChannel(channel, params).then((response) => {
|
||||
commit(types.default.SET_INBOX_ITEM, response);
|
||||
resolve(response);
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
});
|
||||
return donePromise;
|
||||
},
|
||||
listInboxAgents({ commit }, { inboxId }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Account.listInboxAgents(inboxId)
|
||||
.then((response) => {
|
||||
if (response.status === 200) {
|
||||
resolve(response.data);
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
updateInboxAgents({ commit }, { inboxId, agentList }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Account.updateInboxAgents(inboxId, agentList)
|
||||
.then((response) => {
|
||||
if (response.status === 200) {
|
||||
resolve(response.data);
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
|
||||
// Set Labels
|
||||
[types.default.SET_LABELS](_state, data) {
|
||||
let payload = data.data.payload.labels;
|
||||
payload = payload.map(item => ({
|
||||
label: item,
|
||||
toState: `/#/${item}`,
|
||||
}));
|
||||
// Identify menuItem to update
|
||||
// May have more than one object to update
|
||||
// Iterate it accordingly. Updating commmon sidebar now.
|
||||
const menuItems = _state.menuGroup.common.menuItems;
|
||||
// Update children for key `label`
|
||||
menuItems.labels.children = payload;
|
||||
},
|
||||
|
||||
[types.default.INBOXES_LOADING](_state, flag) {
|
||||
_state.inboxesLoading = flag;
|
||||
},
|
||||
// Set Inboxes
|
||||
[types.default.SET_INBOXES](_state, data) {
|
||||
let payload = data.data.payload;
|
||||
payload = payload.map(item => ({
|
||||
channel_id: item.id,
|
||||
label: item.name,
|
||||
toState: `/u/inbox/${item.id}`,
|
||||
channelType: item.channelType,
|
||||
avatarUrl: item.avatar_url,
|
||||
pageId: item.page_id,
|
||||
}));
|
||||
// Identify menuItem to update
|
||||
// May have more than one object to update
|
||||
// Iterate it accordingly. Updating commmon sidebar now.
|
||||
const menuItems = _state.menuGroup.common.menuItems;
|
||||
// Update children for key `inbox`
|
||||
menuItems.inbox.children = payload;
|
||||
},
|
||||
|
||||
[types.default.SET_INBOX_ITEM](_state, { data }) {
|
||||
const menuItems = _state.menuGroup.common.menuItems;
|
||||
// Update children for key `inbox`
|
||||
menuItems.inbox.children.push({
|
||||
channel_id: data.id,
|
||||
label: data.name,
|
||||
toState: `/u/inbox/${data.id}`,
|
||||
channelType: data.channelType,
|
||||
avatarUrl: data.avatar_url === undefined ? null : data.avatar_url,
|
||||
pageId: data.page_id,
|
||||
});
|
||||
},
|
||||
|
||||
[types.default.DELETE_INBOX](_state, id) {
|
||||
const menuItems = _state.menuGroup.common.menuItems;
|
||||
let inboxList = menuItems.inbox.children;
|
||||
inboxList = inboxList.filter(inbox => inbox.channel_id !== id);
|
||||
menuItems.inbox.children = inboxList;
|
||||
},
|
||||
|
||||
|
||||
};
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations,
|
||||
};
|
||||
65
app/javascript/src/store/mutation-types.js
Executable file
65
app/javascript/src/store/mutation-types.js
Executable file
@@ -0,0 +1,65 @@
|
||||
export default {
|
||||
AUTHENTICATE: 'AUTHENTICATE',
|
||||
CLEAR_USER: 'LOGOUT',
|
||||
SET_CURRENT_USER: 'SET_CURRENT_USER',
|
||||
// Chat List
|
||||
RECEIVE_CHAT_LIST: 'RECEIVE_CHAT_LIST',
|
||||
SET_ALL_CONVERSATION: 'SET_ALL_CONVERSATION',
|
||||
EMPTY_ALL_CONVERSATION: 'EMPTY_ALL_CONVERSATION',
|
||||
SET_CONV_TAB_META: 'SET_CONV_TAB_META',
|
||||
CLEAR_LIST_LOADING_STATUS: 'CLEAR_LIST_LOADING_STATUS',
|
||||
SET_LIST_LOADING_STATUS: 'SET_LIST_LOADING_STATUS',
|
||||
SET_ALL_MESSAGES_LOADED: 'SET_ALL_MESSAGES_LOADED',
|
||||
CLEAR_ALL_MESSAGES_LOADED: 'CLEAR_ALL_MESSAGES_LOADED',
|
||||
CHANGE_CHAT_STATUS_FILTER: 'CHANGE_CHAT_STATUS_FILTER',
|
||||
UPDATE_ASSIGNEE: 'UPDATE_ASSIGNEE',
|
||||
|
||||
// Active chat
|
||||
CURRENT_CHAT_WINDOW: 'CURRENT_CHAT_WINDOW',
|
||||
CLEAR_CURRENT_CHAT_WINDOW: 'CLEAR_CURRENT_CHAT_WINDOW',
|
||||
APPEND_MESSAGES: 'APPEND_MESSAGES',
|
||||
CLEAR_ALL_MESSAGES: 'CLEAR_ALL_MESSAGES',
|
||||
RESOLVE_CONVERSATION: 'RESOLVE_CONVERSATION',
|
||||
ADD_CONVERSATION: 'ADD_CONVERSATION',
|
||||
SEND_MESSAGE: 'SEND_MESSAGE',
|
||||
ASSIGN_AGENT: 'ASSIGN_AGENT',
|
||||
SET_CHAT_META: 'SET_CHAT_META',
|
||||
ADD_MESSAGE: 'ADD_MESSAGE',
|
||||
MARK_SEEN: 'MARK_SEEN',
|
||||
MARK_MESSAGE_READ: 'MARK_MESSAGE_READ',
|
||||
FB_TYPING: 'FB_TYPING',
|
||||
SET_PREVIOUS_CONVERSATIONS: 'SET_PREVIOUS_CONVERSATIONS',
|
||||
SET_ACTIVE_INBOX: 'SET_ACTIVE_INBOX',
|
||||
|
||||
// labels
|
||||
SET_LABELS: 'SET_LABELS',
|
||||
|
||||
// Set Inboxes
|
||||
INBOXES_LOADING: 'INBOXES_LOADING',
|
||||
SET_INBOXES: 'SET_INBOXES',
|
||||
SET_INBOX_ITEM: 'SET_INBOX_ITEM',
|
||||
DELETE_INBOX: 'DELETE_INBOX',
|
||||
|
||||
// Agent
|
||||
SET_AGENT_FETCHING_STATUS: 'SET_AGENT_FETCHING_STATUS',
|
||||
SET_AGENTS: 'SET_AGENTS',
|
||||
ADD_AGENT: 'ADD_AGENT',
|
||||
EDIT_AGENT: 'EDIT_AGENT',
|
||||
DELETE_AGENT: 'DELETE_AGENT',
|
||||
|
||||
// Canned Response
|
||||
SET_CANNED_FETCHING_STATUS: 'SET_CANNED_FETCHING_STATUS',
|
||||
SET_CANNED: 'SET_CANNED',
|
||||
ADD_CANNED: 'ADD_CANNED',
|
||||
EDIT_CANNED: 'EDIT_CANNED',
|
||||
DELETE_CANNED: 'DELETE_CANNED',
|
||||
|
||||
// Reports
|
||||
SET_ACCOUNT_REPORTS: 'SET_ACCOUNT_REPORTS',
|
||||
SET_ACCOUNT_SUMMARY: 'SET_ACCOUNT_SUMMARY',
|
||||
TOGGLE_ACCOUNT_REPORT_LOADING: 'TOGGLE_ACCOUNT_REPORT_LOADING',
|
||||
|
||||
// Billings
|
||||
SET_SUBSCRIPTION: 'SET_SUBSCRIPTION',
|
||||
TOGGLE_SUBSCRIPTION_LOADING: 'TOGGLE_SUBSCRIPTION_LOADING',
|
||||
};
|
||||
Reference in New Issue
Block a user