Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c78110fe86 | ||
|
|
bf400fb02e | ||
|
|
d06b66319e |
@@ -616,6 +616,8 @@ function updateAssigneeTab(selectedTab) {
|
|||||||
resetBulkActions();
|
resetBulkActions();
|
||||||
emitter.emit('clearSearchInput');
|
emitter.emit('clearSearchInput');
|
||||||
activeAssigneeTab.value = selectedTab;
|
activeAssigneeTab.value = selectedTab;
|
||||||
|
// Set active tab in store for tab-scoped caching
|
||||||
|
store.commit('conversations/SET_ACTIVE_TAB', selectedTab);
|
||||||
if (!currentPage.value) {
|
if (!currentPage.value) {
|
||||||
fetchConversations();
|
fetchConversations();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,13 @@ const getters = {
|
|||||||
getMineChats: (_state, _, __, rootGetters) => activeFilters => {
|
getMineChats: (_state, _, __, rootGetters) => activeFilters => {
|
||||||
const currentUserID = rootGetters.getCurrentUser?.id;
|
const currentUserID = rootGetters.getCurrentUser?.id;
|
||||||
|
|
||||||
return _state.allConversations.filter(conversation => {
|
// Use allConversations if there are applied filters, otherwise use tab cache
|
||||||
|
const hasAppliedFilters = _state.appliedFilters?.length > 0;
|
||||||
|
const conversations = hasAppliedFilters
|
||||||
|
? _state.allConversations
|
||||||
|
: _state.conversationsByTab.me || [];
|
||||||
|
|
||||||
|
return conversations.filter(conversation => {
|
||||||
const { assignee } = conversation.meta;
|
const { assignee } = conversation.meta;
|
||||||
const isAssignedToMe = assignee && assignee.id === currentUserID;
|
const isAssignedToMe = assignee && assignee.id === currentUserID;
|
||||||
const shouldFilter = applyPageFilters(conversation, activeFilters);
|
const shouldFilter = applyPageFilters(conversation, activeFilters);
|
||||||
@@ -96,7 +102,13 @@ const getters = {
|
|||||||
return hasAppliedFilters ? filterQueryGenerator(_state.appliedFilters) : [];
|
return hasAppliedFilters ? filterQueryGenerator(_state.appliedFilters) : [];
|
||||||
},
|
},
|
||||||
getUnAssignedChats: _state => activeFilters => {
|
getUnAssignedChats: _state => activeFilters => {
|
||||||
return _state.allConversations.filter(conversation => {
|
// Use allConversations if there are applied filters, otherwise use tab cache
|
||||||
|
const hasAppliedFilters = _state.appliedFilters?.length > 0;
|
||||||
|
const conversations = hasAppliedFilters
|
||||||
|
? _state.allConversations
|
||||||
|
: _state.conversationsByTab.unassigned || [];
|
||||||
|
|
||||||
|
return conversations.filter(conversation => {
|
||||||
const isUnAssigned = !conversation.meta.assignee;
|
const isUnAssigned = !conversation.meta.assignee;
|
||||||
const shouldFilter = applyPageFilters(conversation, activeFilters);
|
const shouldFilter = applyPageFilters(conversation, activeFilters);
|
||||||
return isUnAssigned && shouldFilter;
|
return isUnAssigned && shouldFilter;
|
||||||
@@ -107,10 +119,16 @@ const getters = {
|
|||||||
const currentUserId = rootGetters.getCurrentUser.id;
|
const currentUserId = rootGetters.getCurrentUser.id;
|
||||||
const currentAccountId = rootGetters.getCurrentAccountId;
|
const currentAccountId = rootGetters.getCurrentAccountId;
|
||||||
|
|
||||||
|
// Use allConversations if there are applied filters, otherwise use tab cache
|
||||||
|
const hasAppliedFilters = _state.appliedFilters?.length > 0;
|
||||||
|
const conversations = hasAppliedFilters
|
||||||
|
? _state.allConversations
|
||||||
|
: _state.conversationsByTab.all || [];
|
||||||
|
|
||||||
const permissions = getUserPermissions(currentUser, currentAccountId);
|
const permissions = getUserPermissions(currentUser, currentAccountId);
|
||||||
const userRole = getUserRole(currentUser, currentAccountId);
|
const userRole = getUserRole(currentUser, currentAccountId);
|
||||||
|
|
||||||
return _state.allConversations.filter(conversation => {
|
return conversations.filter(conversation => {
|
||||||
const shouldFilter = applyPageFilters(conversation, activeFilters);
|
const shouldFilter = applyPageFilters(conversation, activeFilters);
|
||||||
const allowedForRole = applyRoleFilter(
|
const allowedForRole = applyRoleFilter(
|
||||||
conversation,
|
conversation,
|
||||||
|
|||||||
@@ -38,6 +38,14 @@ export const isOnFoldersView = ({ route: { name: routeName } }) => {
|
|||||||
return FOLDER_ROUTES.includes(routeName);
|
return FOLDER_ROUTES.includes(routeName);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getTabFromFilterType = filterType => {
|
||||||
|
if (filterType === 'me') return 'me';
|
||||||
|
if (filterType === 'unassigned') return 'unassigned';
|
||||||
|
if (filterType === 'all') return 'all';
|
||||||
|
// For appliedFilters and other cases, return null to use allConversations
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
export const buildConversationList = (
|
export const buildConversationList = (
|
||||||
context,
|
context,
|
||||||
requestPayload,
|
requestPayload,
|
||||||
@@ -45,7 +53,20 @@ export const buildConversationList = (
|
|||||||
filterType
|
filterType
|
||||||
) => {
|
) => {
|
||||||
const { payload: conversationList, meta: metaData } = responseData;
|
const { payload: conversationList, meta: metaData } = responseData;
|
||||||
context.commit(types.SET_ALL_CONVERSATION, conversationList);
|
const tab = getTabFromFilterType(filterType);
|
||||||
|
|
||||||
|
if (tab) {
|
||||||
|
// Use tab-scoped mutation for basic assignee tabs
|
||||||
|
context.commit(types.SET_TAB_CONVERSATION, {
|
||||||
|
conversations: conversationList,
|
||||||
|
tab,
|
||||||
|
});
|
||||||
|
context.commit(types.SET_ACTIVE_TAB, tab);
|
||||||
|
} else {
|
||||||
|
// Use allConversations for filtered views (appliedFilters, folders, etc.)
|
||||||
|
context.commit(types.SET_ALL_CONVERSATION, conversationList);
|
||||||
|
}
|
||||||
|
|
||||||
context.dispatch('conversationStats/set', metaData);
|
context.dispatch('conversationStats/set', metaData);
|
||||||
context.dispatch(
|
context.dispatch(
|
||||||
'conversationLabels/setBulkConversationLabels',
|
'conversationLabels/setBulkConversationLabels',
|
||||||
|
|||||||
@@ -8,7 +8,13 @@ import { BUS_EVENTS } from '../../../../shared/constants/busEvents';
|
|||||||
import { emitter } from 'shared/helpers/mitt';
|
import { emitter } from 'shared/helpers/mitt';
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
allConversations: [],
|
allConversations: [], // Keep for backward compatibility during migration
|
||||||
|
conversationsByTab: {
|
||||||
|
me: [],
|
||||||
|
unassigned: [],
|
||||||
|
all: [],
|
||||||
|
},
|
||||||
|
activeCacheTab: 'all',
|
||||||
attachments: {},
|
attachments: {},
|
||||||
listLoadingStatus: true,
|
listLoadingStatus: true,
|
||||||
chatStatusFilter: wootConstants.STATUS_TYPE.OPEN,
|
chatStatusFilter: wootConstants.STATUS_TYPE.OPEN,
|
||||||
@@ -54,9 +60,52 @@ export const mutations = {
|
|||||||
});
|
});
|
||||||
_state.allConversations = newAllConversations;
|
_state.allConversations = newAllConversations;
|
||||||
},
|
},
|
||||||
|
[types.SET_TAB_CONVERSATION](_state, { conversations, tab }) {
|
||||||
|
if (!_state.conversationsByTab[tab]) {
|
||||||
|
_state.conversationsByTab[tab] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetCache = [..._state.conversationsByTab[tab]];
|
||||||
|
const newConversations = [];
|
||||||
|
|
||||||
|
conversations.forEach(conversation => {
|
||||||
|
const indexInCache = targetCache.findIndex(c => c.id === conversation.id);
|
||||||
|
if (indexInCache < 0) {
|
||||||
|
newConversations.push(conversation);
|
||||||
|
} else if (conversation.id !== _state.selectedChatId) {
|
||||||
|
targetCache[indexInCache] = conversation;
|
||||||
|
} else {
|
||||||
|
// Preserve messages, attachments, dataFetched, allMessagesLoaded for selected chat
|
||||||
|
const existingConversation = targetCache[indexInCache];
|
||||||
|
targetCache[indexInCache] = {
|
||||||
|
...conversation,
|
||||||
|
allMessagesLoaded: existingConversation.allMessagesLoaded,
|
||||||
|
messages: existingConversation.messages,
|
||||||
|
dataFetched: existingConversation.dataFetched,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Maintain server order by appending new conversations
|
||||||
|
_state.conversationsByTab[tab] = [...targetCache, ...newConversations];
|
||||||
|
},
|
||||||
[types.EMPTY_ALL_CONVERSATION](_state) {
|
[types.EMPTY_ALL_CONVERSATION](_state) {
|
||||||
_state.allConversations = [];
|
_state.allConversations = [];
|
||||||
_state.selectedChatId = null;
|
_state.selectedChatId = null;
|
||||||
|
// Also clear all tab caches so UI renders empty state immediately
|
||||||
|
_state.conversationsByTab = {
|
||||||
|
me: [],
|
||||||
|
unassigned: [],
|
||||||
|
all: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[types.EMPTY_TAB_CONVERSATION](_state, tab) {
|
||||||
|
if (_state.conversationsByTab[tab]) {
|
||||||
|
_state.conversationsByTab[tab] = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[types.SET_ACTIVE_TAB](_state, tab) {
|
||||||
|
_state.activeCacheTab = tab;
|
||||||
},
|
},
|
||||||
[types.SET_ALL_MESSAGES_LOADED](_state) {
|
[types.SET_ALL_MESSAGES_LOADED](_state) {
|
||||||
const [chat] = getSelectedChatConversation(_state);
|
const [chat] = getSelectedChatConversation(_state);
|
||||||
@@ -202,12 +251,38 @@ export const mutations = {
|
|||||||
|
|
||||||
[types.ADD_CONVERSATION](_state, conversation) {
|
[types.ADD_CONVERSATION](_state, conversation) {
|
||||||
_state.allConversations.push(conversation);
|
_state.allConversations.push(conversation);
|
||||||
|
|
||||||
|
// Add to appropriate tab caches based on conversation properties
|
||||||
|
const { meta: { assignee } = {} } = conversation;
|
||||||
|
|
||||||
|
// Add to 'all' tab
|
||||||
|
if (!_state.conversationsByTab.all.find(c => c.id === conversation.id)) {
|
||||||
|
_state.conversationsByTab.all.unshift(conversation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to 'me' or 'unassigned' tab based on assignee
|
||||||
|
if (assignee) {
|
||||||
|
if (!_state.conversationsByTab.me.find(c => c.id === conversation.id)) {
|
||||||
|
_state.conversationsByTab.me.unshift(conversation);
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
!_state.conversationsByTab.unassigned.find(c => c.id === conversation.id)
|
||||||
|
) {
|
||||||
|
_state.conversationsByTab.unassigned.unshift(conversation);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
[types.DELETE_CONVERSATION](_state, conversationId) {
|
[types.DELETE_CONVERSATION](_state, conversationId) {
|
||||||
_state.allConversations = _state.allConversations.filter(
|
_state.allConversations = _state.allConversations.filter(
|
||||||
c => c.id !== conversationId
|
c => c.id !== conversationId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Also remove from all tab caches
|
||||||
|
Object.keys(_state.conversationsByTab).forEach(tab => {
|
||||||
|
_state.conversationsByTab[tab] = _state.conversationsByTab[tab].filter(
|
||||||
|
c => c.id !== conversationId
|
||||||
|
);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
[types.UPDATE_CONVERSATION](_state, conversation) {
|
[types.UPDATE_CONVERSATION](_state, conversation) {
|
||||||
@@ -231,6 +306,28 @@ export const mutations = {
|
|||||||
} else {
|
} else {
|
||||||
_state.allConversations.push(conversation);
|
_state.allConversations.push(conversation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Also update conversation in all tab caches
|
||||||
|
Object.keys(_state.conversationsByTab).forEach(tab => {
|
||||||
|
const tabIndex = _state.conversationsByTab[tab].findIndex(
|
||||||
|
c => c.id === conversation.id
|
||||||
|
);
|
||||||
|
if (tabIndex > -1) {
|
||||||
|
const selectedTabConversation =
|
||||||
|
_state.conversationsByTab[tab][tabIndex];
|
||||||
|
|
||||||
|
// ignore out of order events
|
||||||
|
if (conversation.updated_at < selectedTabConversation.updated_at) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { messages, ...updates } = conversation;
|
||||||
|
_state.conversationsByTab[tab][tabIndex] = {
|
||||||
|
...selectedTabConversation,
|
||||||
|
...updates,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
[types.SET_LIST_LOADING_STATUS](_state) {
|
[types.SET_LIST_LOADING_STATUS](_state) {
|
||||||
@@ -253,10 +350,22 @@ export const mutations = {
|
|||||||
},
|
},
|
||||||
[types.CHANGE_CHAT_STATUS_FILTER](_state, data) {
|
[types.CHANGE_CHAT_STATUS_FILTER](_state, data) {
|
||||||
_state.chatStatusFilter = data;
|
_state.chatStatusFilter = data;
|
||||||
|
// Clear all tab caches since status filter is global
|
||||||
|
_state.conversationsByTab = {
|
||||||
|
me: [],
|
||||||
|
unassigned: [],
|
||||||
|
all: [],
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
[types.CHANGE_CHAT_SORT_FILTER](_state, data) {
|
[types.CHANGE_CHAT_SORT_FILTER](_state, data) {
|
||||||
_state.chatSortFilter = data;
|
_state.chatSortFilter = data;
|
||||||
|
// Clear all tab caches since sort filter is global
|
||||||
|
_state.conversationsByTab = {
|
||||||
|
me: [],
|
||||||
|
unassigned: [],
|
||||||
|
all: [],
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
// Update assignee on action cable message
|
// Update assignee on action cable message
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ export default {
|
|||||||
// Chat List
|
// Chat List
|
||||||
RECEIVE_CHAT_LIST: 'RECEIVE_CHAT_LIST',
|
RECEIVE_CHAT_LIST: 'RECEIVE_CHAT_LIST',
|
||||||
SET_ALL_CONVERSATION: 'SET_ALL_CONVERSATION',
|
SET_ALL_CONVERSATION: 'SET_ALL_CONVERSATION',
|
||||||
|
SET_TAB_CONVERSATION: 'SET_TAB_CONVERSATION',
|
||||||
EMPTY_ALL_CONVERSATION: 'EMPTY_ALL_CONVERSATION',
|
EMPTY_ALL_CONVERSATION: 'EMPTY_ALL_CONVERSATION',
|
||||||
|
EMPTY_TAB_CONVERSATION: 'EMPTY_TAB_CONVERSATION',
|
||||||
|
SET_ACTIVE_TAB: 'SET_ACTIVE_TAB',
|
||||||
SET_CONV_TAB_META: 'SET_CONV_TAB_META',
|
SET_CONV_TAB_META: 'SET_CONV_TAB_META',
|
||||||
CLEAR_LIST_LOADING_STATUS: 'CLEAR_LIST_LOADING_STATUS',
|
CLEAR_LIST_LOADING_STATUS: 'CLEAR_LIST_LOADING_STATUS',
|
||||||
SET_LIST_LOADING_STATUS: 'SET_LIST_LOADING_STATUS',
|
SET_LIST_LOADING_STATUS: 'SET_LIST_LOADING_STATUS',
|
||||||
|
|||||||
Reference in New Issue
Block a user