Skip to content

Commit

Permalink
Merge branch 'master' into bo/chore/webchat_e2e
Browse files Browse the repository at this point in the history
  • Loading branch information
robert-bo-davis committed Sep 8, 2023
2 parents 38fc66a + a332087 commit 0a9e0a5
Show file tree
Hide file tree
Showing 14 changed files with 15,314 additions and 15,299 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"case": {
"households": {
"splitFormAt": 11
"splitFormAt": 13
},
"perpetrators": {
"splitFormAt": 9
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
{
"name": "repeatCaller",
"label": "Repeat Caller?",
"label": "Suspected Repeat Client",
"type": "checkbox"
},
{
Expand All @@ -19,16 +19,16 @@
"type": "listbox-multiselect",
"options": [
{
"value": "Direct interventions by the child helpline",
"label": "Direct interventions by the child helpline"
"value": "Support provided by Youthline",
"label": "Support provided by Youthline"
},
{
"value": "Recommendations of resources",
"label": "Recommendations of resources"
},
{
"value": "Referrals to child protection agencies",
"label": "Referrals to child protection agencies"
"value": "Referrals to Oranga Tamariki",
"label": "Referrals to Oranga Tamariki"
},
{
"value": "Referrals to general healthcare services",
Expand Down Expand Up @@ -64,10 +64,10 @@
"name": "howDidYouKnowAboutOurLine",
"label": "How did you know about our line/number?",
"type": "select",
"unknownOption": "",
"unknownOption": "Unknown",
"options": [
{
"value": "",
"value": "Unknown",
"label": ""
},
{
Expand Down Expand Up @@ -99,7 +99,7 @@
},
{
"name": "didYouDiscussRightsWithTheChild",
"label": "Did you discuss privacy rights and consent with the young person?",
"label": "Did you discuss privacy rights and consent with the client?",
"type": "mixed-checkbox"
}
]
]
5 changes: 4 additions & 1 deletion plugin-hrm-form/src/___tests__/utils/setUpActions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ describe('afterCompleteTask', () => {
describe('excludeDeactivateConversationOrchestration', () => {
test('backend_handled_chat_janitor === false and enable_post_survey === false should not change ChatOrchestrator', async () => {
const setOrchestrationsSpy = jest.spyOn(ChatOrchestrator, 'setOrchestrations');
excludeDeactivateConversationOrchestration(<FeatureFlags>{ enable_post_survey: false, backend_handled_chat_janitor: false });
excludeDeactivateConversationOrchestration(<FeatureFlags>{
enable_post_survey: false,
backend_handled_chat_janitor: false,
});

expect(setOrchestrationsSpy).not.toHaveBeenCalled();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import CircularProgress from '@material-ui/core/CircularProgress';

import { ErrorFont, LoadMediaButton, LoadMediaButtonText } from './styles';
import { S3StoredRecording } from '../../../types/types';
import { getFileDownloadUrl } from '../../../services/ServerlessService';
import { generateExternalMediaPath } from '../../../services/ContactService';
import fetchHrmApi from '../../../services/fetchHrmApi';

type OwnProps = { contactId: string; externalStoredRecording: S3StoredRecording };

Expand All @@ -34,11 +35,16 @@ const RecordingSection: React.FC<OwnProps> = ({ contactId, externalStoredRecordi
setLoading(true);
setShowButton(false);

const recordingPreSignedUrl = await getFileDownloadUrl(externalStoredRecording.location.key);
const recordingResponse = await fetch(recordingPreSignedUrl.downloadUrl);
const recordingBlob = await recordingResponse.blob();
const voiceRecording = new Audio(URL.createObjectURL(recordingBlob));
setVoiceRecording(voiceRecording.src);
// TODO: this won't currently work for local dev env
const { media_url: recordingPreSignedUrl } = await fetchHrmApi(
generateExternalMediaPath(
contactId,
externalStoredRecording.location.bucket,
externalStoredRecording.location.key,
),
);

setVoiceRecording(recordingPreSignedUrl);

setLoading(false);
} catch (error) {
Expand Down Expand Up @@ -86,7 +92,7 @@ const RecordingSection: React.FC<OwnProps> = ({ contactId, externalStoredRecordi
return (
<div>
{voiceRecording ? (
<audio controls src={voiceRecording} preload="auto" onError={handleFetchAndLoadException}>
<audio controls src={voiceRecording} preload="metadata" onError={handleFetchAndLoadException}>
<track kind="captions" />
</audio>
) : (
Expand Down
2 changes: 1 addition & 1 deletion plugin-hrm-form/src/permissions/ca.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"viewContact": [["isSupervisor"], ["isOwner"]],
"editContact": [["isOwner"], ["isSupervisor"]],
"viewExternalTranscript": [["isSupervisor"]],
"viewRecording": [],
"viewRecording": [["isSupervisor"]],

"viewPostSurvey": [["isSupervisor"]],

Expand Down
6 changes: 3 additions & 3 deletions plugin-hrm-form/src/permissions/cl.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
"viewContact": [["everyone"]],
"editContact": [["everyone"]],
"viewExternalTranscript": [["everyone"]],
"viewRecording": [],

"viewPostSurvey": [["isSupervisor"]],
"viewRecording": [["everyone"]],
"viewPostSurvey": [["isSupervisor"]],

"viewIdentifiers": [["everyone"]]
}
4 changes: 2 additions & 2 deletions plugin-hrm-form/src/permissions/co.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
"viewContact": [["everyone"]],
"editContact": [["isSupervisor"], ["isOwner"]],
"viewExternalTranscript": [["isSupervisor"]],
"viewRecording": [],

"viewRecording": [["isSupervisor"]],
"viewPostSurvey": [["isSupervisor"]],

"viewIdentifiers": [["everyone"]]
Expand Down
2 changes: 1 addition & 1 deletion plugin-hrm-form/src/permissions/hu.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"viewContact": [["everyone"]],
"editContact": [["isSupervisor"], ["isOwner"]],
"viewExternalTranscript": [["isSupervisor"]],
"viewRecording": [],
"viewRecording": [["isSupervisor"]],

"viewPostSurvey": [["isSupervisor"]],

Expand Down
3 changes: 2 additions & 1 deletion plugin-hrm-form/src/permissions/nz.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@
"viewContact": [["everyone"]],
"editContact": [["isSupervisor"], ["isOwner"]],
"viewExternalTranscript": [["everyone"]],
"viewRecording": [],
"viewRecording": [["everyone"]],

"viewPostSurvey": [["isSupervisor"]],
"viewIdentifiers": [["everyone"]]
}

2 changes: 1 addition & 1 deletion plugin-hrm-form/src/permissions/zw.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"viewContact": [["everyone"]],
"editContact": [["isSupervisor"], ["isOwner"]],
"viewExternalTranscript": [["isSupervisor"]],
"viewRecording": [],
"viewRecording": [["isSupervisor"]],

"viewPostSurvey": [["isSupervisor"]],

Expand Down
34 changes: 18 additions & 16 deletions plugin-hrm-form/src/services/ContactService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ import { getNumberFromTask } from '../utils';
import { TaskEntry } from '../states/contacts/types';
import {
ExternalRecordingInfoSuccess,
ExternalRecordingUnneeded,
getExternalRecordingInfo,
isFailureExternalRecordingInfo,
isSuccessfulExternalRecordingInfo,
shouldGetExternalRecordingInfo,
} from './getExternalRecordingInfo';
import { generateUrl } from './fetchApi';

type NestedInformation = { name?: { firstName: string; lastName: string } };
type LegacyInformationObject = NestedInformation & {
Expand Down Expand Up @@ -209,7 +209,7 @@ type HandleTwilioTaskResponse = {
channelSid?: string;
serviceSid?: string;
conversationMedia: ConversationMedia[];
externalRecordingInfo?: ExternalRecordingInfoSuccess | ExternalRecordingUnneeded;
externalRecordingInfo?: ExternalRecordingInfoSuccess;
};

export const handleTwilioTask = async (task): Promise<HandleTwilioTaskResponse> => {
Expand Down Expand Up @@ -241,24 +241,23 @@ export const handleTwilioTask = async (task): Promise<HandleTwilioTaskResponse>
});
}

if (!shouldGetExternalRecordingInfo(task)) return returnData;

const externalRecordingInfo = await getExternalRecordingInfo(task);
if (isFailureExternalRecordingInfo(externalRecordingInfo)) {
throw new Error(`Error getting external recording info: ${externalRecordingInfo.error}`);
}

returnData.externalRecordingInfo = externalRecordingInfo;

if (isSuccessfulExternalRecordingInfo(externalRecordingInfo)) {
const { bucket, key } = externalRecordingInfo;
returnData.conversationMedia.push({
store: 'S3',
type: 'recording',
location: {
bucket,
key,
},
});
}
const { bucket, key } = externalRecordingInfo;
returnData.conversationMedia.push({
store: 'S3',
type: 'recording',
location: {
bucket,
key,
},
});

return returnData;
};
Expand All @@ -268,7 +267,7 @@ type NewHrmServiceContact = Omit<HrmServiceContact, 'id' | 'updatedAt' | 'update
type SaveContactToHrmResponse = {
response: HrmServiceContact;
request: NewHrmServiceContact;
externalRecordingInfo?: ExternalRecordingInfoSuccess | ExternalRecordingUnneeded;
externalRecordingInfo?: ExternalRecordingInfoSuccess;
};
/**
* Function that saves the form to Contacts table.
Expand Down Expand Up @@ -396,3 +395,6 @@ export async function connectToCase(contactId, caseId) {

return fetchHrmApi(`/contacts/${contactId}/connectToCase`, options);
}

export const generateExternalMediaPath = (contactId: string, bucket: string, key: string) =>
`/files/urls?method=getObject&objectType=contact&objectId=${contactId}&fileType=recording&bucket=${bucket}&key=${key}`;
6 changes: 4 additions & 2 deletions plugin-hrm-form/src/services/InsightsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
isSuccessfulExternalRecordingInfo,
} from './getExternalRecordingInfo';
import { generateUrl } from './fetchApi';
import { generateExternalMediaPath } from './ContactService';

/*
* 'Any' is the best we can do, since we're limited by Twilio here.
Expand Down Expand Up @@ -399,12 +400,13 @@ const getInsightsUpdateFunctionsForConfig = (

const generateUrlProviderBlock = (externalRecordingInfo: ExternalRecordingInfoSuccess, contact: HrmServiceContact) => {
const { hrmMicroserviceBaseUrl } = getHrmConfig();

const { bucket, key } = externalRecordingInfo;

const url_provider = generateUrl(
new URL(hrmMicroserviceBaseUrl),
`/files/urls?method=getObject&objectType=contact&objectId=${contact.id}&fileType=recording&bucket=${bucket}&key=${key}`,
generateExternalMediaPath(contact.id, bucket, key),
).toString();

return [
{
type: 'VoiceRecording',
Expand Down
43 changes: 22 additions & 21 deletions plugin-hrm-form/src/services/getExternalRecordingInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,9 @@

import { getHrmConfig } from '../hrmConfig';
import { isVoiceChannel } from '../states/DomainConstants';
import { CustomITask, isOfflineContactTask } from '../types/types';
import { CustomITask, isOfflineContactTask, InMyBehalfITask } from '../types/types';
import { getExternalRecordingS3Location } from './ServerlessService';

export type ExternalRecordingUnneeded = {
status: 'unneeded';
};

export type ExternalRecordingInfoSuccess = {
status: 'success';
recordingSid: string;
Expand All @@ -32,44 +28,49 @@ export type ExternalRecordingInfoSuccess = {

type ExternalRecordingInfoFailure = {
status: 'failure';
name: string;
error: string;
};

export const isSuccessfulExternalRecordingInfo = (r: any): r is ExternalRecordingInfoSuccess => {
return r && r.status === 'success';
};

const isUnneededExternalRecordingInfo = (r: any): r is ExternalRecordingUnneeded => {
return r && r.status === 'unneeded';
};

export const isFailureExternalRecordingInfo = (r: any): r is ExternalRecordingInfoFailure => {
return r && r.status === 'failure';
};

export type ExternalRecordingInfo =
| ExternalRecordingInfoSuccess
| ExternalRecordingUnneeded
| ExternalRecordingInfoFailure;
export type ExternalRecordingInfo = ExternalRecordingInfoSuccess | ExternalRecordingInfoFailure;

const unneededRecordingInfo: ExternalRecordingUnneeded = {
status: 'unneeded',
};

export const getExternalRecordingInfo = async (task: CustomITask): Promise<ExternalRecordingInfo> => {
if (isOfflineContactTask(task)) return unneededRecordingInfo;
/* eslint-disable sonarjs/prefer-single-boolean-return */
export const shouldGetExternalRecordingInfo = (task: CustomITask): task is InMyBehalfITask => {
if (isOfflineContactTask(task)) return false;

const { channelType } = task;
if (!isVoiceChannel(channelType)) return unneededRecordingInfo;
if (!isVoiceChannel(channelType)) return false;

const { externalRecordingsEnabled } = getHrmConfig();
if (!externalRecordingsEnabled) return unneededRecordingInfo;
if (!externalRecordingsEnabled) return false;

return true;
};
/* eslint-enable sonarjs/prefer-single-boolean-return */

export const getExternalRecordingInfo = async (task: CustomITask): Promise<ExternalRecordingInfo> => {
if (!shouldGetExternalRecordingInfo(task)) {
return {
status: 'failure',
name: 'InvalidTask',
error: 'Invalid task',
};
}

// The call id related to the worker is always the one with the recording, as far as I can tell (rbd)
const callSid = task.attributes.conference?.participants?.worker;
if (!callSid) {
return {
status: 'failure',
name: 'NoCallSid',
error: 'Could not find call sid',
};
}
Expand Down
Loading

0 comments on commit 0a9e0a5

Please sign in to comment.