Show Incoming Call Notification

In the previous section, we saw, how to toggle the agent availability for calls. Once the agent's availability is set to Available for calls, the next setup step is to show the inbound call notification from your CTI supplier in the media toolbar and the Fusion application.

Steps to implement the incoming call notification

Part 1: Show incoming call notifications in your media toolbar application
  1. Add a call-panel component in the media toolbar application.
  2. Define the callContext property.
  3. Define the function handleIncomingCall to update the call-panel component property during an incoming call event.
  4. Add a generic function in the src/ts/appController.ts file to update the call-pane state.
  5. Add a method called incomingCallHandler in the integrationEventsHandler class.

Part 2: Show incoming call notifications in the Fusion application

  1. Add a method called showIncomingCallNotificationInFusion in the FusionHandler class and write the logic to publish newCommEvent.
  2. Call the showIncomingCallNotificationInFusion function from the incomingCallHandler function.
  3. Call the incomingCallNotificationHandler function from your vendorHandler file.
  • Add a method called showIncomingCallNotificationInFusion in the FusionHandler class and write the logic to publish newCommEvent.
  • Call the showIncomingCallNotificationInFusion function from the incomingCallHandler function.
  • Call the incomingCallNotificationHandler function from your vendorHandler file.

Part 1: Show incoming call notifications in your media toolbar application

When an incoming called from the CTI supplier comes in, a UI component is displayed in the media toolbar UI.

This component is a JET component consisting of call information and two buttons, for accepting or rejecting the call. Call information consists of the contact name associated with the incoming phone number and the IVR data. The label Unknown Number is displayed if the incoming phone number isn't saved in the Fusion application. If you followed the previous steps, you might have already created this component in your media toolbar application. So, you only need to add this component to your application.

Add a call-panel component in the media toolbar application

You can add the call-panel component in the index.html file of your toolbar application. In the src/index.html file, add the component in the div with role main as shown in the following example:
<oj-bind-if test="[[callContext().state === 'RINGING' || callContext().state === 'ACCEPTED']]">
    <call-panel call-context="[[callContext]]"></call-panel>
</oj-bind-if>
In the code example, call-context is the only property that's passed to the call panel component. So, you need to define callContext in your appController.ts file. The callContext property contains call-related information like phone number, caller name, direction, event id, IVR data, and state of the call. For simplicity, we can define three states for a call to our media toolbar application:
  • RINGING: The toolbar application will be in the RINGING state when the agent receives an incoming call from a customer. The toolbar application will also be in a ringing state when an agent starts an outbound call to a customer, which isn't yet picked up.
  • ACCEPTED: The toolbar application will be in the ACCEPTED state when the agent accepts an incoming call from the customer. The toolbar application will also be in an ACCEPTED state when a customer accepts an outbound call started by an agent.
  • DISCONNECTED: The toolbar application will move to the DISCONNECTED state when an agent rejects an incoming call from a customer or disconnects an ongoing call with the customer.

The call component is loaded conditionally only when the call state is RINGING or ACCEPTED.

Define callContext property

The callContext property must be passed to the call-panel component. Define the callContext property in your appController.ts file found in src/ts/appController.ts using the following code:

//.....
import "oj-c/button";
import "./jet-composites/call-panel/loader";
// ....
  
interface CallContext {
  phonenumber: string;
  callerName: string;
  direction: string;
  eventId: string;
  ivrData: { [key: string]: string };
  state: string;
}
 
class RootViewModel {
    // ....
    callContext: ko.Observable<CallContext>;
    // ...
  
    constructor() {
        // ....
  
        // CTI app properties
        this.callContext = ko.observable({
            phonenumber: "+918921670701",
            callerName: "John Doe",
            direction: "inbound",
            eventId: this.mockEventId(),
            ivrData: {
                jobTitle: "Developer",
                phoneType: "Work Phone",
                additional: "Some more"
            },
            state: "AVAILABLE" //AVAILABLE RINGING
        } as CallContext);    
        //...
    }
}

Define the function handleIncomingCall to update the call-panel component property during an incoming call event

//.....
import "oj-c/button";
import "./jet-composites/call-panel/loader";
// ....
  
interface CallContext {
  phonenumber: string;
  callerName: string;
  direction: string;
  eventId: string;
  ivrData: { [key: string]: string };
  state: string;
}
 
class RootViewModel {
    // ....
    callContext: ko.Observable<CallContext>;
    mockEventId: ko.Observable<string> = ko.observable(Date.now().toString());
    // ...
  
    constructor() {
        // ....
  
        // CTI app properties
        this.callContext = ko.observable({
            phonenumber: "+918921670701",
            callerName: "John Doe",
            direction: "inbound",
            eventId: this.mockEventId(),
            ivrData: {
                jobTitle: "Developer",
                phoneType: "Work Phone",
                additional: "Some more"
            },
            state: "AVAILABLE" //AVAILABLE RINGING
        } as CallContext);    
        //...
    }
    public handleIncomingCall = (customerName: string, incomingPhoneNumber: string, eventId: string) => {
        this.callContext({...this.callContext(),
            direction: 'inbound',
            phonenumber: incomingPhoneNumber,
            callerName: customerName,
            eventId: eventId,
            state: 'RINGING'});
    };
    public updateCallPanelState = (state: string) => {
        this.callContext({...this.callContext(), state: state});
    }
}

Add a generic function in src/ts/appController.ts to update the call-pane state

During the life cycle of a phone call, you need to update the state of the call-pane component several times. You can define the following generic function updateCallPanelState to make it easy::

//.....
import "oj-c/button";
import "./jet-composites/call-panel/loader";
// ....
  
interface CallContext {
  phonenumber: string;
  callerName: string;
  direction: string;
  eventId: string;
  ivrData: { [key: string]: string };
  state: string;
}
 
class RootViewModel {
    // ....
    callContext: ko.Observable<CallContext>;
    mockEventId: ko.Observable<string> = ko.observable(Date.now().toString());
    // ...
  
    constructor() {
        // ....
  
        // CTI app properties
        this.callContext = ko.observable({
            phonenumber: "+918921670701",
            callerName: "John Doe",
            direction: "inbound",
            eventId: this.mockEventId(),
            ivrData: {
                jobTitle: "Developer",
                phoneType: "Work Phone",
                additional: "Some more"
            },
            state: "AVAILABLE" //AVAILABLE RINGING
        } as CallContext);    
        //...
    }
    public updateCallPanelState = (state: string) => {
        this.callContext({...this.callContext(), state: state});
    }
}

Add a method incomingCallHandler to the integrationEventsHandler class

The incomingCallHandler method can be considered as a generic method that should be called during the incoming call event from your CTI supplier. From this method, you can call the handleIncomingCall function to show the incoming call notification component in your toolbar application.

/**
     *
     * @param incomingPhoneNumber
     * @param connectionId
     * Invoke this function when you receive an incoming call notification from your CTI system.
     * Once this is invoked, an incoming call notification popup will be shown in the fusion application.
     * Please refer doc shared for more information on newCommEvent API.
     */
public async incomingCallHandler(incomingPhoneNumber: string, eventId: string): Promise<void> {
    try {
        this.ctiAppViewModel.handleIncomingCall('', incomingPhoneNumber, eventId);
    } catch {
        // Catch errors
    }
}

Note that, the first parameter of thehandleIncomingCall function is the contact name associated with the phone number. For now, it's passed as an empty string. In the below part, you'll see, how you can get the contact name from the Fusion application so it can be passed here instead of an empty string.

Part 2: Showing incoming call notifications in the Fusion application

When there's an incoming call from your CTI supplier, a call notification dialog box will be displayed in the Fusion application.

The following ring received scenario handles this process.

The ring received scenario.

2. Add a method showIncomingCallNotificationInFusion in the FusionHandler class and write the logic to publish the newCommEvent

You'll get the newCommResponse from the showIncomingCallNotificationInFusion function call. You can get the contact name from this response and can be passed to handleIncomingCall function as shown in the following example:

public async incomingCallHandler(incomingPhoneNumber: string, eventId: string): Promise<void> {
    try {
        // Add logic to render the incoming call component and to notify Fusion about the incoming call
        const newCommResponseFromFusion: IMcaOutData = await FusionHandler.showIncomingCallNotificationInFusion(incomingPhoneNumber, eventId);
        const incomingCallCustomerName: string = newCommResponseFromFusion['SVCMCA_CONTACT_NAME'] ? newCommResponseFromFusion['SVCMCA_CONTACT_NAME'] : 'Unknown Number';
        this.ctiAppViewModel.handleIncomingCall(incomingCallCustomerName, incomingPhoneNumber, eventId);
    } catch {
        // Catch errors
    }
}

Call showIncomingCallNotificationInFusion function from incomingCallHandler function

You'll get the newCommResponse from the showIncomingCallNotificationInFusion function call. You can get the contact name from this response and can be passed to handleIncomingCall function as shown in the following example:

public async incomingCallHandler(incomingPhoneNumber: string, eventId: string): Promise<void> {
    try {
        // Add logic to render the incoming call component and to notify Fusion about the incoming call
        const newCommResponseFromFusion: IMcaOutData = await FusionHandler.showIncomingCallNotificationInFusion(incomingPhoneNumber, eventId);
        const incomingCallCustomerName: string = newCommResponseFromFusion['SVCMCA_CONTACT_NAME'] ? newCommResponseFromFusion['SVCMCA_CONTACT_NAME'] : 'Unknown Number';
        this.ctiAppViewModel.handleIncomingCall(incomingCallCustomerName, incomingPhoneNumber, eventId);
    } catch {
        // Catch errors
    }
}

3. Call incomingCallNotificationHandler function from your vendorHandler file

See your CTI supplier's documentation to identify how an incoming call is notified to the CTI application using their APIs. The incomingCallNotificationHandler function should be called from there. You can add the logic in the vendorHandler.ts file:

import { ICtiVendorHandler } from './ICtiVendorHandler';
  
export class VendorHandler implements ICtiVendorHandler {
    public async makeAgentAvailable() {
        // TODO: call the vendor specific api to make the agent available
        // TODO: call the vendor specific api to show incoming call notification
    }
    public async makeAgentUnavailable() {
        // TODO: call the vendor specific api to make the agent unavailable
    }
    public async makeOutboundCall(phoneNumber: string, eventId: string) {
        throw new Error('Method not implemented.');
    }
    public async acceptCall() {
        throw new Error('Method not implemented.');
    }
    public async rejectCall() {
        throw new Error('Method not implemented.');
    }
    public async hangupCall() {
        throw new Error('Method not implemented.');
    }
}

Verify your progress

Once you complete the previous steps, use the OJET serves to start your application and sign in to your Fusion application. Open the media toolbar and make your agent available for calls by clicking the agent availability button. Now, start a call to your customer care number. During this time, your media toolbar state will be changed to the RINGING state and you'll see the incoming call notification in your media toolbar application.