Skip to content

Commit

Permalink
fix: message list view
Browse files Browse the repository at this point in the history
  • Loading branch information
nubsthead committed Mar 9, 2022
1 parent 9e53272 commit 17c41e3
Show file tree
Hide file tree
Showing 19 changed files with 268 additions and 267 deletions.
8 changes: 4 additions & 4 deletions src/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import {
addBoardView,
registerActions,
registerFunctions,
setAppContext,
ACTION_TYPES,
getBridgedFunctions
getBridgedFunctions,
useUserSettings
} from '@zextras/carbonio-shell-ui';
import { some } from 'lodash';
import { useTranslation } from 'react-i18next';
Expand Down Expand Up @@ -72,6 +72,7 @@ const SidebarView = (props) => (

const App = () => {
const [t] = useTranslation();
const { zimbraPrefGroupMailBy } = useUserSettings().prefs;
useEffect(() => {
addRoute({
route: MAILS_ROUTE,
Expand All @@ -95,8 +96,7 @@ const App = () => {
route: MAILS_ROUTE,
component: EditView
});
setAppContext({ isMessageView: false });
}, [t]);
}, [t, zimbraPrefGroupMailBy]);

useEffect(() => {
registerActions(
Expand Down
10 changes: 3 additions & 7 deletions src/hooks/use-conversation-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,8 @@ import { useEffect, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
import { useUserSettings } from '@zextras/carbonio-shell-ui';
import { fetchConversations } from '../store/actions';
import {
selectConversationsArray,
selectCurrentFolder,
selectFolderSearchStatus
} from '../store/conversations-slice';
import { search } from '../store/actions';
import { selectConversationsArray, selectFolderSearchStatus } from '../store/conversations-slice';
import { Conversation } from '../types/conversation';
import { StateType } from '../types/state';
import { selectFolders } from '../store/folders-slice';
Expand All @@ -37,7 +33,7 @@ export const useConversationListItems = (): Array<Conversation> => {
// todo: to fix this error the dispatcher in shell must be fixed
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
dispatch(fetchConversations({ folderId, limit: 101, sortBy })).then(() => {
dispatch(search({ folderId, limit: 101, sortBy })).then(() => {
setIsLoading(false);
});
}
Expand Down
68 changes: 14 additions & 54 deletions src/hooks/use-message-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,82 +3,42 @@
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { find, reduce, some, uniqBy } from 'lodash';
import { filter } from 'lodash';
import { useEffect, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
import { fetchConversations } from '../store/actions';
import { selectConversationsArray, selectFolderSearchStatus } from '../store/conversations-slice';
import { Conversation } from '../types/conversation';
import { search } from '../store/actions';
import { MailMessage } from '../types/mail-message';
import { StateType } from '../types/state';
import { selectFolders } from '../store/folders-slice';
import { selectMessages } from '../store/messages-slice';
import { selectFolderMsgSearchStatus, selectMessagesArray } from '../store/messages-slice';

type RouteParams = {
folderId: string;
};

export const useMessageList = (): Array<Conversation> => {
export const useMessageList = (): Array<Partial<MailMessage>> => {
const [isLoading, setIsLoading] = useState(false);
const { folderId } = <RouteParams>useParams();
const folderStatus = useSelector((state) => selectFolderSearchStatus(<StateType>state, folderId));
const conversations = useSelector(selectConversationsArray);
const folderMsgStatus = useSelector((state) =>
selectFolderMsgSearchStatus(<StateType>state, folderId)
);
const messages = useSelector(selectMessagesArray);

const dispatch = useDispatch();
const allFolders = useSelector(selectFolders);

useEffect(() => {
if (folderStatus !== 'complete' && !isLoading) {
if (folderMsgStatus !== 'complete' && !isLoading) {
setIsLoading(true);
// todo: to fix this error the dispatcher in shell must be fixed
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
dispatch(fetchConversations({ folderId, limit: 101 })).then(() => {
dispatch(search({ folderId, limit: 101, types: 'message' })).then(() => {
setIsLoading(false);
});
}
}, [dispatch, folderId, folderStatus, isLoading]);
const messages = useSelector(selectMessages);
}, [dispatch, folderId, folderMsgStatus, isLoading]);

return useMemo(() => {
let currentFolderId = folderId;
const currentFolder = allFolders[folderId];
if (!!currentFolder && currentFolder.rid) {
currentFolderId = `${currentFolder.zid}:${currentFolder.rid}`;
}

const reducedConversations = reduce(
conversations,
(acc2, v2) => (some(v2.messages, ['parent', currentFolderId]) ? [...acc2, v2] : acc2),
[] as Array<Conversation>
);

const messageList = reduce(
reducedConversations,
(accumulator, item) => [
...accumulator,
...uniqBy(
reduce(
item.messages,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
(acc, v) => {
const msg = find(messages, ['id', v.id]);
if (msg) {
if (folderId === msg.parent) {
return [...acc, { ...msg, convId: item.id }];
}
}
return acc;
},
[]
),
'id'
)
],
[]
);
const currentList = useMemo(() => filter(messages, ['parent', folderId]), [folderId, messages]);

return messageList;
}, [folderId, allFolders, conversations, messages]);
return currentList;
};
75 changes: 0 additions & 75 deletions src/store/actions/fetch-conversations.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/store/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
export * from './conv-action';
export * from './fetch-conversations';
export * from './search';
export * from './get-conv';
export * from './get-msg';
export * from './msg-action';
Expand Down
96 changes: 96 additions & 0 deletions src/store/actions/search.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* SPDX-FileCopyrightText: 2021 Zextras <https://www.zextras.com>
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
/* eslint no-param-reassign: ["error", { "props": true, "ignorePropertyModificationsFor": ["conversation"] }] */

import { createAsyncThunk } from '@reduxjs/toolkit';
import { soapFetch } from '@zextras/carbonio-shell-ui';
import { keyBy, map, reduce } from 'lodash';
import { normalizeConversation } from '../../normalizations/normalize-conversation';
import { normalizeMailMessageFromSoap } from '../../normalizations/normalize-message';
import { IncompleteMessage } from '../../types/mail-message';
import { Conversation } from '../../types/conversation';
import { SearchRequest, SearchResponse } from '../../types/soap/';

export type FetchConversationsParameters = {
folderId: string;
limit: number;
before?: Date;
types?: string;
sortBy: 'dateDesc' | 'dateAsc';
};

export type FetchConversationsReturn =
| {
conversations?: Record<string, Conversation>;
messages?: Record<string, IncompleteMessage>;
hasMore: boolean;
types: string;
}
| undefined;

export const search = createAsyncThunk<FetchConversationsReturn, FetchConversationsParameters>(
'fetchConversations',
async ({ folderId, limit = 100, before, types = 'conversation', sortBy = 'dateDesc' }) => {
const queryPart = [`inId:${folderId}`];
if (before) queryPart.push(`before:${before.getTime()}`);
const result = (await soapFetch<SearchRequest, SearchResponse>('Search', {
_jsns: 'urn:zimbraMail',
limit,
needExp: 1,
types,
recip: '2',
fullConversation: 1,
wantContent: 'full',
sortBy,
query: queryPart.join(' ')
})) as SearchResponse;

if (types === 'conversation' && result.c) {
const conversations = map(result?.c ?? [], (obj) =>
normalizeConversation(obj)
) as unknown as Array<Conversation>;
const messages = reduce(
result?.c ?? [],
(acc, v) =>
v?.m?.length > 0
? [
...acc,
...map(v.m, (m) =>
normalizeMailMessageFromSoap(
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
{ ...m, d: m.d ? Number(m.d) : undefined, s: m.s ? Number(m.s) : undefined },
false
)
)
]
: acc,
[] as Array<IncompleteMessage>
);
return {
conversations: keyBy(conversations, 'id'),
messages: keyBy(messages, 'id'),
hasMore: result.more,
types
};
}
if (types === 'message' && result.m) {
return {
messages: reduce(
result.m ?? [],
(acc, msg) => {
const normalized = normalizeMailMessageFromSoap(msg, false);
return { ...acc, [normalized.id]: normalized };
},
{}
),
hasMore: result.more,
types
};
}
return undefined;
}
);
22 changes: 12 additions & 10 deletions src/store/conversations-slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
convAction,
ConvActionParameters,
ConvActionResult,
fetchConversations,
search,
FetchConversationsReturn,
getConv,
searchConv
Expand All @@ -40,12 +40,14 @@ function fetchConversationsFulfilled(
state: ConversationsStateType,
{ payload, meta }: { payload: FetchConversationsReturn; meta: any }
): void {
state.conversations = { ...state.conversations, ...payload.conversations };
state.status = payload.hasMore ? 'hasMore' : 'complete';
state.searchedInFolder = {
...state.searchedInFolder,
[meta.arg.folderId]: 'complete'
};
if (payload?.types === 'conversation' && payload?.conversations) {
state.conversations = { ...state.conversations, ...payload.conversations };
state.searchedInFolder = {
...state.searchedInFolder,
[meta.arg.folderId]: 'complete'
};
}
state.status = payload?.hasMore ? 'hasMore' : 'complete';
}

function fetchConversationsRejected(state: ConversationsStateType): void {
Expand Down Expand Up @@ -189,9 +191,9 @@ export const conversationsSlice = createSlice({
setSearchedInFolder: produce(setSearchedInFolderReducer)
},
extraReducers: (builder) => {
builder.addCase(fetchConversations.pending, produce(fetchConversationsPending));
builder.addCase(fetchConversations.fulfilled, produce(fetchConversationsFulfilled));
builder.addCase(fetchConversations.rejected, produce(fetchConversationsRejected));
builder.addCase(search.pending, produce(fetchConversationsPending));
builder.addCase(search.fulfilled, produce(fetchConversationsFulfilled));
builder.addCase(search.rejected, produce(fetchConversationsRejected));
builder.addCase(searchConv.pending, produce(searchConvPending));
builder.addCase(searchConv.fulfilled, produce(searchConvFulfilled));
builder.addCase(searchConv.rejected, produce(searchConvRejected));
Expand Down
Loading

0 comments on commit 17c41e3

Please sign in to comment.