Adds unread message bubbles for widget (#943)
Co-authored-by: Sojan <sojan@pepalo.com> Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
This commit is contained in:
committed by
GitHub
parent
6a7d810c95
commit
49db9c5d8a
@@ -11,6 +11,7 @@ const state = {
|
||||
};
|
||||
|
||||
export const getters = {
|
||||
getHasFetched: $state => $state.uiFlags.hasFetched,
|
||||
availableAgents: $state =>
|
||||
$state.records.filter(agent => agent.availability_status === 'online'),
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
getMessagesAPI,
|
||||
sendAttachmentAPI,
|
||||
toggleTyping,
|
||||
setUserLastSeenAt,
|
||||
} from 'widget/api/conversation';
|
||||
import { MESSAGE_TYPE } from 'widget/helpers/constants';
|
||||
import { playNotificationAudio } from 'shared/helpers/AudioNotificationHelper';
|
||||
@@ -59,10 +60,22 @@ export const findUndeliveredMessage = (messageInbox, { content }) =>
|
||||
message => message.content === content && message.status === 'in_progress'
|
||||
);
|
||||
|
||||
export const onNewMessageCreated = data => {
|
||||
const { message_type: messageType } = data;
|
||||
const isIncomingMessage = messageType === MESSAGE_TYPE.OUTGOING;
|
||||
|
||||
if (isIncomingMessage) {
|
||||
playNotificationAudio();
|
||||
}
|
||||
};
|
||||
|
||||
export const DEFAULT_CONVERSATION = 'default';
|
||||
|
||||
const state = {
|
||||
conversations: {},
|
||||
meta: {
|
||||
userLastSeenAt: undefined,
|
||||
},
|
||||
uiFlags: {
|
||||
allMessagesLoaded: false,
|
||||
isFetchingList: false,
|
||||
@@ -93,6 +106,31 @@ export const getters = {
|
||||
}));
|
||||
},
|
||||
getIsFetchingList: _state => _state.uiFlags.isFetchingList,
|
||||
getUnreadMessageCount: _state => {
|
||||
const { userLastSeenAt } = _state.meta;
|
||||
console.log(userLastSeenAt);
|
||||
const count = Object.values(_state.conversations).filter(chat => {
|
||||
const { created_at: createdAt, message_type: messageType } = chat;
|
||||
const isOutGoing = messageType === MESSAGE_TYPE.OUTGOING;
|
||||
const hasNotSeen = userLastSeenAt
|
||||
? createdAt * 1000 > userLastSeenAt * 1000
|
||||
: true;
|
||||
return hasNotSeen && isOutGoing;
|
||||
}).length;
|
||||
return count;
|
||||
},
|
||||
getUnreadTextMessages: (_state, _getters) => {
|
||||
const unreadCount = _getters.getUnreadMessageCount;
|
||||
const allMessages = [...Object.values(_state.conversations)];
|
||||
console.log(unreadCount);
|
||||
const unreadAgentMessages = allMessages.filter(message => {
|
||||
const { message_type: messageType } = message;
|
||||
return messageType === MESSAGE_TYPE.OUTGOING;
|
||||
});
|
||||
const maxUnreadCount = Math.min(unreadCount, 3);
|
||||
const allUnreadMessages = unreadAgentMessages.splice(-maxUnreadCount);
|
||||
return allUnreadMessages;
|
||||
},
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
@@ -112,7 +150,9 @@ export const actions = {
|
||||
file_type: fileType,
|
||||
status: 'in_progress',
|
||||
};
|
||||
const tempMessage = createTemporaryMessage({ attachments: [attachment] });
|
||||
const tempMessage = createTemporaryMessage({
|
||||
attachments: [attachment],
|
||||
});
|
||||
commit('pushMessageToConversation', tempMessage);
|
||||
try {
|
||||
const { data } = await sendAttachmentAPI(params);
|
||||
@@ -136,12 +176,9 @@ export const actions = {
|
||||
}
|
||||
},
|
||||
|
||||
addMessage({ commit }, data) {
|
||||
if (data.message_type === MESSAGE_TYPE.OUTGOING) {
|
||||
playNotificationAudio();
|
||||
}
|
||||
|
||||
addMessage: async ({ commit }, data) => {
|
||||
commit('pushMessageToConversation', data);
|
||||
onNewMessageCreated(data);
|
||||
},
|
||||
|
||||
updateMessage({ commit }, data) {
|
||||
@@ -156,7 +193,21 @@ export const actions = {
|
||||
try {
|
||||
await toggleTyping(data);
|
||||
} catch (error) {
|
||||
// console error
|
||||
// IgnoreError
|
||||
}
|
||||
},
|
||||
|
||||
setUserLastSeen: async ({ commit, getters: appGetters }) => {
|
||||
if (!appGetters.getConversationSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
const lastSeen = Date.now() / 1000;
|
||||
try {
|
||||
commit('setMetaUserLastSeenAt', lastSeen);
|
||||
await setUserLastSeenAt({ lastSeen });
|
||||
} catch (error) {
|
||||
// IgnoreError
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -224,6 +275,10 @@ export const mutations = {
|
||||
const isTyping = status === 'on';
|
||||
$state.uiFlags.isAgentTyping = isTyping;
|
||||
},
|
||||
|
||||
setMetaUserLastSeenAt($state, lastSeen) {
|
||||
$state.meta.userLastSeenAt = lastSeen;
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
|
||||
@@ -17,7 +17,9 @@ export const actions = {
|
||||
get: async ({ commit }) => {
|
||||
try {
|
||||
const { data } = await getConversationAPI();
|
||||
const { user_last_seen_at: lastSeen } = data;
|
||||
commit(SET_CONVERSATION_ATTRIBUTES, data);
|
||||
commit('conversation/setMetaUserLastSeenAt', lastSeen, { root: true });
|
||||
} catch (error) {
|
||||
// Ignore error
|
||||
}
|
||||
|
||||
@@ -86,4 +86,12 @@ describe('#actions', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setUserLastSeen', () => {
|
||||
it('sends correct mutations', () => {
|
||||
const lastSeen = Math.abs(Date.now() / 1000);
|
||||
actions.setUserLastSeen({ commit }, { lastSeen });
|
||||
expect(commit).toBeCalledWith('setMetaUserLastSeenAt', lastSeen);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -262,4 +262,171 @@ describe('#getters', () => {
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
describe('getUnreadMessageCount returns', () => {
|
||||
it('0 if there are no messages and last seen is undefined', () => {
|
||||
const state = {
|
||||
conversations: {},
|
||||
meta: {
|
||||
userLastSeenAt: undefined,
|
||||
},
|
||||
};
|
||||
expect(getters.getUnreadMessageCount(state)).toEqual(0);
|
||||
});
|
||||
|
||||
it('0 if there are no messages and last seen is present', () => {
|
||||
const state = {
|
||||
conversations: {},
|
||||
meta: {
|
||||
userLastSeenAt: Date.now(),
|
||||
},
|
||||
};
|
||||
expect(getters.getUnreadMessageCount(state)).toEqual(0);
|
||||
});
|
||||
|
||||
it('unread count if there are messages and last seen is before messages created-at', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
1: {
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
message_type: 1,
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
message_type: 1,
|
||||
},
|
||||
},
|
||||
meta: {
|
||||
userLastSeenAt: 1474075964,
|
||||
},
|
||||
};
|
||||
expect(getters.getUnreadMessageCount(state)).toEqual(2);
|
||||
});
|
||||
|
||||
it('unread count if there are messages and last seen is after messages created-at', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
1: {
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
message_type: 1,
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
message_type: 1,
|
||||
},
|
||||
3: {
|
||||
id: 3,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
message_type: 0,
|
||||
},
|
||||
},
|
||||
meta: {
|
||||
userLastSeenAt: 1674075964,
|
||||
},
|
||||
};
|
||||
expect(getters.getUnreadMessageCount(state)).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUnreadTextMessages returns', () => {
|
||||
it('no messages if there are no messages and last seen is undefined', () => {
|
||||
const state = {
|
||||
conversations: {},
|
||||
meta: {
|
||||
userLastSeenAt: undefined,
|
||||
},
|
||||
};
|
||||
expect(
|
||||
getters.getUnreadTextMessages(state, { getUnreadMessageCount: 0 })
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it('0 if there are no messages and last seen is present', () => {
|
||||
const state = {
|
||||
conversations: {},
|
||||
meta: {
|
||||
userLastSeenAt: Date.now(),
|
||||
},
|
||||
};
|
||||
expect(
|
||||
getters.getUnreadTextMessages(state, { getUnreadMessageCount: 0 })
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it('only unread text messages from agent if there are messages and last seen is before messages created-at', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
1: {
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
message_type: 1,
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
message_type: 0,
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(
|
||||
getters.getUnreadTextMessages(state, { getUnreadMessageCount: 1 })
|
||||
).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
message_type: 1,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('unread messages omitting seen messages ', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
1: {
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
message_type: 1,
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1674075965,
|
||||
message_type: 1,
|
||||
},
|
||||
3: {
|
||||
id: 3,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
message_type: 0,
|
||||
},
|
||||
},
|
||||
meta: {
|
||||
userLastSeenAt: 1674075964,
|
||||
},
|
||||
};
|
||||
expect(
|
||||
getters.getUnreadTextMessages(state, { getUnreadMessageCount: 1 })
|
||||
).toEqual([
|
||||
{
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1674075965,
|
||||
message_type: 1,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,6 +11,7 @@ describe('#actions', () => {
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['SET_CONVERSATION_ATTRIBUTES', { id: 1, status: 'bot' }],
|
||||
['conversation/setMetaUserLastSeenAt', undefined, { root: true }],
|
||||
]);
|
||||
});
|
||||
it('doesnot send mutation if api is error', async () => {
|
||||
|
||||
Reference in New Issue
Block a user