Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added multi search #601

Merged
merged 22 commits into from
Oct 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/components/UI/SearchBar/SearchBar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ describe('<SearchBar/>', () => {
handleSubmit={mockSubmit}
onReset={mockReset}
searchVal={searchVal}
searchMode={true}
/>
);
};
Expand All @@ -39,6 +40,7 @@ describe('<SearchBar/>', () => {
handleSubmit={mockSubmit}
onReset={mockReset}
searchVal={searchVal}
searchMode={true}
/>
);
wrapper.find(IconButton).simulate('click');
Expand Down
7 changes: 4 additions & 3 deletions src/components/UI/SearchBar/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ export interface SearchBarProps {
className?: any;
handleClick?: any;
endAdornment?: any;
searchMode: boolean;
}

export const SearchBar: React.SFC<SearchBarProps> = (props) => {
const [localSearchValue, setLocalSearchValue] = useState('');

// use local state value so that we can set the defaults correctly
let inputValue: string = '';
if (localSearchValue) {
// local value is needed for list component
let inputValue: string | undefined = props.searchMode ? props.searchVal : '';
if (localSearchValue && props.searchMode) {
inputValue = localSearchValue;
} else {
inputValue = props.searchVal || '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,9 @@
margin-left: 8px;
margin-top: 4px;
}

.TitleText {
font-size: 13px !important;
color: #073f24 !important;
font-weight: bold;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { MARK_AS_READ, MESSAGE_FRAGMENT } from '../../../../graphql/mutations/Ch
import { useApolloClient, useMutation } from '@apollo/client';
import { WhatsAppToJsx } from '../../../../common/RichEditor';
import { Timer } from '../../../../components/UI/Timer/Timer';
import { SEARCH_OFFSET } from '../../../../graphql/queries/Search';

export interface ChatConversationProps {
contactId: number;
Expand All @@ -21,6 +22,7 @@ export interface ChatConversationProps {
onClick: (i: any) => void;
index: number;
lastMessage: {
id: number;
body: string;
insertedAt: string;
type: string;
Expand All @@ -30,6 +32,8 @@ export interface ChatConversationProps {
label: string;
}>;
};
messageNumber?: number;
highlightSearch?: string;
}

const updateMessageCache = (client: any, data: any) => {
Expand All @@ -45,6 +49,7 @@ const updateMessageCache = (client: any, data: any) => {
fragment: MESSAGE_FRAGMENT,
data: messageCopy,
});

return null;
});
};
Expand All @@ -54,8 +59,7 @@ const ChatConversation: React.SFC<ChatConversationProps> = (props) => {
const client = useApolloClient();
let chatInfoClass = [styles.ChatInfo, styles.ChatInfoRead];
let chatBubble = [styles.ChatBubble, styles.ChatBubbleRead];
const { lastMessage, selected, contactId, contactName, index } = props;

const { lastMessage, selected, contactId, contactName, index, highlightSearch } = props;
let unread = false;
const [markAsRead] = useMutation(MARK_AS_READ, {
onCompleted: (mydata) => {
Expand All @@ -74,6 +78,26 @@ const ChatConversation: React.SFC<ChatConversationProps> = (props) => {
}
}

// display highlighted search message
const BoldedText = (text: string, highlight: any) => {
highlight = highlight ? highlight : '';
// Split on highlight term and include term into strings, ignore case
const strings = text.split(new RegExp(`(${highlight})`, 'gi'));
return (
<span>
{strings.map((string, i) =>
string.toLowerCase() === highlight.toLowerCase() ? (
<span key={i} className={styles.TitleText}>
{string}
</span>
) : (
string
)
)}
</span>
);
};

useEffect(() => {
if (unread && selected) {
markAsRead({
Expand All @@ -93,6 +117,16 @@ const ChatConversation: React.SFC<ChatConversationProps> = (props) => {
} else {
message = lastMessage.type;
}
let displayMSG = WhatsAppToJsx(message);

// set offset to use that in chatting window to fetch that msg
const setSearchOffset = (client: any, offset: number = 0) => {
client.writeQuery({
query: SEARCH_OFFSET,
data: { offset },
});
};

return (
<ListItem
data-testid="list"
Expand All @@ -101,8 +135,11 @@ const ChatConversation: React.SFC<ChatConversationProps> = (props) => {
className={clsx(styles.StyledListItem, { [styles.SelectedColor]: selected })}
component={Link}
selected={selected}
onClick={() => props.onClick(index)}
to={'/chat/' + contactId}
onClick={() => {
props.onClick(index);
if (props.messageNumber) setSearchOffset(client, props.messageNumber);
}}
to={'/chat/' + contactId + '/#search' + props.lastMessage.id}
>
<div>
<div className={chatBubble.join(' ')} />
Expand All @@ -119,7 +156,7 @@ const ChatConversation: React.SFC<ChatConversationProps> = (props) => {
{name}
</div>
<div className={styles.MessageContent} data-testid="content">
{WhatsAppToJsx(message)}
{displayMSG[0] ? BoldedText(displayMSG[0], highlightSearch) : null}
</div>
<div className={styles.MessageDate} data-testid="date">
{moment(lastMessage.insertedAt).format(DATE_FORMAT)}
Expand Down
159 changes: 150 additions & 9 deletions src/containers/Chat/ChatConversations/ChatConversations.test.helper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { savedSearchQuery } from '../../../mocks/Chat';
import { SEARCH_QUERY } from '../../../graphql/queries/Search';
import { SEARCH_QUERY, SEARCH_MULTI_QUERY, SEARCH_OFFSET } from '../../../graphql/queries/Search';

const withResult = {
data: {
Expand Down Expand Up @@ -45,7 +45,7 @@ const withResult = {
const noResult = { data: { search: [] } };

const searchQuery = (
messageLimit: number,
messageLimit: object,
contactLimit: number,
filter: any,
showResult: boolean = true
Expand All @@ -55,7 +55,7 @@ const searchQuery = (
query: SEARCH_QUERY,
variables: {
filter: filter,
messageOpts: { limit: messageLimit },
messageOpts: messageLimit,
contactOpts: { limit: contactLimit },
},
},
Expand All @@ -64,17 +64,158 @@ const searchQuery = (
};

export const chatConversationsMocks = [
searchQuery(50, 50, {}),
searchQuery(50, 50, { term: 'a' }, false),
searchQuery(50, 50, { term: '' }),
searchQuery(5, 10, { includeTags: ['12'] }, false),
searchQuery({ limit: 50 }, 50, {}),
searchQuery({ limit: 50 }, 50, { term: 'a' }, false),
searchQuery({ limit: 50 }, 50, { term: '' }),
searchQuery({ limit: 5 }, 10, { includeTags: ['12'] }, false),
searchQuery({ limit: 50 }, 1, {}, false),
searchQuery({ limit: 50, offset: 0 }, 1, { id: '6' }, false),
];

export const searchMultiQuery = (term: string = '', limit: number = 50) => {
return {
request: {
query: SEARCH_MULTI_QUERY,
variables: {
searchFilter: { term: term },
messageOpts: { limit: limit, order: 'ASC' },
contactOpts: { order: 'DESC', limit: limit },
},
},
result: {
data: {
searchMulti: {
contacts: [
{
body: null,
contact: {
bspStatus: 'HSM',
id: '8',
lastMessageAt: '2020-10-15T07:15:33Z',
name: 'Dignesh',
status: 'VALID',
},
id: '66',
insertedAt: '2020-10-15T07:15:33.613260Z',
media: {
caption: null,
url:
'https://filemanager.gupshup.io/fm/wamedia/demobot1/36623b99-5844-4195-b872-61ef34c9ce11',
},
messageNumber: 0,
receiver: {
id: '1',
},
sender: {
id: '8',
},
tags: [
{
colorCode: '#9900ef',
id: '30',
label: 'Default',
},
{
colorCode: '#0C976D',
id: '15',
label: 'Numeric',
},
],
type: 'IMAGE',
},
],
messages: [
{
body: 'Hi',
contact: {
bspStatus: 'HSM',
id: '8',
lastMessageAt: '2020-10-15T07:15:33Z',
name: 'Dignesh',
status: 'VALID',
},
id: '18',
insertedAt: '2020-10-15T06:59:31.473314Z',
media: null,
messageNumber: 48,
receiver: {
id: '1',
},
sender: {
id: '8',
},
tags: [
{
colorCode: '#0C976D',
id: '4',
label: 'Greeting',
},
],
type: 'TEXT',
},
],
tags: [
{
body: 'Hi',
contact: {
bspStatus: 'HSM',
id: '8',
lastMessageAt: '2020-10-15T07:15:33Z',
name: 'Dignesh',
status: 'VALID',
},
id: '12',
insertedAt: '2020-10-15T06:58:34.432894Z',
media: null,
messageNumber: 54,
receiver: {
id: '1',
},
sender: {
id: '8',
},
tags: [
{
colorCode: '#0C976D',
id: '4',
label: 'Greeting',
},
],
type: 'TEXT',
},
],
},
},
},
};
};

export const searchOffset = {
request: {
query: SEARCH_OFFSET,
variables: { offset: 0 },
},
result: {
data: {
offset: 0,
},
},
};

export const SearchConversationsMocks = [
searchMultiQuery(),
searchMultiQuery(),
searchMultiQuery('a'),
];

export const ChatConversationMocks = [
...chatConversationsMocks,
...chatConversationsMocks,
savedSearchQuery,
...SearchConversationsMocks,
...SearchConversationsMocks,
searchOffset,
];

export const searchQueryMock = searchQuery(50, 50, { term: '' });
export const searchQueryEmptyMock = searchQuery(50, 50, {});
export const searchQueryMock = searchQuery({ limit: 50 }, 50, { term: '' });
export const searchQueryEmptyMock = searchQuery({ limit: 50 }, 50, {});
14 changes: 14 additions & 0 deletions src/containers/Chat/ChatConversations/ChatConversations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const ChatConversations: React.SFC<ChatConversationsProps> = (props) => {
const [collectionMethod, setCollectionMethod] = useState('');
const [dialog, setDialogbox] = useState(false);
const [dialogType, setDialogboxType] = useState('');
const [enableSearchMode, setEnableSearchMode] = useState(false);

useEffect(() => {
setSelectedContactId(props.contactId.toString());
Expand All @@ -44,6 +45,12 @@ export const ChatConversations: React.SFC<ChatConversationsProps> = (props) => {
setSearchParam(event.target.param);
}
setSearchVal(event.target.value);

if (Object.keys(searchParam).length === 0) {
setEnableSearchMode(true);
} else {
setEnableSearchMode(false);
}
};

const handleSubmit = (event: any) => {
Expand Down Expand Up @@ -205,6 +212,12 @@ export const ChatConversations: React.SFC<ChatConversationsProps> = (props) => {
<SavedSearchToolbar
savedSearchCriteriaCallback={handlerSavedSearchCriteria}
refetchData={{ savedSearchCollection }}
onSelect={() => {
// on select collection remove search value & disable search mode
setSearchVal('');
if (enableSearchMode) setEnableSearchMode(false);
}}
searchMode={enableSearchMode}
/>
<SearchBar
handleChange={handleChange}
Expand All @@ -213,6 +226,7 @@ export const ChatConversations: React.SFC<ChatConversationsProps> = (props) => {
searchVal={searchVal}
handleClick={handleClick}
endAdornment={true}
searchMode={enableSearchMode}
/>
<ConversationList
searchVal={searchVal}
Expand Down
Loading