NTP-15943 | transfer call

This commit is contained in:
Mayank Singh
2024-12-01 01:30:41 +05:30
parent 0396193c40
commit c4412e5b4d
5 changed files with 130 additions and 56 deletions

View File

@@ -1,9 +1,8 @@
import getResponseWithoutCors from "@universal-call-sdk/common/lib/utils/getResponseWithoutCors.ts";
import { RequestKeys} from "./types";
import {GenericObject, RequestKeys} from "./types";
import RequestType from "@universal-call-sdk/common/lib/types/RequestType.ts";
export const loginInAmeyo = (userId: string, password: string) => {
console.log('loginInAmeyo', userId, password);
return getResponseWithoutCors({
@@ -27,7 +26,7 @@ export const loginInAmeyo = (userId: string, password: string) => {
};
export const maintainHeartbeat = (sessionId: string, webcoreTimestamp: string, counter: number) => {
const HEART_BEAT_REQUEST_TEXT = `7|0|8|${window.BASE_AMEYO_URL}/app/application_ui/|93B024BCBAF3AE5EFEC49890FE64CF5F|com.drishti.ameyo.common.ui.rpc.CommonGwtRpcService|keepAliveWithPingPush|java.lang.String/2004016611|java.lang.Integer/3438268394|${sessionId}|${webcoreTimestamp}|1|2|3|4|3|5|5|6|7|8|6|${counter}|${sessionId}|`;
setInterval(()=> getResponseWithoutCors({
setInterval(() => getResponseWithoutCors({
url: `${window.BASE_AMEYO_URL}/ameyo40/service`,
method: 'POST',
requestKey: RequestKeys.AMEYO_HEARTBEAT,
@@ -110,7 +109,7 @@ export const autoSelectExtension = (sessionId: string, userId: string) => {
requestType: RequestType.JSON,
data: {
sessionId: sessionId,
params: { 'user.id': userId }
params: {'user.id': userId}
},
headers: {
sessionId: sessionId
@@ -139,7 +138,7 @@ export const setAutoStatus = (sessionId: string) => {
method: 'POST',
requestKey: RequestKeys.SET_AUTO_STATUS,
requestType: RequestType.JSON,
data: { userSessionId: sessionId, status: true },
data: {userSessionId: sessionId, status: true},
headers: {
sessionId: sessionId
}
@@ -152,18 +151,18 @@ export const ameyoHangupUser = (sessionId: string, userCRTObjectId: string) => {
method: 'POST',
requestKey: RequestKeys.HANGUP_USER,
requestType: RequestType.JSON,
data: { sessionId, userCRTObjectId },
data: {sessionId, userCRTObjectId},
headers: {
sessionId
}
});
};
export const ameyoDisposeCall = (sessionId: string, campaignId : string,crtObjectId: string, userCRTObjectId: string) => {
export const ameyoDisposeCall = (sessionId: string, campaignId: string, crtObjectId: string, userCRTObjectId: string) => {
return getResponseWithoutCors({
url: `${window.BASE_AMEYO_URL}/ameyorestapi/voice/disposeCall`,
method: 'POST',
requestKey: RequestKeys.HANGUP_USER,
requestKey: RequestKeys.DISPOSE_CALL,
requestType: RequestType.JSON,
data: {
sessionId,
@@ -193,3 +192,38 @@ export const getCampaignId = (sessionId: string) => {
}
});
}
export const getAllAgentsForTransferCall = (sessionId: string) => {
return getResponseWithoutCors({
url: `${window.BASE_AMEYO_URL}/ameyorestapi/voice/getAllUserCampaignVoicePresencesByContactCenterId`,
method: 'GET',
requestKey: RequestKeys.GET_AGENTS_FOR_CALL_TRANSFER,
requestType: RequestType.JSON,
data: {},
headers: {
sessionId
}
});
}
export const transferCallToAgent = (data: GenericObject, sessionId: string, crtObjectId: string, userCRTObjectId: string, campaignId: string) => {
return getResponseWithoutCors({
url: `${window.BASE_AMEYO_URL}/ameyorestapi/voice/transferToUserInDifferentCampaign`,
method: 'POST',
requestKey: RequestKeys.TRANSFER_CALL_TO_AGENT,
requestType: RequestType.JSON,
data: {
sourceCampaignId: campaignId,
sourceCRTObjectId: userCRTObjectId,
targetCampaignId: data?.campaignId,
targetCRTObjectId: data?.targetCRTObjectId,
transferredCRTObjectIds: [crtObjectId],
"requestId": "48ae79ab-faad-21f5-b694-ad3d9e4e0690"
},
headers: {
sessionId
}
});
}

View File

@@ -11,7 +11,8 @@ import {
selectCampaign,
setAgentActive, setAgentOnBreak,
setAutoStatus,
getCampaignId, ameyoDisposeCall
getCampaignId, ameyoDisposeCall,
getAllAgentsForTransferCall, transferCallToAgent
} from "./api.ts";
import {
acceptSipCall,
@@ -31,6 +32,7 @@ class AmeyoAdapter implements IAdapter {
onAdapterReady: () => void,
onAgentAvailabilityChange: (isAgentAvailable: boolean) => void
onForcedLogout: () => void
onAgentsForCallTransfer: (data: GenericObject) => void
};
private currentCallState: string;
private eventListenerUrl: string;
@@ -46,7 +48,7 @@ class AmeyoAdapter implements IAdapter {
constructor(options: AmeyoInitializationOptions) {
console.log('AmeyoAdapter constructor');
if(document.readyState === 'loading') {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', this._appendTags);
} else {
this._appendTags();
@@ -67,6 +69,8 @@ class AmeyoAdapter implements IAdapter {
onAgentAvailabilityChange: () => {
},
onForcedLogout: () => {
},
onAgentsForCallTransfer: () => {
}
};
this.sessionId = '';
@@ -89,7 +93,7 @@ class AmeyoAdapter implements IAdapter {
}
_initializeSipStack = ({accountName, userName, domain="", password}: SipAccountInfo) => {
_initializeSipStack = ({accountName, userName, domain = "", password}: SipAccountInfo) => {
console.log('initializing sip stack');
const domainOnly = domain?.split?.(':')?.[0];
const port = domain?.split?.(':')?.[1];
@@ -157,6 +161,9 @@ class AmeyoAdapter implements IAdapter {
this.callbacks.onAgentAvailabilityChange(false);
window.postMessage({type: 'onAmeyoAvailabiltyChange', data: false},);
}
if (payload?.data?.requestKey === RequestKeys.GET_AGENTS_FOR_CALL_TRANSFER) {
this.callbacks.onAgentsForCallTransfer(payload?.data?.response);
}
}
_registerMessageListener = async ({data}: GenericObject) => {
@@ -219,6 +226,11 @@ class AmeyoAdapter implements IAdapter {
this.callbacks.onForcedLogout = callback;
}
registerOnAgentsForCallTransfer(callback: (data: GenericObject) => void) {
console.log('registerOnAgentsForCallTransfer');
this.callbacks.onAgentsForCallTransfer = callback;
}
acceptCall() {
console.log('acceptCall');
acceptSipCall();
@@ -261,10 +273,22 @@ class AmeyoAdapter implements IAdapter {
return this.currentCallState;
}
getAvailableAgentsForCallTransfer() {
getAllAgentsForTransferCall(this.sessionId);
}
transferCallToAgent(data: GenericObject) {
transferCallToAgent(data,
this.sessionId,
this.currentCallMetadata?.crtObjectId,
this.currentCallMetadata?.userCRTObjectId,
this.campaignId);
}
private _appendTags: () => void = () => {
const script = document.createElement('script');
script.src = 'https://public-assets.np.navi-gi.in/jarvis/sip5ml.js'; // Assuming it's placed in the public folder
script.async=true;
script.async = true;
document.head.appendChild(script);
const is_already_appended = document.querySelector('#audio_remote') && document.querySelector('#video_local') && document.querySelector('#video_remote') && document.querySelector('#ringtone') && document.querySelector('#ringbacktone') && document.querySelector('#dtmfTone');
if (is_already_appended) {
@@ -358,10 +382,10 @@ class AmeyoAdapter implements IAdapter {
src: 'https://public-assets.np.navi-gi.in/jarvis/dtmf.wav',
});
const onSipSetupReadyEvent = new CustomEvent('onSipSetupReady', {
detail: { message: 'Custom page loaded event triggered' }
detail: {message: 'Custom page loaded event triggered'}
});
script.onload = ()=>{
script.onload = () => {
window.dispatchEvent(onSipSetupReadyEvent)
}

View File

@@ -21,9 +21,12 @@ export enum RequestKeys {
OMNIQUEUE_SERVICE = 'ameyo_omniqueue',
SELECT_CAMPAIGN = 'select_campaign',
HANGUP_USER = 'hangup_user',
DISPOSE_CALL = 'dispose_call',
AUTO_SELECT_EXTENSION = 'auto_select_extension',
SET_AUTO_STATUS = "set_auto_status",
GET_CAMPAIGN_ID = "get_campaign_id",
GET_AGENTS_FOR_CALL_TRANSFER = "get_agents_for_call_transfer",
TRANSFER_CALL_TO_AGENT = "transfer_call_to_agent",
}
export type AmeyoInitializationOptions = {

View File

@@ -4,28 +4,25 @@ class IAdapter {
registerOnCallIncoming(callback: (callState: GenericObject)=>void) {callback({})}
registerOnCallConnected(callback: (callState: GenericObject)=>void) {callback({})}
registerOnCallDisconnected(callback: (callState: GenericObject)=>void) {callback({})}
registerOnAdapterReady(callback: ()=> void) {callback()}
registerOnAgentAvailabilityChange(callback: (isAgentAvailable: boolean) => void) {callback(false)}
registerOnForcedLogoutListener(callback:()=>void) {callback()}
registerOnAgentsForCallTransfer(callback: (data : GenericObject) => void) {callback({})}
acceptCall() {}
rejectCall() {}
muteCall() {}
disposeCall() {}
unmuteCall() {}
setOnBreak() {}
setAvailable() {}
init() {}
getAgentAvailability(): boolean {return false}
getLatestCallState() {return {}}
getAvailableAgentsForCallTransfer() {}
transferCallToAgent(data: GenericObject) {}
}
export default IAdapter;

View File

@@ -3,68 +3,66 @@ import {GenericObject, StateType} from "./types.ts";
import IAdapter from "@universal-call-sdk/common/lib/Interfaces/IAdapter.ts";
enum actionTypes {
CALL_INCOMING= 'CALL_INCOMING',
CALL_CONNECTED= 'CALL_CONNECTED',
CALL_DISCONNECTED= 'CALL_DISCONNECTED',
CALL_REJECTED= 'CALL_REJECTED',
CALL_MUTED= 'CALL_MUTED',
CALL_UNMUTED= 'CALL_UNMUTED',
enum actionTypes {
CALL_INCOMING = 'CALL_INCOMING',
CALL_CONNECTED = 'CALL_CONNECTED',
CALL_DISCONNECTED = 'CALL_DISCONNECTED',
CALL_REJECTED = 'CALL_REJECTED',
CALL_MUTED = 'CALL_MUTED',
CALL_UNMUTED = 'CALL_UNMUTED',
}
type Actions = {
type: actionTypes,
payload: GenericObject
}
function reducer(state : StateType, action: Actions) : GenericObject {
if(action.type === actionTypes.CALL_INCOMING) {
function reducer(state: StateType, action: Actions): GenericObject {
if (action.type === actionTypes.CALL_INCOMING) {
return {
...state,
connectedCustomerdata: action.payload,
isRinging: true
}
}
if(action.type === actionTypes.CALL_CONNECTED) {
if (action.type === actionTypes.CALL_CONNECTED) {
return {
...state,
isCallConnected: true
}
}
if(action.type === actionTypes.CALL_DISCONNECTED) {
if (action.type === actionTypes.CALL_DISCONNECTED) {
return {
...state,
connectedCustomerData: {},
isCallDisconnected: true
}
}
if(action.type === actionTypes.CALL_REJECTED) {
if (action.type === actionTypes.CALL_REJECTED) {
return {
connectedCustomerData: {},
isRinging: false
}
}
if(action.type === actionTypes.CALL_MUTED) {
if (action.type === actionTypes.CALL_MUTED) {
return {
...state,
isMuted: true
}
}
if(action.type === actionTypes.CALL_UNMUTED) {
if (action.type === actionTypes.CALL_UNMUTED) {
return {
...state,
isMuted: false
}
}
return state;
return state;
}
const initialState : StateType = {
const initialState: StateType = {
connectedCustomerdata: {},
isRinging: false,
isCallConnected: false,
@@ -73,39 +71,47 @@ const initialState : StateType = {
}
let adapter: IAdapter;
function UseCallSdk({AdapterClass, adapterOptions} : {AdapterClass: new (adapterOptions: IAdapter)=> IAdapter, adapterOptions: IAdapter}) {
function UseCallSdk({AdapterClass, adapterOptions}: {
AdapterClass: new (adapterOptions: IAdapter) => IAdapter,
adapterOptions: IAdapter
}) {
useEffect(() => {
adapter = new AdapterClass(adapterOptions);
}, []);
// @ts-expect-error sdfsf
const [callState] = useReducer<any>(reducer, initialState,()=> initialState);
const [callState] = useReducer<any>(reducer, initialState, () => initialState);
function registerOnCallIncoming(callback : (callState: GenericObject)=>void) {
function registerOnCallIncoming(callback: (callState: GenericObject) => void) {
//dispatch({type: actionTypes.CALL_INCOMING, payload: {}})
adapter.registerOnCallIncoming(callback);
}
function registerOnCallConnected(callback : (callState: GenericObject)=>void) {
function registerOnCallConnected(callback: (callState: GenericObject) => void) {
adapter.registerOnCallConnected(callback);
}
function registerOnCallDisconnected(callback : (callState: GenericObject)=>void) {
function registerOnCallDisconnected(callback: (callState: GenericObject) => void) {
adapter.registerOnCallDisconnected(callback);
}
function registerOnAdapterReady(callback : ()=> void) {
function registerOnAdapterReady(callback: () => void) {
adapter.registerOnAdapterReady(callback);
}
function registerOnAgentAvailabilityChange(callback : (isAgentAvailable: boolean) => void) {
function registerOnAgentAvailabilityChange(callback: (isAgentAvailable: boolean) => void) {
adapter.registerOnAgentAvailabilityChange(callback);
}
function registerOnForcedLogoutListener(callback:()=>void) {
function registerOnForcedLogoutListener(callback: () => void) {
adapter.registerOnForcedLogoutListener(callback);
}
function registerOnAgentsForCallTransfer(callback: (data: GenericObject) => void) {
adapter.registerOnAgentsForCallTransfer(callback);
}
function acceptCall() {
adapter.acceptCall();
}
@@ -140,20 +146,29 @@ function UseCallSdk({AdapterClass, adapterOptions} : {AdapterClass: new (adapter
function getAgentAvailability(): boolean {
console.log('prinitng adapter', adapter);
return adapter.getAgentAvailability();
return adapter.getAgentAvailability();
}
function getLatestCallState(): GenericObject {
return adapter.getLatestCallState();
}
return {
function getAvailableAgentsForCallTransfer() {
adapter.getAvailableAgentsForCallTransfer();
}
function transferCallToAgent(data: GenericObject) {
adapter.transferCallToAgent(data);
}
return {
callState,
registerOnCallIncoming,
registerOnCallConnected,
registerOnCallDisconnected,
registerOnAgentAvailabilityChange,
registerOnForcedLogoutListener,
registerOnAgentsForCallTransfer,
acceptCall,
rejectCall,
disposeCall,
@@ -164,9 +179,10 @@ function UseCallSdk({AdapterClass, adapterOptions} : {AdapterClass: new (adapter
getLatestCallState,
setOnBreak,
registerOnAdapterReady,
getAgentAvailability
}
getAgentAvailability,
getAvailableAgentsForCallTransfer,
transferCallToAgent
}
}
export default UseCallSdk;