Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
78 changes: 72 additions & 6 deletions plugin-hrm-form/src/components/search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

/* eslint-disable react/prop-types */
/* eslint-disable react/no-multi-comp */
import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import React, { useState, useEffect, useRef } from 'react';
import { connect, useSelector } from 'react-redux';
import { bindActionCreators } from 'redux';
import Dialog from '@material-ui/core/Dialog';
import DialogContent from '@material-ui/core/DialogContent';
Expand All @@ -28,8 +28,16 @@ import ContactDetails from '../contact/ContactDetails';
import Case from '../case';
import ProfileRouter, { isProfileRoute } from '../profile/ProfileRouter';
import { SearchParams } from '../../states/search/types';
import selectSearchStateForTask from '../../states/search/selectSearchStateForTask';
import { CustomITask } from '../../types/types';
import { newCreateSearchForm, handleSearchFormChange, searchCases, searchContacts } from '../../states/search/actions';
import {
newCreateSearchForm,
handleSearchFormChange,
searchCases,
searchContacts,
searchV2Contacts,
searchContactsByIds,
} from '../../states/search/actions';
import { RootState } from '../../states';
import { namespace } from '../../states/storeNamespaces';
import { getCurrentTopmostRouteForTask } from '../../states/routing/getRoute';
Expand Down Expand Up @@ -83,6 +91,8 @@ const mapDispatchToProps = (dispatch, ownProps) => {
),
),
searchContacts: (context: string) => searchContacts(dispatch)(taskId, context),
searchContactsByIds: (context: string) => searchContactsByIds(dispatch)(taskId, context),
searchV2Contacts: (context: string) => searchV2Contacts(dispatch)(taskId, context),
searchCases: (context: string) => searchCases(dispatch)(taskId, context),
closeModal: () => dispatch(newCloseModalAction(taskId)),
handleNewCreateSearch: (context: string) => dispatch(newCreateSearchForm(taskId, context)),
Expand All @@ -95,6 +105,8 @@ const Search: React.FC<Props> = ({
task,
currentIsCaller,
searchContacts,
searchContactsByIds,
searchV2Contacts,
searchCases,
handleSearchFormChange,
searchContactsResults,
Expand All @@ -109,6 +121,15 @@ const Search: React.FC<Props> = ({
const [mockedMessage, setMockedMessage] = useState('');
const [searchParams, setSearchParams] = useState<any>({});

const [contactsOffset, setContactsOffset] = useState(0);
const prevContactsOffset = useRef(-1);

const searchState = useSelector((state: RootState) => selectSearchStateForTask(state, task.taskSid, searchContext));
const {
isRequesting,
searchContactsResult: { searchMatchIds: contactSearchMatchIds, currentPageIds: contactsCurrentPageIds },
} = searchState;

useEffect(() => {
if (!form) {
handleNewCreateSearch(searchContext);
Expand All @@ -117,8 +138,18 @@ const Search: React.FC<Props> = ({

const closeDialog = () => setMockedMessage('');

const handleSearchContacts = (newSearchParams: SearchParams, newOffset) =>
searchContacts(searchContext)({ ...form, ...newSearchParams }, CONTACTS_PER_PAGE, newOffset);
const handleSearchContacts = (newSearchParams: SearchParams, newOffset: number) => {
// TODO: handle legacy
// if (enable_search_v2) {
searchV2Contacts(searchContext)({
searchParams: { ...form, ...newSearchParams },
limit: CONTACTS_PER_PAGE,
offset: newOffset,
});
// } else {
// searchContacts(searchContext)({ ...form, ...newSearchParams }, CONTACTS_PER_PAGE, newOffset);
// }
};

const handleSearchCases = (newSearchParams, newOffset) =>
searchCases(searchContext)({ ...form, ...newSearchParams }, CASES_PER_PAGE, newOffset);
Expand All @@ -137,7 +168,42 @@ const Search: React.FC<Props> = ({
}
};

const setOffsetAndHandleSearchContacts = newOffset => handleSearchContacts(searchParams, newOffset);
const setOffsetAndHandleSearchContacts = setContactsOffset;

// On page change, trigger a new search
useEffect(() => {
console.log('>>>>>>>>>>> triggered effect');
const handlePageChange = (newSearchParams: SearchParams, newOffset: number) => {
// if (enable_search_v2) {

const targetIds = contactSearchMatchIds?.slice(newOffset, newOffset + CONTACTS_PER_PAGE);
console.log('>>>>>>>>>>> contactsOffset', contactsOffset);
console.log('>>>>>>>>>>> prevContactsOffset', prevContactsOffset.current);
console.log('>>>>>>>>>>> isRequesting', isRequesting);
console.log('>>>>>>>>>>> targetIds', targetIds);
// const targetsChanged: boolean =
// Boolean(targetIds) && targetIds.every((id, index) => contactsCurrentPageIds[index] !== id);
// if (targetIds && targetsChanged && !isRequesting) {
if (targetIds && prevContactsOffset.current !== newOffset) {
console.log('>>>>>>>>>>> inner if condition of effect reached');
prevContactsOffset.current = contactsOffset;
searchContactsByIds(searchContext)(targetIds, CONTACTS_PER_PAGE, newOffset);
}
// } else {
// searchContacts(searchContext)({ ...form, ...newSearchParams }, CONTACTS_PER_PAGE, newOffset);
// }
};

handlePageChange(searchParams, contactsOffset);
}, [
contactSearchMatchIds,
contactsCurrentPageIds,
contactsOffset,
isRequesting,
searchContactsByIds,
searchContext,
searchParams,
]);

const setOffsetAndHandleSearchCases = newOffset => handleSearchCases(searchParams, newOffset);

Expand Down
43 changes: 43 additions & 0 deletions plugin-hrm-form/src/services/ContactService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,49 @@ export async function searchContacts(
};
}

export async function searchContactsByIds(
ids: string[],
limit,
offset,
): Promise<{
count: number;
contacts: Contact[];
}> {
const queryParams = getQueryParams({ limit, offset });

console.log('>>>>>>>>>>>> searchContactsByIds with ids', ids);

const options = {
method: 'POST',
body: JSON.stringify({ ids }),
};
const response = await fetchHrmApi(`/contacts/searchByIds${queryParams}`, options);
console.log('>>>>>>>>>>>> response.contacts', response.contacts);
return {
...response,
contacts: response.contacts.map(convertApiContactToFlexContact),
};
}

export async function searchContactsV2({
searchParams,
}: {
searchParams: SearchParams;
}): Promise<{
count: number;
contacts: Contact[];
}> {
const options = {
method: 'POST',
body: JSON.stringify({}),
};
const response = await fetchHrmApi(`/contacts/searchV2`, options);
return {
...response,
contacts: response.contacts.map(convertApiContactToFlexContact),
};
}

type HandleTwilioTaskResponse = {
channelSid?: string;
serviceSid?: string;
Expand Down
74 changes: 61 additions & 13 deletions plugin-hrm-form/src/states/search/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,16 @@ import { endOfDay, formatISO, parseISO, startOfDay } from 'date-fns';

import * as t from './types';
import { SearchParams } from './types';
import { searchContacts as searchContactsApiCall } from '../../services/ContactService';
import {
searchContacts as searchContactsApiCall,
searchContactsByIds as searchContactsByIdsApiCall,
searchContactsV2 as searchV2ContactsApiCall,
} from '../../services/ContactService';
import { searchCases as searchCasesApiCall } from '../../services/CaseService';
import { updateDefinitionVersion } from '../configuration/actions';
import { getCasesMissingVersions, getContactsMissingVersions } from '../../utils/definitionVersions';
import { getNumberFromTask } from '../../utils';
import { Contact } from '../../types/types';

// Action creators
export const handleSearchFormChange = (taskId: string, context: string) => <K extends keyof t.SearchFormValues>(
Expand All @@ -48,25 +53,25 @@ export const newCreateSearchForm = (taskId: string, context: string): t.SearchAc
} as t.SearchActionType;
};

export const searchContacts = (dispatch: Dispatch<any>) => (taskId: string, context: string) => async (
searchParams: SearchParams,
const searchContactsActionWithSearchService = <T>(
searchService: (
searchParams: T,
limit: any,
offset: any,
) => Promise<{
count: number;
contacts: Contact[];
}>,
) => (dispatch: Dispatch<any>) => (taskId: string, context: string) => async (
searchParams: T,
limit: number,
offset: number,
dispatchedFromPreviousContacts?: boolean,
) => {
try {
dispatch({ type: t.SEARCH_CONTACTS_REQUEST, taskId, context });

const { dateFrom, dateTo, ...rest } = searchParams ?? {};
const searchParamsToSubmit: SearchParams = rest;
if (dateFrom) {
searchParamsToSubmit.dateFrom = formatISO(startOfDay(parseISO(dateFrom)));
}
if (dateTo) {
searchParamsToSubmit.dateTo = formatISO(endOfDay(parseISO(dateTo)));
}

const searchResultRaw = await searchContactsApiCall(searchParamsToSubmit, limit, offset);
const searchResultRaw = await searchService(searchParams, limit, offset);
const searchResult = { ...searchResultRaw, contacts: searchResultRaw.contacts };

const definitions = await getContactsMissingVersions(searchResultRaw.contacts);
Expand All @@ -78,6 +83,11 @@ export const searchContacts = (dispatch: Dispatch<any>) => (taskId: string, cont
}
};

/**
* Legacy search actions
*/
export const searchContacts = searchContactsActionWithSearchService(searchContactsApiCall);

export const searchCases = (dispatch: Dispatch<any>) => (taskId: string, context: string) => async (
searchParams: any,
limit: number,
Expand Down Expand Up @@ -118,6 +128,44 @@ export const searchCases = (dispatch: Dispatch<any>) => (taskId: string, context
}
};

/**
* Search v2 actions
*/
export const searchContactsByIds = searchContactsActionWithSearchService(searchContactsByIdsApiCall);

export const searchV2Contacts = (dispatch: Dispatch<any>) => (taskId: string, context: string) => async ({
searchParams,
limit,
offset,
dispatchedFromPreviousContacts,
}: {
searchParams: SearchParams;
limit: number;
offset: number;
dispatchedFromPreviousContacts?: boolean;
}) => {
console.log('>>>>>>>>>>>>> searchV2Contacts callewd')
try {
dispatch({ type: t.SEARCH_CONTACTS_REQUEST, taskId, context });

const { dateFrom, dateTo, ...rest } = searchParams ?? {};
const searchParamsToSubmit: SearchParams = rest;
if (dateFrom) {
searchParamsToSubmit.dateFrom = formatISO(startOfDay(parseISO(dateFrom)));
}
if (dateTo) {
searchParamsToSubmit.dateTo = formatISO(endOfDay(parseISO(dateTo)));
}

const searchResultRaw = await searchV2ContactsApiCall({ searchParams: searchParamsToSubmit });
const searchMatchIds = searchResultRaw.contacts.map(c => c.id);

dispatch({ type: t.SEARCH_V2_CONTACTS_SUCCESS, searchMatchIds, taskId, dispatchedFromPreviousContacts, context });
} catch (error) {
dispatch({ type: t.SEARCH_CONTACTS_FAILURE, error, taskId, dispatchedFromPreviousContacts, context });
}
};

export const viewPreviousContacts = (dispatch: Dispatch<any>) => (task: ITask) => () => {
const contactNumber = getNumberFromTask(task);
const taskId = task.taskSid;
Expand Down
42 changes: 37 additions & 5 deletions plugin-hrm-form/src/states/search/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ export const newTaskEntry: SearchStateTaskEntry = {
[ContactDetailsSections.EXTERNAL_REPORT]: false,
[ContactDetailsSections.RECORDING]: false,
},
searchContactsResult: { count: 0, ids: [] },
searchCasesResult: { count: 0, ids: [] },
searchContactsResult: { count: 0, currentPageIds: [] },
searchCasesResult: { count: 0, currentPageIds: [] },
isRequesting: false,
isRequestingCases: false,
caseRefreshRequired: false,
Expand Down Expand Up @@ -223,9 +223,14 @@ export function reduce(
} = action;
const task = state.tasks[taskId];
const searchContext = state.tasks[taskId][context];
const { searchContactsResult } = state.tasks[taskId][context];
const newContactsResult = {
ids: contacts.map(c => c.id),
count: searchResult.count,
...searchContactsResult,
currentPageIds: contacts.map(c => c.id),
// if v2 is enabled, preserve count, else re-compute after every search
count: searchContactsResult.searchMatchIds?.length
? searchContactsResult.searchMatchIds.length
: searchResult.count,
};
const previousContactCounts = dispatchedFromPreviousContacts
? { ...searchContext.previousContactCounts, contacts: searchResult.count }
Expand All @@ -247,6 +252,33 @@ export function reduce(
},
};
}
case t.SEARCH_V2_CONTACTS_SUCCESS: {
const { searchMatchIds, taskId, dispatchedFromPreviousContacts, context } = action;
const task = state.tasks[taskId];
const searchContext = state.tasks[taskId][context];
const newContactsResult = {
searchMatchIds,
count: searchMatchIds.length,
currentPageIds: [],
};
const previousContactCounts = dispatchedFromPreviousContacts
? { ...searchContext.previousContactCounts, contacts: searchMatchIds.length }
: searchContext.previousContactCounts;
return {
...state,
tasks: {
...state.tasks,
[taskId]: {
...task,
[context]: {
...searchContext,
searchContactsResult: newContactsResult,
previousContactCounts,
},
},
},
};
}
case t.SEARCH_CONTACTS_FAILURE: {
const task = state.tasks[action.taskId];
const context = state.tasks[action.taskId][action.context];
Expand Down Expand Up @@ -292,7 +324,7 @@ export function reduce(
const task = state.tasks[taskId];
const context = state.tasks[action.taskId][action.context];
const newCasesResult = {
ids: cases.map(c => c.id),
currentPageIds: cases.map(c => c.id),
count,
};
const previousContactCounts = dispatchedFromPreviousContacts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const selectCasesForSearchResults = (state: RootState, taskSid: string, context:
}
return {
count: resultReferences.count,
cases: resultReferences.ids
cases: resultReferences.currentPageIds
.map(id => state[namespace].connectedCase.cases[id]?.connectedCase)
.filter(c => Boolean(c)),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const selectContactsForSearchResults = (state: RootState, taskSid: string, conte
}
return {
count: resultReferences.count,
contacts: resultReferences.ids
contacts: resultReferences.currentPageIds
.map(id => state[namespace].activeContacts.existingContacts[id]?.savedContact)
.filter(c => Boolean(c)),
};
Expand Down
Loading