feat: Add state and mutations for multiple conversation on widget
This commit is contained in:
parent
430c0b1569
commit
fa5d9e8cd7
3 changed files with 519 additions and 0 deletions
36
app/javascript/widget/store/modules/conversation_new/index.js
Executable file
36
app/javascript/widget/store/modules/conversation_new/index.js
Executable file
|
@ -0,0 +1,36 @@
|
|||
import { getters } from './getters';
|
||||
import { actions } from './actions';
|
||||
import { mutations } from './mutations';
|
||||
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: {},
|
||||
allIds: [],
|
||||
uiFlags: {
|
||||
byId: {
|
||||
// 1: { allMessagesLoaded: false, isAgentTyping: false, isFetching: false },
|
||||
},
|
||||
},
|
||||
},
|
||||
messages: {
|
||||
byId: {},
|
||||
allIds: [],
|
||||
uiFlags: {
|
||||
byId: {
|
||||
// 1: { isCreating: false, isPending: false, isDeleting: false },
|
||||
},
|
||||
},
|
||||
},
|
||||
uiFlags: {
|
||||
allConversationsLoaded: false,
|
||||
isFetching: false,
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations,
|
||||
};
|
|
@ -0,0 +1,103 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
export const mutations = {
|
||||
setUIFlag($state, uiFlags) {
|
||||
$state.uiFlags = {
|
||||
...$state.uiFlags,
|
||||
...uiFlags,
|
||||
};
|
||||
},
|
||||
|
||||
addConversationEntry($state, conversation) {
|
||||
if (!conversation.id) return;
|
||||
|
||||
Vue.set($state.conversations.byId, conversation.id, {
|
||||
...conversation,
|
||||
messages: [],
|
||||
});
|
||||
},
|
||||
|
||||
addConversationId($state, conversationId) {
|
||||
$state.conversations.allIds.push(conversationId);
|
||||
},
|
||||
|
||||
updateConversationEntry($state, conversation) {
|
||||
if (!conversation.id) return;
|
||||
if (!$state.conversations.allIds.includes(conversation.id)) return;
|
||||
|
||||
Vue.set($state.conversations.byId, conversation.id, conversation);
|
||||
},
|
||||
|
||||
removeConversationEntry($state, conversationId) {
|
||||
if (!conversationId) return;
|
||||
|
||||
Vue.set($state.conversations.byId, conversationId, undefined);
|
||||
},
|
||||
|
||||
removeConversationId($state, conversationId) {
|
||||
$state.conversations.allIds = $state.conversations.allIds.filter(
|
||||
id => id !== conversationId
|
||||
);
|
||||
},
|
||||
|
||||
setConversationUIFlag($state, { conversationId, uiFlags }) {
|
||||
const flags = $state.conversations.uiFlags.byId[conversationId];
|
||||
$state.conversations.uiFlags.byId[conversationId] = {
|
||||
...flags,
|
||||
...uiFlags,
|
||||
};
|
||||
},
|
||||
|
||||
addMessageIds($state, { conversationId, messages }) {
|
||||
const conversationById = $state.conversations.byId[conversationId];
|
||||
if (!conversationById) return;
|
||||
|
||||
const messageIds = messages.map(message => message.id);
|
||||
const updatedMessageIds = [...conversationById.messages, ...messageIds];
|
||||
Vue.set(conversationById, 'messages', updatedMessageIds);
|
||||
},
|
||||
|
||||
updateMessageEntry($state, message) {
|
||||
const messageId = message.id;
|
||||
if (!messageId) return;
|
||||
|
||||
const messageById = $state.messages.byId[messageId];
|
||||
if (!messageById) return;
|
||||
if (messageId !== message.id) return;
|
||||
|
||||
Vue.set($state.messages.byId, messageId, { ...message });
|
||||
},
|
||||
|
||||
removeMessageEntry($state, messageId) {
|
||||
if (!messageId) return;
|
||||
|
||||
Vue.delete($state.messages.byId, messageId);
|
||||
},
|
||||
|
||||
removeMessageIdFromConversation($state, { conversationId, messageId }) {
|
||||
if (!messageId || !conversationId) return;
|
||||
|
||||
const conversationById = $state.conversations.byId[conversationId];
|
||||
if (!conversationById) return;
|
||||
|
||||
conversationById.messages = conversationById.messages.filter(
|
||||
id => id !== messageId
|
||||
);
|
||||
},
|
||||
|
||||
removeMessageId($state, messageId) {
|
||||
if (!messageId) return;
|
||||
|
||||
$state.messages.allIds = $state.messages.allIds.filter(
|
||||
id => id !== messageId
|
||||
);
|
||||
},
|
||||
|
||||
setMessageUIFlag($state, { messageId, uiFlags }) {
|
||||
const flags = $state.messages.uiFlags.byId[messageId];
|
||||
$state.messages.uiFlags.byId[messageId] = {
|
||||
...flags,
|
||||
...uiFlags,
|
||||
};
|
||||
},
|
||||
};
|
|
@ -0,0 +1,380 @@
|
|||
import { mutations } from '../../conversation_new/mutations';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#setUIFlag', () => {
|
||||
it('it sets UI flags correctly', () => {
|
||||
const state = {
|
||||
uiFlags: { allConversationsLoaded: false, isFetching: false },
|
||||
};
|
||||
mutations.setUIFlag(state, { isFetching: true });
|
||||
expect(state.uiFlags).toEqual({
|
||||
allConversationsLoaded: false,
|
||||
isFetching: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#addConversationEntry', () => {
|
||||
it('it creates a conversation in store', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: {},
|
||||
allIds: [],
|
||||
},
|
||||
};
|
||||
mutations.addConversationEntry(state, { id: 420, messages: [] });
|
||||
expect(state.conversations).toEqual({
|
||||
byId: {
|
||||
420: { id: 420, messages: [] },
|
||||
},
|
||||
allIds: [],
|
||||
});
|
||||
});
|
||||
it('it creates conversation with empty messages in store', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 120: { id: 120 } },
|
||||
allIds: [120],
|
||||
},
|
||||
};
|
||||
mutations.addConversationEntry(state, { id: 420, messages: [] });
|
||||
expect(state.conversations.allIds).toEqual([120]);
|
||||
});
|
||||
it('it does not create a conversation if conversation id is missing', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 120: { id: 120 } },
|
||||
allIds: [120],
|
||||
},
|
||||
};
|
||||
mutations.addConversationEntry(state, {});
|
||||
expect(state.conversations.allIds).toEqual([120]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#addConversationId', () => {
|
||||
it('it adds conversation id in store', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: {},
|
||||
allIds: [],
|
||||
},
|
||||
};
|
||||
mutations.addConversationId(state, 420);
|
||||
expect(state.conversations).toEqual({
|
||||
byId: {},
|
||||
allIds: [420],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateConversationEntry', () => {
|
||||
it('it updates an existing conversation in store', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 120: { id: 120, channel: 'email' } },
|
||||
allIds: [120],
|
||||
},
|
||||
};
|
||||
mutations.updateConversationEntry(state, {
|
||||
id: 120,
|
||||
channel: 'facebook',
|
||||
});
|
||||
expect(state.conversations).toEqual({
|
||||
byId: {
|
||||
120: { id: 120, channel: 'facebook' },
|
||||
},
|
||||
allIds: [120],
|
||||
});
|
||||
});
|
||||
it('it does not clears messages in conversation', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 120: { id: 120, channel: 'email', messages: [10] } },
|
||||
allIds: [120],
|
||||
},
|
||||
messages: {
|
||||
byId: {
|
||||
10: {
|
||||
id: 10,
|
||||
content: 'hi',
|
||||
},
|
||||
},
|
||||
allIds: [10],
|
||||
},
|
||||
};
|
||||
mutations.updateConversationEntry(state, {
|
||||
id: 120,
|
||||
channel: 'facebook',
|
||||
});
|
||||
expect(state.messages).toEqual({
|
||||
byId: {
|
||||
10: {
|
||||
id: 10,
|
||||
content: 'hi',
|
||||
},
|
||||
},
|
||||
allIds: [10],
|
||||
});
|
||||
});
|
||||
it('it does not create a new conversation if conversation id is missing', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 120: { id: 120 } },
|
||||
allIds: [120],
|
||||
},
|
||||
};
|
||||
mutations.updateConversationEntry(state, {});
|
||||
expect(state).toEqual({
|
||||
conversations: {
|
||||
byId: { 120: { id: 120 } },
|
||||
allIds: [120],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#removeConversationEntry', () => {
|
||||
it('it removes conversation from store', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 120: { id: 120 } },
|
||||
allIds: [120],
|
||||
},
|
||||
};
|
||||
mutations.removeConversationEntry(state, 120);
|
||||
expect(state).toEqual({
|
||||
conversations: {
|
||||
byId: {},
|
||||
allIds: [120],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#removeConversationId', () => {
|
||||
it('it removes conversation id from store', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 120: { id: 120 } },
|
||||
allIds: [120],
|
||||
},
|
||||
};
|
||||
mutations.removeConversationId(state, 120);
|
||||
expect(state).toEqual({
|
||||
conversations: {
|
||||
byId: { 120: { id: 120 } },
|
||||
allIds: [],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setConversationUIFlag', () => {
|
||||
it('it sets UI flag for conversation correctly', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: {},
|
||||
allIds: [],
|
||||
uiFlags: {
|
||||
byId: {
|
||||
1: {
|
||||
allMessagesLoaded: false,
|
||||
isAgentTyping: false,
|
||||
isFetching: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
mutations.setConversationUIFlag(state, {
|
||||
conversationId: 1,
|
||||
uiFlags: { isFetching: true },
|
||||
});
|
||||
expect(state.conversations.uiFlags.byId[1]).toEqual({
|
||||
allMessagesLoaded: false,
|
||||
isAgentTyping: false,
|
||||
isFetching: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#addMessageIds', () => {
|
||||
it('it adds a list of message ids to existing conversation entry', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 120: { id: 120, messages: [] } },
|
||||
allIds: [120],
|
||||
},
|
||||
messages: { byId: {}, allIds: [] },
|
||||
};
|
||||
const messages = [
|
||||
{ id: 2, content: 'hi' },
|
||||
{ id: 3, content: 'hello' },
|
||||
];
|
||||
mutations.addMessageIds(state, {
|
||||
conversationId: 120,
|
||||
messages,
|
||||
});
|
||||
expect(state.conversations.byId[120].messages).toEqual([2, 3]);
|
||||
});
|
||||
it('it does not clear existing messages in a conversation', () => {});
|
||||
it('new message id is added as last in allIds message in a conversation', () => {});
|
||||
it('it does not add messages if conversation is not present in store', () => {});
|
||||
});
|
||||
|
||||
describe('#addMessageIds', () => {
|
||||
it('it adds a list of message ids to existing conversation entry', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 120: { id: 120, messages: [] } },
|
||||
allIds: [120],
|
||||
},
|
||||
messages: { byId: {}, allIds: [] },
|
||||
};
|
||||
const messages = [
|
||||
{ id: 2, content: 'hi' },
|
||||
{ id: 3, content: 'hello' },
|
||||
];
|
||||
mutations.addMessageIds(state, {
|
||||
conversationId: 120,
|
||||
messages,
|
||||
});
|
||||
expect(state.conversations.byId[120].messages).toEqual([2, 3]);
|
||||
});
|
||||
it('it does not clear existing messages in a conversation', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 120: { id: 120, messages: [2] } },
|
||||
allIds: [120],
|
||||
},
|
||||
messages: { byId: { 2: { id: 2, content: 'hi' } }, allIds: [2] },
|
||||
};
|
||||
const messages = [{ id: 3, content: 'hello' }];
|
||||
mutations.addMessageIds(state, {
|
||||
conversationId: 120,
|
||||
messages,
|
||||
});
|
||||
expect(state.conversations.byId[120].messages).toEqual([2, 3]);
|
||||
});
|
||||
it('it does not add messages if conversation is not present in store', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 12: { id: 12, messages: [2] } },
|
||||
allIds: [12],
|
||||
},
|
||||
messages: { byId: { 2: { id: 2, content: 'hi' } }, allIds: [2] },
|
||||
};
|
||||
const messages = [{ id: 3, content: 'hello' }];
|
||||
mutations.addMessageIds(state, {
|
||||
conversationId: 120,
|
||||
messages,
|
||||
});
|
||||
expect(state.conversations.byId[120]).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateMessageEntry', () => {
|
||||
it('it updates message in conversation correctly', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 12: { id: 12, messages: [2] } },
|
||||
allIds: [12],
|
||||
},
|
||||
messages: { byId: { 2: { id: 2, content: 'hi' } }, allIds: [2] },
|
||||
};
|
||||
const message = { id: 2, content: 'hello' };
|
||||
mutations.updateMessageEntry(state, message);
|
||||
expect(state.messages.byId[2].content).toEqual('hello');
|
||||
});
|
||||
it('it does not create message if message does not exist in conversation', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 12: { id: 12, messages: [2] } },
|
||||
allIds: [12],
|
||||
},
|
||||
messages: { byId: { 2: { id: 2, content: 'hi' } }, allIds: [2] },
|
||||
};
|
||||
const message = { id: 23, content: 'hello' };
|
||||
mutations.updateMessageEntry(state, message);
|
||||
expect(state.messages.byId[23]).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
describe('#removeMessageEntry', () => {
|
||||
it('it deletes message in conversation correctly', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 12: { id: 12, messages: [2] } },
|
||||
allIds: [12],
|
||||
},
|
||||
messages: { byId: { 2: { id: 2, content: 'hi' } }, allIds: [2] },
|
||||
};
|
||||
const messageId = 2;
|
||||
mutations.removeMessageEntry(state, messageId);
|
||||
expect(state.messages.byId[2]).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#removeMessageId', () => {
|
||||
it('it deletes message id in conversation correctly', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 12: { id: 12, messages: [2] } },
|
||||
allIds: [12],
|
||||
},
|
||||
messages: { byId: { 2: { id: 2, content: 'hi' } }, allIds: [2] },
|
||||
};
|
||||
const messageId = 2;
|
||||
mutations.removeMessageId(state, messageId);
|
||||
expect(state.messages.allIds).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#removeMessageIdFromConversation', () => {
|
||||
it('it deletes message id in conversation correctly', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
byId: { 12: { id: 12, messages: [2] } },
|
||||
allIds: [12],
|
||||
},
|
||||
messages: { byId: { 2: { id: 2, content: 'hi' } }, allIds: [2] },
|
||||
};
|
||||
const messageId = 2;
|
||||
const conversationId = 12;
|
||||
mutations.removeMessageIdFromConversation(state, {
|
||||
conversationId,
|
||||
messageId,
|
||||
});
|
||||
expect(state.conversations.byId[12].messages).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setMessageUIFlag', () => {
|
||||
it('it sets UI flag for conversation correctly', () => {
|
||||
const state = {
|
||||
messages: {
|
||||
byId: {},
|
||||
allIds: [],
|
||||
uiFlags: {
|
||||
byId: {
|
||||
1: {
|
||||
isCreating: false,
|
||||
isPending: false,
|
||||
isDeleting: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
mutations.setMessageUIFlag(state, {
|
||||
messageId: 1,
|
||||
uiFlags: { isCreating: true },
|
||||
});
|
||||
expect(state.messages.uiFlags.byId[1]).toEqual({
|
||||
isCreating: true,
|
||||
isPending: false,
|
||||
isDeleting: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue