Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/v2.12-rc' into merge_v2.12-rc
Browse files Browse the repository at this point in the history
  • Loading branch information
GPaoloni committed Dec 19, 2023
2 parents 681ffdf + c3f8038 commit c5e4c74
Show file tree
Hide file tree
Showing 47 changed files with 367 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,10 @@
"name": "counsellingManagerInformed",
"label": "Did you inform the Counselling Manager about this referral form? (CM team must be informed once referral is complete)",
"type": "checkbox"
},
{
"name": "cmSignOff",
"label": "Sign off from Counselling Manager (CM use only)",
"type": "input"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,5 @@
"rows": 20,
"width": 500,
"placeholder": "Ingrese un resumen del cliente"
},
{
"name": "somethingElse",
"label": "Something Else",
"editLabel": "Edit Something Else",
"type": "textarea",
"rows": 20,
"width": 500,
"placeholder": "Ingrese el enfoque recomendado"
}
]
4 changes: 2 additions & 2 deletions plugin-hrm-form/src/HrmFormPlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import { setUpReferrableResources } from './components/resources/setUpReferrable
import { subscribeNewMessageAlertOnPluginInit } from './notifications/newMessage';
import { subscribeReservedTaskAlert } from './notifications/reservedTask';
import { setUpCounselorToolkits } from './components/toolkits/setUpCounselorToolkits';
import { setupConferenceComponents, setUpConferenceActions } from './conference';
import { setUpConferenceActions, setupConferenceComponents } from './conference';
import { setUpTransferActions } from './transfer/setUpTransferActions';
import { playNotification } from './notifications/playNotification';
import { namespace } from './states/storeNamespaces';
Expand Down Expand Up @@ -114,7 +114,7 @@ const setUpComponents = (
Channels.setUpIncomingTransferMessage();
}

if (featureFlags.enable_case_management) Components.setUpCaseList();
Components.setUpCaseList();
if (featureFlags.enable_client_profiles) Components.setUpClientProfileList();

if (!Boolean(setupObject.helpline)) Components.setUpDeveloperComponents(translateUI); // utilities for developers only
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ import { VALID_EMPTY_CONTACT } from '../../testContacts';
import { FeatureFlags } from '../../../types/types';
import { contactFormsBase, namespace } from '../../../states/storeNamespaces';

jest.mock('react-hook-form', () => ({
useFormContext: () => ({
clearErrors: jest.fn(),
register: jest.fn(),
}),
}));
jest.mock('../../../components/CSAMReport/CSAMReportFormDefinition');
jest.mock('../../../hrmConfig');

Expand Down
16 changes: 5 additions & 11 deletions plugin-hrm-form/src/___tests__/search/ContactDetails.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const mockStore = configureMockStore([]);

const contactOfType = (type): Contact => ({
id: 'TEST CONTACT ID',
profileId: 123,
accountSid: '',
createdAt: '',
updatedBy: '',
Expand Down Expand Up @@ -110,12 +111,11 @@ const contactOfType = (type): Contact => ({
callType: type,
contactlessTask: {
channel: 'voice',
},
conversationMedia: [],
} as Contact['rawJson']['contactlessTask'],
},
conversationMedia: [],
});

const handleBack = jest.fn();
const handleSelectSearchResult = jest.fn();

let mockV1;
Expand Down Expand Up @@ -185,18 +185,16 @@ test(`<ContactDetails> with contact of type ${callTypes.child}`, async () => {
<ContactDetails
contact={contact}
currentIsCaller={false}
handleBack={handleBack}
handleSelectSearchResult={handleSelectSearchResult}
showActionIcons={false}
task={{ taskSid: 'TEST_TASK_ID' }}
task={{ taskSid: 'TEST_TASK_ID' } as CustomITask}
/>
</Provider>
</StorelessThemeProvider>,
);

expect(screen.getByTestId('ContactDetails')).toBeInTheDocument();
expect(screen.queryByTestId('ContactDetails-Section-ChildInformation')).toBeInTheDocument();
expect(store.getActions().length).toBe(1);
expect(screen.getAllByTestId('ContactDetails-Section')).toHaveLength(4);
});

Expand All @@ -210,7 +208,6 @@ test(`<ContactDetails> with contact of type ${callTypes.caller}`, async () => {
<ContactDetails
contact={contact}
currentIsCaller={true}
handleBack={handleBack}
handleSelectSearchResult={handleSelectSearchResult}
task={{ taskSid: 'TEST_TASK_ID' } as CustomITask}
showActionIcons={false}
Expand All @@ -220,7 +217,6 @@ test(`<ContactDetails> with contact of type ${callTypes.caller}`, async () => {
);
expect(screen.getByTestId('ContactDetails')).toBeInTheDocument();
expect(screen.queryByTestId('ContactDetails-Section-ChildInformation')).toBeInTheDocument();
expect(store.getActions().length).toBe(1);
expect(screen.getAllByTestId('ContactDetails-Section')).toHaveLength(5);
});

Expand All @@ -234,15 +230,13 @@ test(`<ContactDetails> with a non data (standalone) contact`, async () => {
<ContactDetails
contact={contact}
currentIsCaller={false}
handleBack={handleBack}
handleSelectSearchResult={handleSelectSearchResult}
showActionIcons={false}
task={{ taskSid: 'TEST_TASK_ID' }}
task={{ taskSid: 'TEST_TASK_ID' } as CustomITask}
/>
</Provider>
</StorelessThemeProvider>,
);
expect(screen.getByTestId('ContactDetails')).toBeInTheDocument();
expect(store.getActions().length).toBe(1);
expect(screen.getAllByTestId('ContactDetails-Section')).toHaveLength(1);
});
2 changes: 1 addition & 1 deletion plugin-hrm-form/src/___tests__/search/Search.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -331,5 +331,5 @@ test('<Search> should display <ContactDetails />', async () => {
expect(screen.queryByTestId('ContactDetails')).toBeInTheDocument();
expect(screen.queryByTestId('SearchForm')).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'SearchResultsIndex-BackToResults' })).toBeDefined();
expect(store.getActions().length).toBe(1);
expect(store.getActions().length).toBe(0);
});
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ describe('test reducer (specific actions)', () => {
{ route: 'case', subroute: 'home' },
]),
expected: stateGenerator([{ route: 'tabbed-forms' }]),
action: actions.changeRoute({ route: 'tabbed-forms' }, task.taskSid, ChangeRouteMode.Reset),
action: actions.changeRoute({ route: 'tabbed-forms' }, task.taskSid, ChangeRouteMode.ResetModal),
description: `should replace the whole ${routeDescription} route with a new stack containing the new route as the only item if mode is Reset`,
},
];
Expand Down
5 changes: 2 additions & 3 deletions plugin-hrm-form/src/components/CustomCRMContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { createContactAsyncAction } from '../states/contacts/saveContact';
import { getAseloFeatureFlags, getHrmConfig } from '../hrmConfig';
import { newContact } from '../states/contacts/contactState';
import { selectAnyContactIsSaving } from '../states/contacts/selectContactSaveStatus';
import selectCurrentOfflineContact from '../states/contacts/selectCurrentOfflineContact';

type OwnProps = {
task?: ITask;
Expand Down Expand Up @@ -127,9 +128,7 @@ const mapStateToProps = (state: RootState) => {
} = state;
const { selectedTaskSid } = flex.view;
const { isAddingOfflineContact } = routing;
const currentOfflineContact = Object.values(activeContacts.existingContacts).find(
contact => contact.savedContact.taskId === getOfflineContactTaskSid(),
);
const currentOfflineContact = selectCurrentOfflineContact(state);
const hasUnsavedChanges =
Object.values(activeContacts.existingContacts).some(
({ savedContact, draftContact }) => !_.isEqual(savedContact, getUnsavedContact(savedContact, draftContact)),
Expand Down
5 changes: 3 additions & 2 deletions plugin-hrm-form/src/components/TaskView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import HrmForm from './HrmForm';
import FormNotEditable from './FormNotEditable';
import { RootState } from '../states';
import { hasTaskControl } from '../utils/transfer';
import { CustomITask, isOfflineContactTask, isInMyBehalfITask } from '../types/types';
import { CustomITask, isInMyBehalfITask, isOfflineContactTask } from '../types/types';
import ProfileIdentifierBanner from './profile/ProfileIdentifierBanner';
import { Flex } from '../styles/HrmStyles';
import { isStandaloneITask } from './case/Case';
Expand Down Expand Up @@ -185,7 +185,8 @@ const mapStateToProps = (state: RootState, ownProps: OwnProps) => {
};

const mapDispatchToProps = (dispatch, { task }: OwnProps) => ({
loadContactFromHrmByTaskSid: () => dispatch(loadContactFromHrmByTaskSidAsyncAction(task.taskSid)),
loadContactFromHrmByTaskSid: () =>
dispatch(loadContactFromHrmByTaskSidAsyncAction(task.taskSid, `${task.taskSid}-active`)),
createContact: (definition: DefinitionVersion) =>
asyncDispatch(dispatch)(
createContactAsyncAction(newContact(definition, task), getHrmConfig().workerSid, task.taskSid),
Expand Down
8 changes: 7 additions & 1 deletion plugin-hrm-form/src/components/case/CaseHome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import InfoIcon from '../caseMergingBanners/InfoIcon';
import { selectCurrentTopmostRouteForTask } from '../../states/routing/getRoute';
import selectCurrentRouteCaseState from '../../states/case/selectCurrentRouteCase';
import CaseCreatedBanner from '../caseMergingBanners/CaseCreatedBanner';
import { setCaseConnectedToContact } from '../../states/contacts/actions';

export type CaseHomeProps = {
task: CustomITask | StandaloneITask;
Expand Down Expand Up @@ -82,6 +83,7 @@ const CaseHome: React.FC<Props> = ({
connectedCaseState,
taskContact,
isCreating,
setCaseConnectedToContact,
// eslint-disable-next-line sonarjs/cognitive-complexity
}) => {
if (!connectedCaseState) return null; // narrow type before deconstructing
Expand Down Expand Up @@ -134,7 +136,8 @@ const CaseHome: React.FC<Props> = ({
const { can: canForContact } = getPermissionsForContact(taskContact?.twilioWorkerId);

const showConnectToCaseButton = Boolean(
taskContact &&
enableCaseMerging &&
taskContact &&
!taskContact.caseId &&
!isConnectedToTaskContact &&
connectedCase.connectedContacts?.length &&
Expand Down Expand Up @@ -242,6 +245,7 @@ const CaseHome: React.FC<Props> = ({
isConnectedToTaskContact={isConnectedToTaskContact}
onClickConnectToTaskContact={() => {
connectCaseToTaskContact(taskContact, connectedCaseState.connectedCase);
setCaseConnectedToContact(connectedCaseState.connectedCase, taskContact.id);
closeModal();
}}
color="black"
Expand Down Expand Up @@ -360,6 +364,8 @@ const mapDispatchToProps = (dispatch: Dispatch<any>, { task }: CaseHomeProps) =>
connectCaseToTaskContact: async (taskContact: Contact, cas: Case) =>
asyncDispatch(dispatch)(connectToCaseAsyncAction(taskContact.id, cas.id)),
closeModal: () => dispatch(newCloseModalAction(task.taskSid, 'tabbed-forms')),
setCaseConnectedToContact: (connectedCase: Case, contactId: string) =>
dispatch(setCaseConnectedToContact(connectedCase, contactId)),
});

const connector = connect(mapStateToProps, mapDispatchToProps);
Expand Down
23 changes: 16 additions & 7 deletions plugin-hrm-form/src/components/contact/ContactDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ import ContactDetailsSectionForm from './ContactDetailsSectionForm';
import IssueCategorizationSectionForm from './IssueCategorizationSectionForm';
import { forExistingContact } from '../../states/contacts/issueCategorizationStateApi';
import { loadContactFromHrmByIdAsyncAction } from '../../states/contacts/saveContact';
import { clearDraft, newSetContactDialogStateAction, updateDraft } from '../../states/contacts/existingContacts';
import {
clearDraft,
newSetContactDialogStateAction,
releaseContact,
updateDraft,
} from '../../states/contacts/existingContacts';
import CSAMReport from '../CSAMReport/CSAMReport';
import { existingContactCSAMApi } from '../CSAMReport/csamReportApi';
import { getAseloFeatureFlags, getTemplateStrings } from '../../hrmConfig';
Expand Down Expand Up @@ -76,15 +81,16 @@ const ContactDetails: React.FC<Props> = ({
clearContactDraft,
currentRoute,
openFormConfirmDialog,
saveStatus,
loadContactFromHrm,
...otherProps
// eslint-disable-next-line sonarjs/cognitive-complexity
}) => {
React.useEffect(() => {
if (!savedContact) {
if (!savedContact && saveStatus !== 'saving') {
loadContactFromHrm();
}
}, [savedContact, loadContactFromHrm]);
}, [saveStatus, savedContact, loadContactFromHrm]);
const version = savedContact?.rawJson.definitionVersion;

const featureFlags = getAseloFeatureFlags();
Expand Down Expand Up @@ -251,19 +257,22 @@ const mapDispatchToProps = (
goBack: () => dispatch(newGoBackAction(task.taskSid)),
openFormConfirmDialog: (form: keyof ContactRawJson, dismissAction: 'close' | 'back') =>
dispatch(newSetContactDialogStateAction(contactId, `${form}-confirm-${dismissAction}`, true)),
loadContactFromHrm: () => dispatch(loadContactFromHrmByIdAsyncAction(contactId)),
loadContactFromHrm: () => dispatch(loadContactFromHrmByIdAsyncAction(contactId, `${task.taskSid}-viewing`)),

releaseContactFromState: () => dispatch(releaseContact(contactId, `${task.taskSid}-viewing`)),
});

const mapStateToProps = (
{ [namespace]: { configuration, activeContacts, 'csam-report': csamReport, routing } }: RootState,
{ contactId, task }: OwnProps,
) => {
const currentRoute = getCurrentTopmostRouteForTask(routing, task.taskSid);

const { savedContact, draftContact, metadata } = activeContacts.existingContacts[contactId] ?? {};
return {
definitionVersions: configuration.definitionVersions,
savedContact: activeContacts.existingContacts[contactId]?.savedContact,
draftContact: activeContacts.existingContacts[contactId]?.draftContact,
savedContact,
draftContact,
saveStatus: metadata?.saveStatus,
draftCsamReport: csamReport.contacts[contactId],
currentRoute,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ const ContactDetailsHome: React.FC<Props> = function ({
const profileLink = featureFlags.enable_client_profiles && !isProfileRoute && savedContact.profileId && (
<SectionActionButton padding="0" type="button" onClick={() => openProfileModal(savedContact.profileId)}>
<Icon icon="DefaultAvatar" />
View Client
<Template code="Profile-ViewClient" />
</SectionActionButton>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type { CategoriesDefinition } from 'hrm-form-definitions';
import { Template } from '@twilio/flex-ui';
import GridIcon from '@material-ui/icons/GridOn';
import ListIcon from '@material-ui/icons/List';
import { useFormContext } from 'react-hook-form';

import { RootState } from '../../states';
import useFocus from '../../utils/useFocus';
Expand Down Expand Up @@ -63,6 +64,28 @@ const IssueCategorizationSectionForm: React.FC<Props> = ({
const firstElementRef = useFocus(shouldFocusFirstElement);
const selectedCount = Object.values(selectedCategories).reduce((acc, curr) => acc + curr.length, 0);

const { clearErrors, register } = useFormContext();

// Add invisible field that errors if no category is selected (triggered by validaiton)
React.useEffect(() => {
register('categories.categorySelected', {
validate: () => {
if (selectedCount < 1) {
return 'Error';
}

return null;
},
});
}, [register, selectedCount]);

// Clear the error state once the count is non-zero
React.useEffect(() => {
if (selectedCount) {
clearErrors('categories.categorySelected');
}
}, [clearErrors, selectedCount]);

return (
<Container formContainer={true}>
<CategoryTitle>
Expand Down
2 changes: 1 addition & 1 deletion plugin-hrm-form/src/components/profile/ProfileTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const ProfileTabs: React.FC<Props> = ({ profileId, task, currentTab, changeProfi

const tabs = [
{
label: 'Client',
label: <Template code="Profile-ClientTab" />,
key: 'details',
renderComponent: () => <ProfileDetails profileId={profileId} task={task} />,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import React from 'react';
import { ProfileSectionDefinition } from 'hrm-form-definitions';
import { Template } from '@twilio/flex-ui';

import { ProfileCommonProps } from '../types';
import { useProfileSectionByType } from '../../../states/profile/hooks/useProfileSection';
Expand All @@ -34,7 +35,13 @@ const ProfileSectionView = ({ profileId, sectionType }: OwnProps) => {

return (
<ProfileSectionTextContent hasContent={Boolean(section?.content)}>
{section?.content?.length > 0 ? section?.content : `No ${sectionType.label}`}
{section?.content?.length > 0 ? (
section?.content
) : (
<>
<Template code="Profile-Notes-No" /> {sectionType.label}
</>
)}
</ProfileSectionTextContent>
);
};
Expand Down
Loading

0 comments on commit c5e4c74

Please sign in to comment.