When the chat is viewed, a function `fetchAllAttachments` is run to get all attachments for a particular conversation. This function, before updating the record creates the `attachments` property on the `chat` object in the store. If in any case this function fails, the `attachments` property is not created, and when the code reaches the `dashboard/store/modules/conversations/index.js` the error occurs This PR fixes it by ensuring that `SET_ALL_ATTACHMENTS` is always run. And it handles the default case as well --- Sentry Issue: [CHATWOOT-FRONTEND-APP-5Y](https://chatwoot-p3.sentry.io/issues/5459056982/) ``` TypeError: Cannot read properties of undefined (reading 'some') at forEach(./app/javascript/dashboard/store/modules/conversations/index.js:160:31) at Array.forEach(<anonymous>) at mutations(./app/javascript/dashboard/store/modules/conversations/index.js:159:27) at handler(./node_modules/vuex/dist/vuex.js:771:7) at forEach(./node_modules/vuex/dist/vuex.js:470:9) at Array.forEach(<anonymous>) at fn(./node_modules/vuex/dist/vuex.js:469:13) at Store.prototype._withCommit(./node_modules/vuex/dist/vuex.js:574:5) at Store.prototype.commit(./node_modules/vuex/dist/vuex.js:468:10) at this.commit(./node_modules/vuex/dist/vuex.js:420:21) at call(./app/javascript/dashboard/store/modules/conversations/actions.js:273:7) at tryCatch(./node_modules/videojs-record/dist/videojs.record.js:2868:27) at _invoke(./node_modules/videojs-record/dist/videojs.record.js:3088:32) at prototype[method](./node_modules/videojs-record/dist/videojs.record.js:2921:31) at as(/packs/js/application-cf716bca3c984faeb095.js:4:76) at as(/packs/js/application-cf716bca3c984faeb095.js:4:76) at nrWrapper(/app/accounts/81898/conversations/95:6:17817) ``` --------- Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Co-authored-by: Sojan Jose <sojan@pepalo.com> Co-authored-by: Pranav <pranav@chatwoot.com>
115 lines
4.0 KiB
JavaScript
115 lines
4.0 KiB
JavaScript
import { MESSAGE_TYPE } from 'shared/constants/messages';
|
|
import { applyPageFilters, sortComparator } from './helpers';
|
|
import filterQueryGenerator from 'dashboard/helper/filterQueryGenerator';
|
|
|
|
export const getSelectedChatConversation = ({
|
|
allConversations,
|
|
selectedChatId,
|
|
}) =>
|
|
allConversations.filter(conversation => conversation.id === selectedChatId);
|
|
|
|
const getters = {
|
|
getAllConversations: ({ allConversations, chatSortFilter: sortKey }) => {
|
|
return allConversations.sort((a, b) => sortComparator(a, b, sortKey));
|
|
},
|
|
getSelectedChat: ({ selectedChatId, allConversations }) => {
|
|
const selectedChat = allConversations.find(
|
|
conversation => conversation.id === selectedChatId
|
|
);
|
|
return selectedChat || {};
|
|
},
|
|
getSelectedChatAttachments: ({ selectedChatId, attachments }) => {
|
|
return attachments[selectedChatId] || [];
|
|
},
|
|
getChatListFilters: ({ conversationFilters }) => conversationFilters,
|
|
getLastEmailInSelectedChat: (stage, _getters) => {
|
|
const selectedChat = _getters.getSelectedChat;
|
|
const { messages = [] } = selectedChat;
|
|
const lastEmail = [...messages].reverse().find(message => {
|
|
const {
|
|
content_attributes: contentAttributes = {},
|
|
message_type: messageType,
|
|
} = message;
|
|
const { email = {} } = contentAttributes;
|
|
const isIncomingOrOutgoing =
|
|
messageType === MESSAGE_TYPE.OUTGOING ||
|
|
messageType === MESSAGE_TYPE.INCOMING;
|
|
if (email.from && isIncomingOrOutgoing) {
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
return lastEmail;
|
|
},
|
|
getMineChats: (_state, _, __, rootGetters) => activeFilters => {
|
|
const currentUserID = rootGetters.getCurrentUser?.id;
|
|
|
|
return _state.allConversations.filter(conversation => {
|
|
const { assignee } = conversation.meta;
|
|
const isAssignedToMe = assignee && assignee.id === currentUserID;
|
|
const shouldFilter = applyPageFilters(conversation, activeFilters);
|
|
const isChatMine = isAssignedToMe && shouldFilter;
|
|
|
|
return isChatMine;
|
|
});
|
|
},
|
|
getAppliedConversationFilters: _state => {
|
|
return _state.appliedFilters;
|
|
},
|
|
getAppliedConversationFiltersQuery: _state => {
|
|
const hasAppliedFilters = _state.appliedFilters.length !== 0;
|
|
return hasAppliedFilters ? filterQueryGenerator(_state.appliedFilters) : [];
|
|
},
|
|
getUnAssignedChats: _state => activeFilters => {
|
|
return _state.allConversations.filter(conversation => {
|
|
const isUnAssigned = !conversation.meta.assignee;
|
|
const shouldFilter = applyPageFilters(conversation, activeFilters);
|
|
return isUnAssigned && shouldFilter;
|
|
});
|
|
},
|
|
getAllStatusChats: _state => activeFilters => {
|
|
return _state.allConversations.filter(conversation => {
|
|
const shouldFilter = applyPageFilters(conversation, activeFilters);
|
|
return shouldFilter;
|
|
});
|
|
},
|
|
getChatListLoadingStatus: ({ listLoadingStatus }) => listLoadingStatus,
|
|
getAllMessagesLoaded(_state) {
|
|
const [chat] = getSelectedChatConversation(_state);
|
|
return !chat || chat.allMessagesLoaded === undefined
|
|
? false
|
|
: chat.allMessagesLoaded;
|
|
},
|
|
getUnreadCount(_state) {
|
|
const [chat] = getSelectedChatConversation(_state);
|
|
if (!chat) return [];
|
|
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,
|
|
getChatSortFilter: ({ chatSortFilter }) => chatSortFilter,
|
|
getSelectedInbox: ({ currentInbox }) => currentInbox,
|
|
getConversationById: _state => conversationId => {
|
|
return _state.allConversations.find(
|
|
value => value.id === Number(conversationId)
|
|
);
|
|
},
|
|
getConversationParticipants: _state => {
|
|
return _state.conversationParticipants;
|
|
},
|
|
getConversationLastSeen: _state => {
|
|
return _state.conversationLastSeen;
|
|
},
|
|
|
|
getContextMenuChatId: _state => {
|
|
return _state.contextMenuChatId;
|
|
},
|
|
};
|
|
|
|
export default getters;
|