fix(frontend): stop offline conversation request loop
This commit is contained in:
@@ -97,6 +97,7 @@ const allChatList = useMapGetter('getAllStatusChats');
|
||||
const unAssignedChatsList = useMapGetter('getUnAssignedChats');
|
||||
const participatingChatsList = useMapGetter('getParticipatingChats');
|
||||
const chatListLoading = useMapGetter('getChatListLoadingStatus');
|
||||
const chatListError = useMapGetter('getChatListErrorStatus');
|
||||
const activeInbox = useMapGetter('getSelectedInbox');
|
||||
const conversationStats = useMapGetter('conversationStats/getStats');
|
||||
const appliedFilters = useMapGetter('getAppliedConversationFiltersV2');
|
||||
@@ -915,7 +916,13 @@ watch(chatLists, () => {
|
||||
/>
|
||||
|
||||
<p
|
||||
v-if="!chatListLoading && !conversationList.length"
|
||||
v-if="chatListError"
|
||||
class="flex overflow-auto justify-center items-center p-4 text-n-slate-11"
|
||||
>
|
||||
{{ $t('CHAT_LIST.LIST.ERROR') }}
|
||||
</p>
|
||||
<p
|
||||
v-else-if="!chatListLoading && !conversationList.length"
|
||||
class="flex overflow-auto justify-center items-center p-4"
|
||||
>
|
||||
{{ $t('CHAT_LIST.LIST.404') }}
|
||||
@@ -933,6 +940,7 @@ watch(chatLists, () => {
|
||||
<ConversationList
|
||||
:conversation-list="conversationList"
|
||||
:is-loading="chatListLoading"
|
||||
:has-error="chatListError"
|
||||
:show-end-of-list-message="showEndOfListMessage"
|
||||
:label="label"
|
||||
:team-id="teamId"
|
||||
|
||||
@@ -12,6 +12,7 @@ import wootConstants from 'dashboard/constants/globals';
|
||||
const props = defineProps({
|
||||
conversationList: { type: Array, default: () => [] },
|
||||
isLoading: { type: Boolean, default: false },
|
||||
hasError: { type: Boolean, default: false },
|
||||
showEndOfListMessage: { type: Boolean, default: false },
|
||||
label: { type: String, default: '' },
|
||||
teamId: { type: [String, Number], default: 0 },
|
||||
@@ -86,7 +87,7 @@ defineExpose({ conversationListRef });
|
||||
{{ $t('CHAT_LIST.EOF') }}
|
||||
</p>
|
||||
<IntersectionObserver
|
||||
v-else
|
||||
v-else-if="!hasError"
|
||||
:options="intersectionObserverOptions"
|
||||
@observed="loadMoreConversations"
|
||||
/>
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"LOAD_MORE_CONVERSATIONS": "Load more conversations",
|
||||
"EOF": "All conversations loaded 🎉",
|
||||
"LIST": {
|
||||
"404": "There are no active conversations in this group."
|
||||
"404": "There are no active conversations in this group.",
|
||||
"ERROR": "Unable to load conversations. Waiting for the server to reconnect."
|
||||
},
|
||||
"FAILED_TO_SEND": "Failed to send",
|
||||
"TAB_HEADING": "Conversations",
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"LOAD_MORE_CONVERSATIONS": "加载更多对话",
|
||||
"EOF": "所有对话已加载 🎉",
|
||||
"LIST": {
|
||||
"404": "没有有效的对话在这个群组里面"
|
||||
"404": "没有有效的对话在这个群组里面",
|
||||
"ERROR": "无法加载会话,正在等待服务器重新连接。"
|
||||
},
|
||||
"FAILED_TO_SEND": "发送失败",
|
||||
"TAB_HEADING": "会话",
|
||||
|
||||
@@ -44,6 +44,7 @@ const actions = {
|
||||
},
|
||||
|
||||
fetchAllConversations: async ({ commit, state, dispatch }, explicitFilters) => {
|
||||
commit(types.CLEAR_LIST_ERROR_STATUS);
|
||||
commit(types.SET_LIST_LOADING_STATUS);
|
||||
try {
|
||||
const params = explicitFilters || state.conversationFilters;
|
||||
@@ -56,12 +57,19 @@ const actions = {
|
||||
data,
|
||||
params.assigneeType
|
||||
);
|
||||
commit(types.CLEAR_LIST_ERROR_STATUS);
|
||||
} catch (error) {
|
||||
// Handle error
|
||||
// Stop the infinite-scroll observer from immediately retrying a failed
|
||||
// page while the backend is unavailable. Reconnect/manual fetches clear
|
||||
// this flag before trying again.
|
||||
commit(types.SET_LIST_ERROR_STATUS);
|
||||
} finally {
|
||||
commit(types.CLEAR_LIST_LOADING_STATUS);
|
||||
}
|
||||
},
|
||||
|
||||
fetchFilteredConversations: async ({ commit, dispatch }, params) => {
|
||||
commit(types.CLEAR_LIST_ERROR_STATUS);
|
||||
commit(types.SET_LIST_LOADING_STATUS);
|
||||
try {
|
||||
const { data } = await ConversationApi.filter(params);
|
||||
@@ -71,8 +79,11 @@ const actions = {
|
||||
data,
|
||||
'appliedFilters'
|
||||
);
|
||||
commit(types.CLEAR_LIST_ERROR_STATUS);
|
||||
} catch (error) {
|
||||
// Handle error
|
||||
commit(types.SET_LIST_ERROR_STATUS);
|
||||
} finally {
|
||||
commit(types.CLEAR_LIST_LOADING_STATUS);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -138,6 +138,7 @@ const getters = {
|
||||
});
|
||||
},
|
||||
getChatListLoadingStatus: ({ listLoadingStatus }) => listLoadingStatus,
|
||||
getChatListErrorStatus: ({ listErrorStatus }) => listErrorStatus,
|
||||
getAllMessagesLoaded(_state) {
|
||||
const [chat] = getSelectedChatConversation(_state);
|
||||
return !chat || chat.allMessagesLoaded === undefined
|
||||
|
||||
@@ -12,6 +12,7 @@ const state = {
|
||||
allConversations: [],
|
||||
attachments: {},
|
||||
listLoadingStatus: true,
|
||||
listErrorStatus: false,
|
||||
chatStatusFilter: wootConstants.STATUS_TYPE.OPEN,
|
||||
chatSortFilter: wootConstants.SORT_BY_TYPE.LATEST,
|
||||
currentInbox: null,
|
||||
@@ -274,6 +275,14 @@ export const mutations = {
|
||||
_state.listLoadingStatus = false;
|
||||
},
|
||||
|
||||
[types.SET_LIST_ERROR_STATUS](_state) {
|
||||
_state.listErrorStatus = true;
|
||||
},
|
||||
|
||||
[types.CLEAR_LIST_ERROR_STATUS](_state) {
|
||||
_state.listErrorStatus = false;
|
||||
},
|
||||
|
||||
[types.UPDATE_MESSAGE_UNREAD_COUNT](
|
||||
_state,
|
||||
{ id, lastSeen, unreadCount = 0 }
|
||||
|
||||
+92
-6
@@ -431,15 +431,101 @@ describe('#actions', () => {
|
||||
});
|
||||
|
||||
describe('#fetchFilteredConversations', () => {
|
||||
it('fetches filtered conversations with a mock commit', async () => {
|
||||
it('fetches filtered conversations and clears the loading state', async () => {
|
||||
const localCommit = vi.fn();
|
||||
const localDispatch = vi.fn();
|
||||
axios.post.mockResolvedValue({
|
||||
data: dataReceived,
|
||||
});
|
||||
await actions.fetchFilteredConversations({ commit }, dataToSend);
|
||||
expect(commit).toHaveBeenCalledTimes(2);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['SET_LIST_LOADING_STATUS'],
|
||||
['SET_ALL_CONVERSATION', dataReceived.payload],
|
||||
await actions.fetchFilteredConversations(
|
||||
{ commit: localCommit, dispatch: localDispatch },
|
||||
dataToSend
|
||||
);
|
||||
expect(localCommit.mock.calls).toEqual([
|
||||
[types.CLEAR_LIST_ERROR_STATUS],
|
||||
[types.SET_LIST_LOADING_STATUS],
|
||||
[types.SET_ALL_CONVERSATION, dataReceived.payload],
|
||||
[
|
||||
`contacts/${types.SET_CONTACTS}`,
|
||||
dataReceived.payload.map(conversation => conversation.meta.sender),
|
||||
],
|
||||
[types.CLEAR_LIST_ERROR_STATUS],
|
||||
[types.CLEAR_LIST_LOADING_STATUS],
|
||||
]);
|
||||
expect(localDispatch).toHaveBeenCalledWith(
|
||||
'conversationStats/set',
|
||||
dataReceived.meta
|
||||
);
|
||||
});
|
||||
|
||||
it('clears the loading state when the API request fails', async () => {
|
||||
const localCommit = vi.fn();
|
||||
axios.post.mockRejectedValue(new Error('Request failed'));
|
||||
|
||||
await actions.fetchFilteredConversations(
|
||||
{ commit: localCommit, dispatch: vi.fn() },
|
||||
dataToSend
|
||||
);
|
||||
|
||||
expect(localCommit.mock.calls).toEqual([
|
||||
[types.CLEAR_LIST_ERROR_STATUS],
|
||||
[types.SET_LIST_LOADING_STATUS],
|
||||
[types.SET_LIST_ERROR_STATUS],
|
||||
[types.CLEAR_LIST_LOADING_STATUS],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#fetchAllConversations', () => {
|
||||
it('fetches conversations and clears the loading state', async () => {
|
||||
const localCommit = vi.fn();
|
||||
const localDispatch = vi.fn();
|
||||
const filters = {
|
||||
inboxId: 4,
|
||||
status: 'open',
|
||||
assigneeType: 'all',
|
||||
page: 1,
|
||||
};
|
||||
axios.get.mockResolvedValue({ data: { data: dataReceived } });
|
||||
|
||||
await actions.fetchAllConversations({
|
||||
commit: localCommit,
|
||||
dispatch: localDispatch,
|
||||
state: { conversationFilters: filters },
|
||||
});
|
||||
|
||||
expect(localCommit.mock.calls).toEqual([
|
||||
[types.CLEAR_LIST_ERROR_STATUS],
|
||||
[types.SET_LIST_LOADING_STATUS],
|
||||
[types.SET_ALL_CONVERSATION, dataReceived.payload],
|
||||
[
|
||||
`contacts/${types.SET_CONTACTS}`,
|
||||
dataReceived.payload.map(conversation => conversation.meta.sender),
|
||||
],
|
||||
[types.CLEAR_LIST_ERROR_STATUS],
|
||||
[types.CLEAR_LIST_LOADING_STATUS],
|
||||
]);
|
||||
expect(localDispatch).toHaveBeenCalledWith(
|
||||
'conversationStats/set',
|
||||
dataReceived.meta
|
||||
);
|
||||
});
|
||||
|
||||
it('clears the loading state when the API request fails', async () => {
|
||||
const localCommit = vi.fn();
|
||||
axios.get.mockRejectedValue(new Error('Request failed'));
|
||||
|
||||
await actions.fetchAllConversations({
|
||||
commit: localCommit,
|
||||
dispatch: vi.fn(),
|
||||
state: { conversationFilters: {} },
|
||||
});
|
||||
|
||||
expect(localCommit.mock.calls).toEqual([
|
||||
[types.CLEAR_LIST_ERROR_STATUS],
|
||||
[types.SET_LIST_LOADING_STATUS],
|
||||
[types.SET_LIST_ERROR_STATUS],
|
||||
[types.CLEAR_LIST_LOADING_STATUS],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1066,6 +1066,26 @@ describe('#mutations', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_LIST_ERROR_STATUS', () => {
|
||||
it('marks the conversation list request as failed', () => {
|
||||
const state = { listErrorStatus: false };
|
||||
|
||||
mutations[types.SET_LIST_ERROR_STATUS](state);
|
||||
|
||||
expect(state.listErrorStatus).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CLEAR_LIST_ERROR_STATUS', () => {
|
||||
it('clears the conversation list request error', () => {
|
||||
const state = { listErrorStatus: true };
|
||||
|
||||
mutations[types.CLEAR_LIST_ERROR_STATUS](state);
|
||||
|
||||
expect(state.listErrorStatus).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CHANGE_CHAT_STATUS_FILTER', () => {
|
||||
it('should update chat status filter', () => {
|
||||
const state = {
|
||||
|
||||
@@ -15,6 +15,8 @@ export default {
|
||||
SET_CONV_TAB_META: 'SET_CONV_TAB_META',
|
||||
CLEAR_LIST_LOADING_STATUS: 'CLEAR_LIST_LOADING_STATUS',
|
||||
SET_LIST_LOADING_STATUS: 'SET_LIST_LOADING_STATUS',
|
||||
CLEAR_LIST_ERROR_STATUS: 'CLEAR_LIST_ERROR_STATUS',
|
||||
SET_LIST_ERROR_STATUS: 'SET_LIST_ERROR_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',
|
||||
|
||||
Reference in New Issue
Block a user