Professional Documents
Culture Documents
of Contents
Overview
Introduction 1.1
Changelog 1.2
FAQ 1.3
User Guide
Getting Started 2.1
API Reference
Widget API Methods 3.1
onDataEvent 3.1.1
sendMessage 3.1.2
sendNotification 3.1.3
getConfiguration 3.1.4
getInteractionId 3.1.5
getWorkCardCount 3.1.6
getInteractionData 3.1.7
sendChatMessage 3.1.8
sendEmailMessage 3.1.9
removeEmailAttachment 3.1.10
reportChatTyping 3.1.11
startVoiceInteraction 3.1.12
acceptInteraction 3.1.13
holdInteraction 3.1.14
unholdInteraction 3.1.15
endInteraction 3.1.16
singleStepTransfer 3.1.17
2
consult 3.1.18
endConsult 3.1.19
completeTransfer 3.1.20
completeConference 3.1.21
getCapabilities 3.1.22
setTransferToServicesList 3.1.23
getDispositionCodes 3.1.24
setDispositionCode 3.1.25
getWorkCodes 3.1.26
setWorkCode 3.1.27
getNotReadyReasonCodes 3.1.28
getAdditionalWorkCodes 3.1.29
sendDTMF 3.1.30
insertMessageIntoResponseArea 3.1.31
insertContentIntoEmailBody 3.1.32
createCustomCard 3.1.33
updateCustomCard 3.1.34
deleteCustomCard 3.1.35
createCustomStatePanel 3.1.36
updateCustomStatePanel 3.1.37
deleteCustomStatePanel 3.1.38
updateMenuItems 3.1.39
searchEnterpriseDirectory 3.1.40
isEnterpriseContactsServiceAvailable 3.1.41
unregister 3.1.42
startWork 3.1.43
startWorkNotReady 3.1.44
setAgentReady 3.1.45
setAgentACW 3.1.46
finishWork 3.1.47
additionalWork 3.1.48
setAgentNotReady 3.1.49
bidi 3.1.50
forceReload 3.1.51
setFocus 3.1.52
onInteractionEvent 4.1.1
onChannelStatusUpdateEvent 4.1.2
onUserTypingEvent 4.1.3
onEmailAttachmentUploadEvent 4.1.4
3
onFileUploadEvent 4.1.5
onFileTransferInitiatedEvent 4.1.6
onFileTransferCompleteEvent 4.1.7
onInteractionEndedEvent 4.1.8
onCRMDataEvent 4.1.9
onContextDataEvent 4.1.10
onMediaEvent 4.1.11
onMediaMessageEvent 4.1.12
onPagePushUrlEvent 4.1.13
onAgentStateEvent 4.1.14
onNavigationEvent 4.1.15
onLocaleUpdatedEvent 4.1.16
onBeforeTextDirectionChangedEvent 4.1.17
onStylesheetsReadyEvent 4.1.18
onObserveEvent 4.1.19
onRequestServicesEvent 4.1.20
onCapabilitiesEvent 4.1.21
onMessageEvent 4.1.22
onTeamMemberEvent 4.1.23
onEnterpriseContactsReceivedEvent 4.1.24
onEnterpriseServiceAvailableEvent 4.1.25
onEnterpriseServiceUnavailableEvent 4.1.26
onCustomCardDeletedEvent 4.1.27
onCardFocusedEvent 4.1.28
onSSOTokenRefreshEvent 4.1.29
Capabilities 5.5
Using Web Components 5.6
Examples
Hello World 6.1
Localisation 6.4
4
5
Introduction
customise the layout and behavior of Workspaces for an entire contact center.
have access to a Widget API so that developers can create custom widgets that can be configured and deployed in
workspaces.
Both of these features combined enable contact centers and Avaya customers to customise Workspaces to their business needs.
Important - Please read the Widget Build Tools and Change Log sections for each new release in order to ensure that you
are up to date with the latest changes. Otherwise, you may see that custom widgets will not load properly in Workspaces.
6
Changelog
Release 3.7.0.0
Changes
Added the following property to the button object returned by createCustomCard or updateCustomCard method:
customCardId
Added the following Widget API methods:
bidi
setFocus
getWorkCardCount
Added the following Widget API events:
onBeforeTextDirectionChangedEvent
onStylesheetsReadyEvent
onCustomCardDeletedEvent
onCardFocusedEvent
onSSOTokenRefreshEvent
Added a new disableDefaultTabActivation property to the custom card object passed to the createCustomCard method
Release 3.6.1.0
Changes
Added the following Widget API methods:
sendEmailMessage
removeEmailAttachment
Added the following Widget API events:
onEmailAttachmentUploadEvent
Release 3.6.0.1
Changes
Added a new timeout property to the custom card object passed to the createCustomCard method
Removed the following deprecated events:
onCapabilitiesChangedEvent
onMediaDataEvent
Removed deprecated getCanStartVoiceInteraction method
Added the following Widget API methods:
updateMenuItems
sendChatMessage
reportChatTyping
getInteractionData
Added the following Widget API events:
onUserTypingEvent
onFileUploadEvent
7
Changelog
onFileTransferInitiatedEvent
onFileTransferCompleteEvent
Renamed isBeingObserved property passed within onInteractionEvent and onInteractionEndedEvent to isObserved
Extended onContextDataEvent with clientValidation data specifying max characters allowed when sending messages for
Chat, SMS or Social interactions
Added a new positionIndex property to the custom card object passed to the createCustomCard and updateCustomCard
methods
Release 3.6.0.0
Changes
Added the agent capabilities to the data passed in the [onAgentStateChangeEvent]
Added the following Widget API methods:
createCustomCard
updateCustomCard
deleteCustomCard
searchEnterpriseDirectory
isEnterpriseContactsServiceAvailable
getNotReadyReasonCodes
getAdditionalWorkCodes
startWork
startWorkNotReady
setAgentReady
setAgentACW
finishWork
additionalWork
setAgentNotReady
Added the following Widget API events:
onEnterpriseContactsReceivedEvent
onEnterpriseServiceAvailableEvent
onEnterpriseServiceUnavailableEvent
onInteractionEndedEvent
Added onPagePushUrlEvent to Widget API events. This was originally added as a 3.5.0.1 hotfix but was also ported forward
to 3.6.0.0.
Release 3.5.0.1
Changes
Added the following Widget API methods:
insertMessageIntoResponseArea
insertContentIntoEmailBody
Added the following new capabilities to the data passed in the onCapabilitiesEvent or the data returned by the getCapabilities
method:
canSendMessage
Added new push-suggested-responses sample widget to demonstrate usage of the insertMessageIntoResponseArea and
insertContentIntoEmailBody methods.
Added onPagePushUrlEvent to Widget API events.
8
Changelog
Release 3.5.0.0
Changes
Added the following Widget API methods:
getDispositionCodes
setDispositionCode
getWorkCodes
setWorkCode
sendDTMF
Added the following new capabilities to the data passed in the onCapabilitiesEvent or the data returned by the getCapabilities
method:
canSetDispositionCode
canSetWorkCode
canSendDtmf
Added the following new properties to the data passed in the onInteractionEvent:
skillId
topicId
Release 3.4.0.10
Changes
Added the following Widget API methods:
acceptInteraction
holdInteraction
unholdInteraction
endInteraction
singleStepTransfer
consult
endConsult
completeTransfer
completeConference
getCapabilities
Added onCapabilitiesEvent to Widget API events.
Added the following new properties to the data passed in the onInteractionEvent:
stateReason
interactionType
isCustomerInteraction
9
Changelog
isConsult
The getCanStartVoiceInteraction() Widget API method has been deprecated and will be removed in the next release.
Please use getCapabilities() instead.
The onCapabilitiesChangedEvent Widget API event has been deprecated and will be removed in the next release. Please
use onCapabilitiesEvent instead.
Release 3.4.0.1
Changes
Added onMediaEvent to Widget API events.
onMediaDataEvent has been deprecated and will be removed in the next release. Please use onMediaMessageEvent instead.
Release 3.4.0.0
Changes
Included the NEO CSS framework.
Added NEO CSS framework online documentation.
Improved Widget API online documentation.
Added 4 new widgets to the sample widget library.
Added a new project template to create widget library projects.
New Widget Manager UI added to Workspaces administrator
Added sendTextEmailTemplate and sendHTMLEmailTemplate Widget API methods to send custom email templates to the
Email widget.
Added getCanStartVoiceInteraction Widget API method to implement click-to-call functionality.
Added startVoiceInteraction Widget API method to implement click-to-call functionality.
Added onCapabilitiesChangedEvent Widget API event.
Added onTeamMemberEvent Widget API event to get team member data.
10
FAQ
The widget framework developer documentation can be downloaded directly from the Workspaces administrator log in. To access
the documentation, you will need access to a live contact center deployment and will have to log in to Workspaces as an
Administrator user (configured in ACM). Once logged-in, you can download the documentation and sample widget library by
clicking on the URL links in the Overview section of the Workspaces Administrator widget.
Can I write a widget that a supervisor can use to send messages to a widget used by agents?
No. Widget to widget communication is intended so that two or more widgets can communicate with each other within a single
instance of Workspaces and only when the agent is presented with a work card. For example, when an agent receives a call and
accepts the work card, two or more widgets can communicate and access details about the call and perform actions such as
querying a remote database or loading a web page, etc. Widget communication only occurs within the context of the work card,
which means that if an agent has several work cards, widgets can only communicate with each other and only within the bounds
of their own work card type (voice, chat, email, etc.)
How can I access the prompted digits from a customer call from a widget?
Prompted digits information is available in the "onInteractionEvent" which is documented in the Widget API.
Widgets offer several options for integrating external systems such as CRM systems.
IFRAME - a simple widget can be written to encapsulate the CRM website in an IFRAME and make the CRM system
accessible via a web page.
REST API - If the CRM system has a REST API, a widget can be written to directly query the CRM's REST API, this
approach would be considered a pure client-side integration.
SALESFORCE - Workspaces comes with an in-built Salesforce CRM adapter that provides client-side integration out of the
box. Salesforce CRM data is available as a data object in the Widget API.
BACKEND - a custom CRM can be integrated as a Breeze snap-in and integrated with Workspaces via the UAC component
and Client JavaScript SDK, then this integration can be exposed in the Widget API in a similar fashion as the native
Salesforce CRM adapter.
PROXY - a custom CRM can be integrated via a Proxy REST API or a Proxy Web Application. A proxy REST API wraps an
existing CRM system and makes it REST capable so that widgets can access CRM data indirectly via the proxy. A proxy web
application is a simple web app/page that encapsulates the CRM interface and makes it accessible via an IFRAME indirectly
without blocking any content or permission restrictions.
Each widget contains a configuration file in JSON format (e.g. hello-world.json ). This configuration file can be imported from
the Widget Manager section in the Workspaces Administrator.
Why do you use AngularJS for writing widgets? Can we use another framework?
Workspaces is written in AngularJS version 1.5.0. We do not support Angular 2. As a requirement, widgets need to be written as
AngularJS directives and because AngularJS is flexible, widgets could load external JavaScript code and HTML templates
developed in other frameworks (e.g. ReactJS, VueJS, etc). However, we don't recommend doing this because it contradicts the
philosophy of keeping widgets simple!
Is it all Angular JS and what release do we support? Does it have to be the release we support?
The latest AngularJS release we support in the widget framework is Angular JS version 1.5.0. The minimum AngularJS release
supported is 1.2.
11
FAQ
Are the widgets contained or can they use other features in Workspaces?
Widgets are bound to work cards in Workspaces. They can not access or use other Workspaces features unless that feature is
requested and supported by the UAC component in Breeze.
There are no tools to generate the widget files in Workspaces 3.2/3.3. Instead, we recommend that developers modify the widgets
in the sample library and adapt them to their needs.
Core widgets like Chat, Email, Customer Details are bundled in Workspaces and do not need to be loaded, they are available by
default in every Workspaces version. External widgets need to be hosted on a remote web server via HTTPS with CORS enabled.
The URL for this web server needs to be configured so that Workspaces can load the widgets.
Core widgets - these are the default widgets provided in Workspaces and developed and supported by Avaya, for example the
Chat, Email, Customer Details widgets, etc. These widgets are bundled in every version of Workspaces.
External widgets - these are widgets developed by a third-party and maintained externally. These are typically widgets
written by Avaya customers. These widgets use the Widget Framework API and implement custom functionality (e.g.
integrate with customer infrastructure).
How can my widget access a legacy application that it not web based?
Widgets are written using web technologies (JavaScript, HTML, CSS, JSON). You can still write a widget that implements a
screen sharing protocol such as VNC/RDP to access a legacy application that is not web based.
Can you load ActiveX controls, Flash or Java Applets inside widgets?
It is possible but not recommended as these are considered legacy web technologies prone to browser incompatibilities and
security issues.
Are widgets secure? Are there any risks of leaking data to unauthorized applications or users?
Widgets inherit the Browsers security model and security permissions of the underlying network and the security model of the
Workspaces solution. We recommend that the widget library is hosted on internal web servers only accessible from VPN or
restricted networks.
Do you provide custom CSS UI components such as buttons or forms that I can use in my widgets?
Custom CSS UI components are provided in Workspaces 3.4 via the NEO CSS Framework.
Can I import my own CSS style sheets and use them in my widgets?
Yes. Custom CSS style sheets can be used as long as they don't overwrite the global web font used by Workspaces or implement a
CSS reset.
Do you have examples of more complex widgets or larger applications integrated into Workspaces using the Widget API?
12
FAQ
Not at this moment. However, AWFOS is an application entirely written using the widget framework developed by an internal
team at Avaya. The sample widget library provided is intended to showcase the Widget API and most widgets are intentionally
simple.
13
Getting Started
Getting Started
Administrator User
To customize Workspaces, a new Administrator user role is required. This user can be created and configured in ACM (Avaya
Control Manager). The administrator user won't have access to any channels or any contact center features. The only purpose of
this user is to customize Workspaces.
Workspaces Administrator UI
Once the Administrator is created and configured, they can easily customize the layout of Workspaces via this Workspaces
Administrator UI.
Using this interface, an administrator user has access to the default layout configuration of Workspaces and can perform the
following actions:
Restrictions:
14
Getting Started
15
Layout Manager
Layout Manager
You can choose to alter the layout based on role, interaction type or defaults. The following layouts can be customized:
Home: default layout presented when the user initially logs in or selects the home tab
Voice: layout presented when a Voice interaction is accepted
Webchat: layout presented when a Webchat interaction is accepted
Email: layout presented when an Email interaction is accepted
SMS: layout presented when an SMS interaction is accepted
Social: layout presented when a social interaction is accepted
Outbound: layout presented when an Outbound interaction is accepted
Video: layout presented when a Video interaction is accepted
Generic: layout presented when a Generic channel interaction is accepted
It is important to note that if you wish to change the layout for all interaction types, you will need to make the change in each
interaction type (i.e. changing the layout for Voice will not affect other interaction types)
16
Layout Manager
The button will set the sidebar tab as the default for that layout. This tab will be selected when Workspaces enters
the context of the chosen layout. e.g For the voice layout - when a voice interaction is accepted.
Clicking the button allows the user to edit the properties of this sidebar tab.
Name
Description
Icon
Alignment
Role
Layout
Widgets
Note: only the Select Layout and Select Widgets properties can be set for core sidebar tabs (non custom tabs)
The button allows you to clone the sidebar tab, providing a starting point for a new sidebar tab. A new sidebar tab
will be appended to the bottom of the sidebar tab list.
The button removes the selected tab from the current layout.
17
Layout Manager
Fill out the details of your new tab in the Sidebar Options panel.
Select the layout you want by clicking the radio button below the layout choices.
Click on each Widget area and select the desired Widget to be displayed in that position.
Your new Sidebar tab should now be available on the Customize Sidebar screen.
18
Layout Manager
The newly created Sidebar tab will now be visible on the Sidebar. The tooltip text will be displayed when the tab is hovered over.
Clicking on the new Sidebar tab will display the Widgets that were configured for the Sidebar tab in the main Context area of the
UI.
19
Layout Manager
Importing a Layout
Click on the Layout tab link.
Click on the "IMPORT LAYOUT" button. This will open your File Explorer.
Navigate to the location on your hard drive/storage to where a previously saved layout is located and import the file.
Your layout will be updated to the imported configuration.
Exporting a Layout
Click on the Layout tab link.
Click on the "EXPORT LAYOUT" button. This will download the layout to your downloads folder location.
20
Layout Manager
21
Widget Manager
Widget Manager
Sample Widget JSON
{
"metadata": {
"name": "Hello World",
"description": "Basic Hello world example",
"tags": "agent, demo, hello, world",
"library": "Sample",
"version": "1.0.0",
"date": "2017-02-14T23:24:41.230Z",
"id": "5e066f61-5794-4aab-bc1d-3dda05743062"
},
"configuration": {
"external": true,
"timeout": 5000,
"serie": true,
"name": "5e066f61-5794-4aab-bc1d-3dda05743062",
"element": "<hello-world></hello-world>",
"icon": "aoc-home",
"files": [
"hello-world/libs/external.js",
"hello-world/libs/miniq.js",
"hello-world/hello-world.css",
"hello-world/hello-world.js"
]
}
}
Importing a Widget
Rules:
A widget must contain the following properties: metadata.name , metadata.description , metadata.id ,
metadata.library , configuration.name , configuration.icon , configuration.element ;
Navigate to the location on your hard drive/storage where you saved your widget library and import the file the JSON file for
the hello-world widget.
Important - You must import the built/minified version of the widget from the bundle folder.
Once the widget is imported, you should be able to see it in the list of widgets.
22
Widget Manager
23
Sample Library
The table below describes the list of widgets included in the sample widget library:
Widget Description
hello-world This widget demonstrates all the Widget API methods and Widget API events.
crm-
This widget demonstrates how to obtain customer history data from the Salesforce CRM system. Client
history-
will need to be successfully connected to Salesforce to use this widget.
timeline
email-
This widget demonstrates how to produce a word cloud visualization of the email text.
word-cloud
message-
This widget demonstrates how to use the Widget API for widget to widget communication.
echo
pdf-viewer This widget demonstrates how to load an external PDF document from an URL.
This widget demonstrates how to use the Widget API to fetch prompted digits information from a voice
prompt- work card. This widget needs to be configured on voice layout on a system that has CollectedDigits
digits configured in ACM : Oceana Core Data Service Collected Digits Key Note: The sample pdf provided
with the widget is for id: 1141
slide-share This widget demonstrates how to configure a slide share presentation using an iframe.
twitter-feed This widget demonstrates how to display a twitter live feed loaded using an iframe.
vimeo-
This widget demonstrates how to create a video player using the Vimeo service.
player
youtube-
This widget demonstrates how to create a video player using the YouTube service.
player
address-
This widget demonstrates searching the enterprise directory (LDAP)
book
google-
This widget hosts google maps within workspaces.
maps
transfer-to-
This widget demonstrates how to override the Transfer to Service List.
service-list
knowledge-
This widget demonstrates a knowledge base word cloud.
base
filtered-
transfer-to- This widget demonstrates how to override the Transfer to Service List.
service-list
single-step-
This widget demonstrates how to perform a single step transfer to an address.
transfer
interaction-
This widget demonstrates various interaction capabilities such as accept/hold/unhold/end/consult etc.
operations
interaction- This widget demonstrates how to handle and communicate with participants on Chat/SMS/Social
messenger interactions
electrical-
grid-line- This widget demonstrates some css animation.
checker
24
Sample Library
push-
This widget demonstrates how to insert messages into the response area on a Chat/SMS/Social widget and
suggested-
also how to insert HTML or Plain text into the Email widget.
responses
25
Sample Project
The table below describes the contents of the sample project template:
Widget Description
Readme.md This file contains instructions on how to install and use the project template
Gruntfile.js This file is used by the Grunt task runner to create, compile and bundle widgets
package.json This file contains all the NodeJS package dependencies needed by the project template
View instructions on how to use the build tools and the sample project template
26
Default Layouts - Elite
Home
Team Same as
Customer
Viewer Agent +
Home n/a Search Same as Agent
Welcome My
Settings
Page Agents
Help
Home
Customer
Customer Details
Details Customer
Same as
Journey
Voice Agent +
Interaction n/a n/a
Interaction My
Details Screenpops
Agents
Customer
Customer Search
History Settings
Help
Home
Customer
Details
Tab for
parent
interaction
Same as
type
Customer Agent +
Customer n/a Customer n/a
Journey My
Journey Journey
Agents
Screenpops
Customer
Search
Settings
Help
Home
Customer
Details
Tab for
Open parent
Screenpop full interaction
Same as
screen type
Agent +
Screenpops If multiple Customer n/a
Screenpops My
screenpops Journey
Agents
toggle using
tabs Screenpops
Customer
Search
Settings
Help
Home
Customer
Search
Supervisor Review Analytics
Supervisor n/a n/a
Desktop Agent status My
Desktop
Agents
Settings
Help
27
Default Layouts - Elite
28
Default Layouts - Oceana
Home
Team Same as Agent
Viewer Customer +
Home n/a Same as Agent
Welcome Search Analytics
Page Settings My Agents
Help
Home
Customer
Details
Customer
Details
Customer Same as Agent
Voice Journey +
Interaction n/a n/a
Interaction Analytics
Details
Screenpops My Agents
Customer
Customer
History
Search
Settings
Help
Send
Home
message
Send
Customer
suggested
Details
phrase
Chat
Edit
Co-
suggested
Browse
Chat phrase before Same as Agent
sending +
Web Chat Customer n/a
Suggested If in Analytics
Journey
Content Conference: My Agents
Send
Screenpops
message to
Agents only
Customer
(Whisper)
Search
Send
Settings
message to all
Help
participants
Home
Customer
Details
Send SMS
SMS
Send
SMS suggested Same as Agent
Customer
phrase +
SMS Journey n/a
Suggested Edit Analytics
Content suggested My Agents
Screenpops
phrase before
sending
Customer
Search
Settings
Help
Home
29
Default Layouts - Oceana
Customer
Details
Email
Same as Agent
Email
Email Reply Customer +
Email n/a
[Read] Reply to all Journey Analytics
Templates
My Agents
Screenpops
Customer
Search
Settings
Help
Home
Customer
Details
Email
Same as Agent
Email Customer
Email +
Email Send Email Journey n/a
[Reply] Analytics
Templates
My Agents
Screenpops
Customer
Search
Settings
Help
Home
Customer
Details
Social
Social Same as Agent
Screenpops
+
Social Send Social n/a
Suggested Analytics
Customer
Content My Agents
Journey
Customer
Search
Settings
Help
Home
Customer
Outbound
Details Same as Agent
+
Outbound n/a Customer n/a
Interaction Analytics
Search
Details My Agents
Settings
Help
Outbound
Script
Home
Customer
Open Details
Screenpop full
Same as Agent
screen Customer +
Generic If multiple Journey n/a
Screenpops Analytics
screenpops
My Agents
toggle using Customer
tabs Search
Settings
30
Default Layouts - Oceana
Help
Home
Customer
Details
Customer
Search
Settings
Help
Home
Customer
Details
Tab for
parent
interaction
type Same as Agent
Customer +
Customer n/a n/a
Journey Customer Analytics
Journey
Journey My Agents
Screenpops
Customer
Search
Settings
Help
Home
Customer
Details
Tab for
parent
Open
interaction
Screenpop full
type Same as Agent
screen
+
Screenpops If multiple n/a
Screenpops Customer Analytics
screenpops
Journey My Agents
toggle using
tabs
Screenpops
Customer
Search
Settings
Help
Home
Customer
Request Details
control from Tab for
user parent
Release interaction
Chat type
control to user Same as Agent
(mini
(if agent has +
Co-Browse view) Customer n/a
control) Analytics
Co- Journey
Refresh My Agents
Browse
End Co-
Browse Screenpops
Session
31
Default Layouts - Oceana
Session Customer
Search
Settings
Help
Home
Review
Customer
Agent status
Search
Supervisor Observe
Supervisor n/a Analytics n/a
Desktop Agent
Desktop My Agents
Barge In on
Settings
Agent
Help
Home
Dashboards
Home
(Edit Private /
Dashboards
Administer View Public)
(Public)
Dashboards Views (Edit
Views
Create Private / View
(Public)
Analytics Views n/a Public)
Analytics Calculated
Create Calculated
Measures
Calculated Measures (Edit
(Public)
Measures Private / View
Settings
Public)
Help
Settings
Help
32
Default Layouts - AACC
Home
Team
Viewer
Customer
Home n/a n/a Same as Agent
Search
Welcome
Settings
Page
Help
Customer
Home
Details
Voice Customer
Interaction n/a n/a n/a
Interaction Search
Details
Settings
Help
Customer
History
Send message
Send suggested
phrase
Edit suggested Home
Web
phrase before
Chat
sending Customer
Web Chat n/a n/a
If in Conference: Search
Suggested
Send message to Settings
Content
Agents only Help
(Whisper)
Send message to
all participants
Home
Reply Reply
Email Reply to all Customer
n/a n/a
[Read] Suggested Insert text into Search
Content email Settings
Help
Home
Email
Send Email
Email Customer
Insert text into n/a n/a
[Reply] Suggested Search
email
Content Settings
Help
Home
Customer
Details
Same as
Screenpops Agent +
Video Video Mute Analytics n/a
Hide Customer My
Journey Agents
Customer
Search
Settings
Help
33
Default Layouts - AACC
34
Widget API Methods
Widget API
The Widget API enables third-party developers to write custom widgets and deploy them in Workspaces. To write a custom
widget, you will need access to the Widget API Developer Documentation and code examples. The Widget API is designed to
make it easier for anyone with a basic understanding of HTML, CSS and JavaScript to write a custom widget and deploy it in
Workspaces.
To get developers started, we provide a sample widget library that can be deployed directly in Workspaces. The sample widget
library can be downloaded here. In the sample widget library, there are several example widgets that use the features of the Widget
API.
Please note, methods marked as 'Requires Interaction' require an interaction context. Any Widget leveraging these methods
will need to be placed on an Interaction related tab (e.g. Customer Details).
Constructor
Constructor method to initialize the Widget API (see examples in the sample widget library). The constructor returns a
reference to the Widget API object which can then be used to make API calls. The params object must be passed
automatically during the initialization stage of the widgetContainer (see code examples provided in the sample widget
library).
onDataEvent(event, callback)
Allows the widget to subscribe to the various data events delivered by Workspaces. See the Widget API Events section for
the list of currently supported events.
event: This is the name of the event you want to subscribe to.
callback: a callback function which is fired once the event returns data.
sendMessage(data, id)
Broadcasts a data event to all the widgets under the same interaction context. This method can be used for widget-to-
widget communication and to exchange data.
35
Widget API Methods
Note: this data will get broadcast on the onMessageEvent. For details see Widget API Events.
sendNotification(level, message)
Displays a notification message in Workspaces. This method sends and displays the message as a "toast" notification.
getConfiguration()
This method returns configuration information relevant to the current Workspaces session for a Workspaces User. The
following information is provided:
user ID
station ID
user
display name
user first name
user last name
user handle
user state
authentication token (JWT)
current locale
user settings
user POM settings*
36
Widget API Methods
Payload
{
"agentId": "10003",
"stationId": "1003",
"displayName": "John Costello",
"firstName": "John",
"lastName": "Costello",
"handle": "johnCostello",
"token": "Bearer
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJqb2huQ29zdGVsbG8iLCJpYXQiOjE1MDY1MT
ExOTIsImV4cCI6MTUwNjc3MDM5Mn0.eDl3y4NQfWQBeXx8R0m7uwFXE6HXdsuNr3avaBtIJhKr4pLW-
9SypDIaWNtz7TI8S-
VN9AtDlt6LIGiMm_l0hyPrcLTpO9EmT0GTXMOZlL45G5uork8FW_1tCujaCh8N4fgPZeXgkHcxjBTdnexxn
HJ1Vqriu3n_r6J7XlmOcM5nUekIy8hItKE3Z-
SsbcV7LjqG9T8oWM3nSXPYrdnWvn7i30JDQf_z4l3etBes_t_3BX1mTDhWdCMNUIBIB0qVE7SmnKqOHyyec
ilkHxCYWl-
4v73FxTcpyLI6RGD_3Uy3EFXDo60SMr7TzctmnKlTiS4lzMFeFpe12CGQDUyuSGDQDH0n5D4wESF-
Fgd8GAhvVRh1yqdwEOIxAtWDlS-
7jdjwOgc9HK0jPQCnKchlwcSPNP9HJsFGks65tZbDqmYUvvfBLmEvhhWQR36ksVDnYl1-
sq1yWDuQJGDzNPGrKFzgThfIkZSF2EmHI2qTOP959ZLibFx8jrBA1epK2o6-
F7tJ7a5SZGWCJJDL5GWGhmGa58429zk49vUS5h01j_ajvgfNxF__MFnUvRbgOjPhEfXw4-
eVEgXLe9p3FOpHdu4cKsByXL_Yew5G9NYeL9l13Wh8fokZ9OiJkhNFF7B_UboIsbbwA6gSvZ8gxWENaIm6F
MGD3Hh5EZ3Uq5KZ2Uw",
"state": "READY",
"channels": {
"VOICE": {
"state": "READY",
"stateReason": "DEFAULT",
"capabilities": {
"canSetCallForwarding": true,
"canCancelCallForwarding": true,
"canStartInteraction": true,
"canStartSupervisorInteraction": true
}
},
"WEBCHAT": {
"state": "READY",
"stateReason": "DEFAULT",
"capabilities": {
"canSetCallForwarding": false,
"canCancelCallForwarding": false,
"canStartInteraction": false,
"canStartSupervisorInteraction": false
}
},
"EMAIL": {
"state": "READY",
"stateReason": "DEFAULT",
"capabilities": {
"canSetCallForwarding": false,
37
Widget API Methods
"canCancelCallForwarding": false,
"canStartInteraction": true,
"canStartSupervisorInteraction": false
}
},
"SMS": {
"state": "READY",
"stateReason": "DEFAULT",
"capabilities": {
"canSetCallForwarding": false,
"canCancelCallForwarding": false,
"canStartInteraction": false,
"canStartSupervisorInteraction": false
}
},
"SOCIAL": {
"state": "READY",
"stateReason": "DEFAULT",
"capabilities": {
"canSetCallForwarding": false,
"canCancelCallForwarding": false,
"canStartInteraction": false,
"canStartSupervisorInteraction": false
}
},
"VIDEO": {
"state": "READY",
"stateReason": "DEFAULT",
"capabilities": {
"canSetCallForwarding": true,
"canCancelCallForwarding": true,
"canStartInteraction": true,
"canStartSupervisorInteraction": true
}
},
"GENERIC": {
"state": "READY",
"stateReason": "DEFAULT",
"capabilities": {
"canSetCallForwarding": true,
"canCancelCallForwarding": true,
"canStartInteraction": true,
"canStartSupervisorInteraction": true
}
}
},
"locale": {
"id": "en-us",
"label": "English (US)",
"textDirection": "ltr",
"textAvatar": true,
38
Widget API Methods
"stringsVersion": "1"
},
"settings": {
"awfosEnabled": true,
"coBrowseURL": "10.134.146.163",
"coBrowseFQDN": "10.134.146.163",
"contextStoreClusterIP": "ocdsFQDN",
"ocdsFQDN": "ocdsFQDN",
"customerManagementFQDN": "10.134.146.40",
"aawgFQDN": "aawgFQDN",
"ocpAddress": "10.134.146.28",
"ocpFQDN": "10.134.146.28",
"hotdesk": false,
"isWebRTC": false,
"observeIndicatorEnabled": true,
"salesforceConfiguration": {
"ApplicationName": "CC_Client",
"ConsumerKey":
"3MVG98_Psg5cppyYaaOW5FZdV8rTYZuaYxGoP4wz97OSfkLYl0EBZrXQ3B8lbWPqs5NAcPAOi5rPdpD4vP
9nd",
"ConsumerSecretKey": "3723015645493377233",
"CRMIntegrationEnabled": "true",
"ProxyServerURL": "http://10.134.138.178:9090",
"SalesforceEndpoint": "https://eu6.salesforce.com"
},
"screenPopConfiguration": {
"DisplayInternalScreenpopWidgetFirstOnAgentAccept": "false",
"EnableScreenpopWithoutAgentprompting": "false",
"LaunchExternalScreenpopsOnAgentAccept": "false"
},
"welcomePage": "assets/pages/iframe.html",
"supervisorReportingURL": "assets/pages/iframe.html",
"workspacesLoggingEnabled": false,
"workspacesLoggingLevel": "",
"workspacesLogUploadLocation": "https://10.134.138.178:8443/upload",
"websocketsEnabled": true,
"genericChannelFriendlyName": "TestChannel",
"genericChannelIcon": "aoc-custom01",
"clockDriftMillis": 155
}
},
"pomSettings": {
"widgetDownloadLocation": "https://widgetDownloadLocation/",
"widgetPrimaryAddress": "https://widgetPrimaryAddress/",
"widgetPrimaryPort": "1234",
"widgetSecondaryAddress": "https://widgetSecondaryAddress/",
"widgetSecondaryPort": "2345",
"pomOrganizations": [{
"organization": "org1",
"zones": ["zone1", "zone2"]
}, {
39
Widget API Methods
"organization": "org2",
"zones": ["zone3", "zone4"]
}]
}
}
getInteractionId()
This method returns the Interaction ID for the active interaction.
getWorkCardCount()
This method returns the number of interactions.
getInteractionData()
This method returns the interaction related data (same as what you get using onInteractionEvent)
Payload
{
"id": "f775be25-68a0-4c54-9b10-a24f6cc4b5ff",
"workRequestId": "0085617462979956890064",
"externalInteractionId": "-2694020189_9f88add7-0f0d-4708-aec9-b6cc8b740554",
"channel": "SMS",
"state": "ACTIVE",
"stateReason": "DEFAULT",
"interactionType": "CALLED",
"title": "(212) 842-5599",
"topic": "Oceana Service",
"topicId": "3007",
"skill": null,
"skillId": null,
40
Widget API Methods
"direction": "INCOMING",
"isCustomerInteraction": false,
"isWebRtcCall": false,
"userToUserInfo": null,
"isConsult": false,
"originatingAddress": "(212) 842-5599",
"destinationAddress": "1001",
"isObserved": false,
"contactId": "lHu1kWd6xBhjp7mifzcCJI"
}
sendChatMessage(message)
Sends text message into an interaction on behalf of current agent.
This method will only execute if the capabilities.interaction.canSendMessage capability is set to true . Please see
Capabilities for more information.
Note: This method is restricted to be invoked no more than once per 1 second due to security restrictions
sendEmailMessage(emailData)
Sends text message into an interaction on behalf of current agent.
This method will only execute if the capabilities.interaction.canSendMessage capability is set to true . Please see
Capabilities for more information.
Note: This method is restricted to be invoked no more than once per 1 second due to security restrictions
The emailData object passed to sendEmailMessage method can contain the following properties...
41
Widget API Methods
removeEmailAttachment(attachment)
Remove email attachment by attachment id.
The attachment object passed to removeEmailAttachment method can contain the following properties...
reportChatTyping()
Sends a typing notification to other participants
Note: This method is restricted to be invoked no more than once per 6 seconds due to security restrictions
Note: In order to prevent "is typing..." label flickering on side of customer, make sure to invoke this method once per 6
seconds during user is typing.
// Listen to keydown event on input and call reportChatTypingThrottle each time user presses any key
document.querySelector('input[type=text]').addEventListener('keydown', reportChatTypingThrottle);
startVoiceInteraction(address)
Starts an outbound voice interaction.
42
Widget API Methods
This method will only execute if the capabilities.channels.canStartVoiceInteraction capability is set to true .
Please see Capabilities for more information.
address: the address that will be used to initiate the outbound voice interaction.
acceptInteraction()
Accepts an altering interaction.
This method will only execute if the capabilities.interaction.canAccept capability is set to true . Please see
Capabilities for more information.
Note: This method is only applicable in an Elite environment where the widgets are displayed while an interaction is
altering.
api.acceptInteraction();
holdInteraction()
Holds an active interaction.
This method will only execute if the capabilities.interaction.canHold capability is set to true . Please see
Capabilities for more information.
api.holdInteraction();
unholdInteraction()
Unholds a held interaction.
This method will only execute if the capabilities.interaction.canUnhold capability is set to true . Please see
Capabilities for more information.
api.unholdInteraction();
43
Widget API Methods
endInteraction()
Ends the active interaction.
This method will only execute if the capabilities.interaction.canEnd capability is set to true . Please see
Capabilities for more information.
api.endInteraction();
singleStepTransfer(address)
Performs a single step transfer to an address.
This method will only execute if the capabilities.interaction.canSingleStepTransfer capability is set to true .
Please see Capabilities for more information.
consult(address, uui)
Initiates a consult to an address.
This method will only execute if the capabilities.interaction.canConsult capability is set to true . Please see
Capabilities for more information.
// Consult an address
api.consult('3156');
44
Widget API Methods
endConsult()
Ends the consultative leg of an interaction.
completeTransfer()
Transfers the interaction to the consulted address.
This method will only execute if the capabilities.interaction.canTransferComplete capability is set to true . Please
see Capabilities for more information.
completeConference()
Completes the consult as a conference.
This method will only execute if the capabilities.interaction.canConferenceComplete capability is set to true .
Please see Capabilities for more information.
getCapabilities()
Gets the latest capabilities for the active interaction and agent channels.
45
Widget API Methods
Payload
{
interaction: {
canAccept: false,
canEnd: true,
canHold: true,
canUnhold: false,
canSingleStepTransfer: true,
canConsult: true,
canTransferComplete: false,
canConferenceComplete: false,
canSetDispositionCode: true,
canSetWorkCode: true,
canSendDtmf: true,
canSendMessage: true
},
channels: {
canStartVoiceInteraction: true
}
}
setTransferToServicesList
Allows the setting of a custom list of transfer to service destinations in the Workspaces work card. This method expects an
array of services that will be displayed on the Transfer to Service dropdown list on an interaction's work card. In order for a
Transfer to work the services must already exist in UCA. It is expected that the widget developer will retrieve this list from
UCA and filter the services list inside the widget. See filtered-transfer-to-service-list sample widget for further
demonstration.
// The following list of services is only an example. In order for a Transfer to work the services must already
exist in UCA.
// In the real world this list of services will not be hardcoded, it will be retrieved from UCA and then filter
ed by the widget developer.
var services = [{
"id" : "Language.Irish|Service.TechnicalSupport",
"name" : "IrishVoiceTransferToService"
}, {
"id" : "Language.English|Service.TechnicalSupport",
"name" : "EnglishVoiceTransferToService"
}];
api.setTransferToServicesList(services);
getDispositionCodes(channelType)
46
Widget API Methods
Gets a list of all disposition codes if any are configured. By default this method will return all disposition codes configured
for all channel types. However, it is possible to receive a filtered list by passing a valid channelType as an argument. i.e
VOICE, EMAIL, CHAT, SMS, SOCIAL.
channelType (optional): A channel type. This will result in the method returning a filtered list of disposition codes
which have been assigned to this channel type.
Payload
[
{
"code": "5645",
"friendlyName": "Report to Supervisor",
"type": "DISPOSITION",
"channels": [
"SMS",
"WEBCHAT"
]
},
{
"code": "3534",
"friendlyName": "Offer discount on next call",
"type": "DISPOSITION",
"channels": [
"VOICE",
"SMS",
"EMAIL",
"WEBCHAT"
]
}
]
See the interaction operations or hello-world sample widgets for further demonstration.
setDispositionCode(code)
47
Widget API Methods
This method will only execute if the capabilities.interaction.canSetDispositionCode capability is set to true .
Please see Capabilities for more information.
getWorkCodes(channelType)
Gets a list of all work codes if any are configured. By default this method will return all work codes configured for all
channel types. However, it is possible to receive a filtered list by passing a valid channelType as an argument. i.e VOICE,
EMAIL, CHAT, SMS, SOCIAL.
channelType (optional): A channel type. This will result in the method returning a filtered list of work codes which
have been assigned to this channel type.
Payload
[
{
"code": "7277",
"friendlyName": "Breakfast",
"type": "WORK",
"channels": [
"VOICE"
]
},
{
"code": "7777",
"friendlyName": "Sales",
48
Widget API Methods
"type": "WORK",
"channels": [
"VOICE",
"SMS",
"EMAIL",
"WEBCHAT"
]
},
{
"code": "8888",
"friendlyName": "Support",
"type": "WORK",
"channels": [
"EMAIL"
]
}
]
See the interaction operations or hello-world sample widgets for further demonstration.
setWorkCode(code)
Sets a work code on the interaction.
This method will only execute if the capabilities.interaction.canSetWorkCode capability is set to true . Please see
Capabilities for more information.
getNotReadyReasonCodes()
Gets a list of all Not Ready reason codes if any are configured.
Payload
[
{
49
Widget API Methods
"code": "1234",
"friendlyName": "Bathroom",
"type": "NOT_READY",
"channels": []
},
{
"code": "4567",
"friendlyName": "Break",
"type": "NOT_READY",
"channels": []
},
{
"code": "6785",
"friendlyName": "Meeting",
"type": "NOT_READY",
"channels": []
}
]
getAdditionalWorkCodes()
Gets a list of all Additional Work codes if any are configured.
Payload
[
{
"code": "999",
"friendlyName": "Additional Work",
"type": "ADDITIONAL_WORK",
"channels": []
}
]
sendDTMF(digit)
Sends a DTMF digit.
This method will only execute if the capabilities.interaction.canSendDtmf capability is set to true . Please see
Capabilities for more information.
50
Widget API Methods
digit: The DTMF digit to be sent. Only values 0-9 , * and # are accepted.
insertMessageIntoResponseArea(message)
Inserts a message into the response area (input box) located on the Chat/SMS/Social widget.
This method will only execute if the capabilities.interaction.canSendMessage capability is set to true . Please see
Capabilities for more information.
This method will only execute if the capabilities.interaction.canSendMessage capability is set to true . Please see
Capabilities for more information.
encoding (required): The encoding of the Email. Values accepted are either 'HTML' or 'PLAIN'.
content (optional): The content to be inserted into the Email body. This is left optional so that the method can still be
called to show the Email editor screen.
subject (optional): The subject to be inserted into the Email body.
51
Widget API Methods
Note: you can use the onMediaMessageEvent to retrieve the encoding of the current Email interaction. For details see the push-
suggested-responses sample widget.
createCustomCard(data)
This method allows 3rd party developers to create work cards that will appear in the work card area in Workspaces. These custom
cards will appear similar to existing work cards but can be customized to suit the requirements of a 3rd party widget developer
looking to integrate Workspaces with an external work provider. These custom work cards will always be displayed to the right of
Contact Center work cards. There has been a limit of 3 set on the maximum number of custom work cards that can be displayed in
Workspaces at any one time. This is configurable up to 10 in the Administrator settings. Each top-level button will have an icon
and a title. A button can define an optional property 'color' which adds a background color to the icon (green, yellow, red or
blue). An optional 'action' property can also be added to a button to trigger a callback function when the button is clicked. A
maximum of 6 top-level buttons can be displayed on the custom card at any one time. A developer can create a dropdown menu
button by setting the isContextMenu property to true and defining a list of menu items and sub-menu items. Menu items can have a
title, a tooltip, an action and an array of subMenusItems. There are some limitations with these drop-down menus. Please refer to
the 'Menu Limitations' note below. The data sent to the API to create a custom work card needs to be localised by the calling 3rd
party widget. The API will enforce validation of the JavaScript object to ensure it can be displayed in the card. It is up to the 3rd
party widget to maintain the buttons as the card changes state.
Note: For Custom Cards to work with Customer Journey, it is required that the interactionData.state property is set to 'ACTIVE'
while the card is in an active state, as Customer Journey will only be initialised if this property is set to 'ACTIVE'
Menu Limitations: For the context menu buttons, there are some limitations that a developer should be aware of. If a developer
chooses to configure the parent menu to have sub-menu items, there will be no search field on the parent menu. Searching on a
first-level dropdown menu is only supported if the menu is configured to have no sub-menus. Searching in a sub-menu is
supported. So developers can create two types of dropdown menus: A menu with no sub-menus and a search input field or a menu
with sub-menus (searching supported within the sub-menus) and no search input field. Menu items that contain sub-menus are
limited to 5 per parent menu. Sub-menus or first-level menus without sub-menus will display a maximum of 20 items at a time.
There will be searching provided on these types of menus to further refine the list.
Creates a custom Card that will be displayed in the Work Card Area in Workspaces. This method accepts the following
parameters:
data (required): A JavaScript Object used to configure the content, behaviour and look of the Custom Card
The data object passed to createCustomCard method can contain the following properties...
52
Widget API Methods
No - Property
available on Custom Card ID to give button access to which card button is
customCardId string
button callback attached to
object
53
Widget API Methods
No/ Yes if
menuItems menuItem[] isContextMenu Array of menu items to display in drop down list
is true
Input with a button icon. If set, will be placed at the top of the
inputWithButton object No
context menu. Can be used only if isContextMenu is true.
action function No Callback executed when menu item has been clicked
action function No Callback executed when sub-menu item has been clicked
Callback executed when button has been clicked. Input value is passed as
action function Yes
callback's parameter
combo string Yes A white listed keyboard shortcut i.e 'Ctrl + Shift + h'
Callback executed when button has been clicked. Cards value is passed
action function No
as callback's parameter
Shortcut
Ctrl then a
54
Widget API Methods
Ctrl then x
Ctrl + Shift + h
Ctrl then h
Ctrl then t
Ctrl + Shift + m
Ctrl then d
Ctrl then c
Ctrl then g
Ctrl then e
Ctrl then z
Ctrl then u
Ctrl then o
Ctrl then b
Ctrl then 1
Ctrl then 2
Ctrl then 3
Ctrl then 4
Ctrl then 5
Ctrl then 6
Ctrl then 7
Ctrl then 8
Ctrl then 9
Ctrl then 0
55
Widget API Methods
buttons: [{
title: 'accept',
positionIndex: '1',
icon: 'aoc-accept-call',
color: 'green',
uniqueIdentifier: 'buttonToClick',
action: function (data) {
console.log('accept clicked');
api.sendNotification('info', 'The button is attached to ' + data.customCardId);
}
},{
title: 'button-2',
positionIndex: '2',
icon: 'aoc-hold',
isContextMenu: true,
inputWithButton: {
placeholder: 'Input field',
buttonIcon: 'aoc-voice-active',
buttonTooltip: 'My purpose here is to submit the input field value',
action: function (value) {
api.sendNotification('info', value + ' submitted');
}
},
menuItems: [{
title: 'dropdown-menu-item-1',
tooltip: 'tooltip-dropdown-menu-item-1',
action: function () {console.log('dropdown-menu-item-1 clicked')}
},{
title: 'dropdown-menu-item-2',
action: function () {console.log('dropdown-menu-item-1 clicked')}
}]
}],
interactionData: {
workRequestId: '23498734598723049'
},
focusOnCreated: true
});
updateCustomCard(data)
This method allows 3rd party developers to update existing custom work cards. Throttling of one update per second is enforced on
custom card updates to ensure better rendering performance and to prevent flickering or unwanted UI artifacts.
Updates an existing custom Card that is displayed in the Work Card Area in Workspaces. This method accepts the
following parameters:
data (required): A JavaScript Object used to configure the content, behaviour and look of the Custom Card
The data object passed to updateCustomCard method can contain the following properties...
56
Widget API Methods
legTitle string No Optional text to display at top of Custom Card context area
No - Property
available on Custom Card ID to give button access to which card button is
customCardId string
button callback attached to
object
No/ Yes if
menuItems menuItem[] isContextMenu Array of menu items to display in drop down list
is true
Input with a button icon. If set, will be placed at the top of the
inputWithButton object No
context menu. Can be used only if isContextMenu is true.
57
Widget API Methods
action function No Callback executed when menu item has been clicked
action function No Callback executed when sub-menu item has been clicked
Callback executed when button has been clicked. Input value is passed as
action function Yes
callback's parameter
58
Widget API Methods
title: 'dropdown-menu-item-1',
tooltip: 'tooltip-dropdown-menu-item-1',
subMenuItems: [{
title: 'dropdown-submenu-item-1',
tooltip: 'tooltip-dropdown-submenu-item-1',
action: function () {
console.log('dropdown-menu-item-1-sub-menu-1 clicked')
}
}]
}, {
title: 'dropdown-menu-item-2',
subMenuItems: [{
title: 'dropdown-submenu-item-1',
action: function () {
console.log('dropdown-menu-item-2-sub-menu-1 clicked')
}
}]
}]
}]
});
deleteCustomCard(data)
Removes a custom Card from the Work Card Area in Workspaces. This method accepts the following parameters:
data (required): A JavaScript Object used to configure the content, behaviour and look of the Custom Card
The data object passed to deleteCustomCard method can contain the following properties...
createCustomStatePanel(data)
This method allows 3rd party developers to create a custom state panel. The custom state panel can be customized to display a
title, color and timer, with the option to add up to 5 channel icons. The custom state panel will match the display of the existing
State panel in the footer (i.e. compressed and uncompressed layouts). When a custom state panel is being displayed, the standard
state panel will not be displayed.
Creates a custom state panel that will be displayed in the footer area in Workspaces. This method accepts the following
parameters:
data (required): A JavaScript Object used to configure the content, behaviour and look of the Custom State Panel
Note: Only one instance of a Custom State Panel can exist in Workspaces at any given time.
color string No Class name of color to use for Custom State Panel
59
Widget API Methods
readyIcon string Yes The icon to display when the channel is ready
notReadyIcon string Yes The icon to display when the channel is not ready
reasonCode string No Displayed as part of the icon tooltip when the channel is not ready
api.createCustomStatePanel({
timer: true,
color: 'blue',
title: 'Awaiting Nailup Call',
reasonCodes: ['Break', 'Lunch', 'Training'],
mandatoryCodes: true,
channels : [
{readyIcon: 'aoc-chat', notReadyIcon: 'aoc-chat-missed', ready: true, name: 'Chat'},
{readyIcon: 'aoc-email', notReadyIcon: 'aoc-email-missed', ready: false, name: 'Email', reasonCode: 'Exam
ple Reason Code'}
],
});
updateCustomStatePanel(data)
Updates a custom state panel that will be displayed in the footer area in Workspaces. This method accepts the following
parameters:
data (required): A JavaScript Object used to configure the content, behaviour and look of the Custom State Panel
Note: Only one instance of a Custom State Panel can exist in Workspaces at any given time.
color string No Class name of color to use for Custom State Panel
60
Widget API Methods
readyIcon string Yes The icon to display when the channel is ready
notReadyIcon string Yes The icon to display when the channel is not ready
reasonCode string No Displayed in the icon tooltip when the channel is not ready
api.updateCustomStatePanel({
timer: true,
color: 'blue',
title: 'Awaiting Nailup Call',
reasonCodes: ['Break', 'Lunch', 'Training'],
mandatoryCodes: true,
channels : [
{readyIcon: 'aoc-chat', notReadyIcon: 'aoc-chat-missed', ready: true, name: 'Chat'},
{readyIcon: 'aoc-email', notReadyIcon: 'aoc-email-missed', ready: false, name: 'Email', reasonCode: 'Exam
ple Reason Code'}
],
});
deleteCustomStatePanel()
Removes a custom state panel from the footer area in Workspaces.
api.deleteCustomStatePanel();
updateMenuItems(data, id)
Updates the menu items and submenu items contained inside a context menu button on a custom card. This method is
intended to be called from within an action callback on a button object. Context menu buttons get their unique id passed to
the action callback so that it can be passed to the updateMenuItems api function.
Note: There is an 8 second timeout on this update function. If the data does not get returned from the 3rd party widget
through to the widget API within 8 seconds of the button click, the menu will not load the items and will display 'Unable to
load menu items'.
data (required): An array of menu item JavaScript Objects used to configure the menu content.
id (required): The id of the context menu button that was clicked. This property is passed to the action property
function. See below example:
61
Widget API Methods
action function No Callback executed when menu item has been clicked
var data = [{
title: 'My Team',
tooltip: 'Team members',
subMenuItems: [{
title: 'Ian Power',
action: function (data) {
api.sendNotification('info', data.title + ' pressed');
}
},{
title: 'Stephen Dunphy',
action: function (data) {
api.sendNotification('info', data.title + ' pressed');
}
},{
title: 'Cathal Jackson',
action: function (data) {
api.sendNotification('info', data.title + ' pressed');
}
}],
},
{
title: 'Disposition Codes',
tooltip: 'Disposition Codes',
subMenuItems: [{
title: 'Callback Customer',
tooltip: '999',
action: function (data) {
api.sendNotification('info', data.title + ' pressed');
}
},{
title: 'Discount Offered',
tooltip: '766',
action: function (data) {
api.sendNotification('info', data.title + ' pressed');
}
}],
}
];
searchEnterpriseDirectory(text)
Searches the enterprise directory (LDAP) for contacts.
62
Widget API Methods
This method will only execute if the enterprise directory is configured correctly. See the
api.isEnterpriseContactsServiceAvailable() method, onEnterpriseServiceAvailableEvent and
Note: If multiple widgets using this method are added to the same layout (e.g Home, Voice, Email etc.), each widget in the
layout will receive the same onEnterpriseContactsReceivedEvent event data. However, each interaction layout will receive
unique event data. For example if I click on the one voice work card and search via a widget, then click on a seperate voice
work card, each of the two layouts will retain their own contact search state.
text: The search text. You may search by name, email address or department.
isEnterpriseContactsServiceAvailable()
Checks if the enterprise directory contacts search is available to make a search.
This will return false if the AADS url is not set in System Manager or an invalid url has been used. Otherwise it will return
true.
If this returns false the widget should react to ensure the Agent is not allowed to perform a search from the widget. i.e
search field should be disabled
unregister
This method can be called during the clean-up stage to unregister and unload the current widget.
api.unregister();
startWork()
Logs in an agent and puts them into a Ready state.
This method will only execute if the capabilities.canLogin capability is set to true . Please see Capabilities for more
information.
63
Widget API Methods
// Start Work
api.startWork();
startWorkNotReady()
Logs in an agent and puts them into a Not Ready state.
This method will only execute if the capabilities.canLogin capability is set to true . Please see Capabilities for more
information.
setAgentReady()
Puts an agent into a Ready state
This method will only execute if the capabilities.canSetReady capability is set to true . Please see Capabilities for
more information.
setAgentACW()
Puts an agent into an After Contact Work state
Note: This is an Elite only feature and will not work on Oceana environments. The 'Enable After Contact Work' setting
must also be enabled through the Workspaces Administrator Settings for this method to execute. This method also relies on
capabilities and will only execute if the capabilities.canSetAfterContactWork capability is set to true . Please see
Capabilities for more information.
finishWork()
Logs out an Agent (Does not exit Workspaces) and puts them into a Connected state
64
Widget API Methods
This method will only execute if the capabilities.canLogout capability is set to true . Please see Capabilities for more
information.
additionalWork(code)
Puts an agent into Additional Work mode
This method will only execute if the capabilities.canSetNotReady capability is set to true . Please see Capabilities for
more information.
code: The additional work code to put agent into Additional Work mode.
// Put agent into Additional Work mode with Additional Work Code
var code = api.getAdditionalWorkCodes()[0];
api.additionalWork(code);
setAgentNotReady(code)
Puts an agent into a Not Ready state with a Not Ready Reason Code
This method will only execute if the capabilities.canSetNotReady capability is set to true . Please see Capabilities for
more information.
bidi(element)
If element is not specified, returns direction of the whole document ('ltr' or 'rtl')
65
Widget API Methods
forceReload()
This method forces page reload without showing dialog box
setFocus(interactionId)
This method sets focus on interaction
66
Widget API Events
Please note, events marked as 'Requires Interaction' require an interaction context. Any Widget leveraging these events will
need to be placed on an Interaction related tab (e.g. Customer Details).
onInteractionEvent
This event is triggered when a new work card (interaction) appears in Workspaces. It is also triggered each time the
interaction is updated.
The state property can be used to determine what state the interaction is currently in (e.g ALERTING, ACTIVE,
HELD).
Payload
{
"id": "bffae854-9219-4cfc-9fd3-7125f2e76844",
"workRequestId": "00142002901551796576",
"externalInteractionId": "14221",
"channel": "VOICE",
"state": "ALERTING",
"stateReason": "DEFAULT",
"interactionType": "CALLED",
"title": "Stella Pavlova",
"topic": "Support",
"topicId": "3007",
"skill": "IT",
"skillId": "3009",
"direction": "INCOMING",
"isCustomerInteraction": false,
"isWebRtcCall": false,
"userToUserInfo": "172917",
"isConsult": false,
"workCode": "7277",
"originatingAddress": "14225",
67
Widget API Events
"destinationAddress": "14221",
"contactId": "00142002901551796576"
}
onChannelStatusUpdateEvent
This event is triggered when the status of a channel on a Custom State Panel gets updated.
Payload
{
"name": "Chat"
"notReadyIcon": "aoc-chat-missed"
"ready": false
"readyIcon": "aoc-chat"
"reasonCode": "Lunch"
}
onUserTypingEvent
This event is triggered while user is typing
Payload
{
"participantType": "CUSTOMER",
"participantName": "Test User",
"participantAddress": "1001",
"muted": false,
"isSelf": true
68
Widget API Events
onFileUploadEvent
This event is triggered after a file upload to the server has been completed.
Payload
{
"attachments": [
{
"partId": "5399B8DF-7038-42B6-9F67-64B9C178D132",
"mimeType": "image/jpeg",
"name": "test_img.JPG",
"size": 8233,
"address":
"http://localhost/services/AgentControllerService/attachment/5399B8DF-7038-42B6-
9F67-64B9C178D132"
}
],
"message": {
"messageId": "09188b9c-1870-4e47-9c23-9728559d430a",
"interactionMediaId": "81a9ed17-1f1e-4b5e-bf3d-273ad638b01f",
"subject": null,
"body": "",
"arrivalDate": "1554475193536",
"lastModifiedDate": "",
"receivedFrom": {
"participantType": "AGENT",
"participantSubtype": null,
"participantName": "Test Agent",
"participantAddress": "(503) 421-9800",
"muted": false,
"isSelf": true
},
"messageEvent": null,
"flags": {
"sensitivity": "PUBLIC",
"importance": "NORMAL",
"encoding": "PLAIN",
"doNotForward": false
69
Widget API Events
},
"parts": [
{
"partId": "5399B8DF-7038-42B6-9F67-64B9C178D132",
"mimeType": "image/jpeg",
"name": "test_img.JPG",
"size": 8233,
"address":
"http://localhost/services/AgentControllerService/attachment/5399B8DF-7038-42B6-
9F67-64B9C178D132"
}
],
"sendTo": [],
"type": "WEBCHAT",
"chatMessageEvent": {
"type": null,
"subject": "",
"participants": [
{
"participantType": "AGENT",
"participantSubtype": null,
"participantName": "Test Agent",
"participantAddress": "(503) 421-9800",
"muted": false,
"isSelf": true
},
{
"participantType": "CUSTOMER",
"participantSubtype": null,
"participantName": "user test",
"participantAddress": "test@customer.com",
"muted": false,
"isSelf": false
}
],
"chatEventType": "TRANSFERRED_FILE"
},
"customData": null,
"sensitivity": "PUBLIC",
"importance": "NORMAL"
}
}
onEmailAttachmentUploadEvent
This event is triggered after a email attachment upload to the server has been completed.
70
Widget API Events
Payload
{
"attachments": [
{
"partId": "5399B8DF-7038-42B6-9F67-64B9C178D132",
"mimeType": "image/jpeg",
"name": "test_img.JPG",
"size": 8233,
"address":
"http://localhost/services/AgentControllerService/attachment/5399B8DF-7038-42B6-
9F67-64B9C178D132"
}
]
}
onFileTransferInitiatedEvent
This event is triggered when the customer starts downloading the file.
Payload
{
"attachment": {
"partId": "5399B8DF-7038-42B6-9F67-64B9C178D132",
"mimeType": "image/jpeg",
"name": "test_img.JPG",
"size": 8233,
"address":
"http://localhost/services/AgentControllerService/attachment/5399B8DF-7038-42B6-
9F67-64B9C178D132"
},
"message": {
"messageId": "04b119a8-765a-410f-bdbd-45bf00858107",
"interactionMediaId": "81a9ed17-1f1e-4b5e-bf3d-273ad638b01f",
"subject": null,
71
Widget API Events
"body": null,
"arrivalDate": "0",
"lastModifiedDate": "",
"receivedFrom": {
"participantType": "CUSTOMER",
"participantSubtype": null,
"participantName": "user test",
"participantAddress": "test@customer.com",
"muted": false,
"isSelf": false
},
"messageEvent": null,
"flags": {
"sensitivity": "PUBLIC",
"importance": "NORMAL",
"encoding": "PLAIN",
"doNotForward": false
},
"parts": [
{
"partId": "5399B8DF-7038-42B6-9F67-64B9C178D132",
"mimeType": "image/jpeg",
"name": "test_img.JPG",
"size": 8233,
"address":
"http://localhost/services/AgentControllerService/attachment/5399B8DF-7038-42B6-
9F67-64B9C178D132"
}
],
"sendTo": [],
"type": "WEBCHAT",
"chatMessageEvent": {
"type": null,
"subject": "",
"participants": [
{
"participantType": "AGENT",
"participantSubtype": null,
"participantName": "Test Agent",
"participantAddress": "(503) 421-9800",
"muted": false,
"isSelf": true
},
{
"participantType": "CUSTOMER",
"participantSubtype": null,
"participantName": "user test",
"participantAddress": "test@customer.com",
"muted": false,
"isSelf": false
}
72
Widget API Events
],
"chatEventType": "CUSTOMER_DOWNLOAD_INITIATED"
},
"customData": null,
"sensitivity": "PUBLIC",
"importance": "NORMAL"
}
}
onFileTransferCompleteEvent
This event is triggered when the file is fully transferred.
Payload
{
"attachment": {
"partId": "19285BFC-09CA-442E-8823-AB0C9A705F71",
"mimeType": "image/jpeg",
"name": "test_img.JPG",
"size": 8233,
"address":
"http://localhost/services/AgentControllerService/attachment/19285BFC-09CA-442E-
8823-AB0C9A705F71"
},
"message": {
"messageId": "775fa9e0-71a2-44a9-8325-6eade9ceae6c",
"interactionMediaId": "81a9ed17-1f1e-4b5e-bf3d-273ad638b01f",
"subject": null,
"body": null,
"arrivalDate": "0",
"lastModifiedDate": "",
"receivedFrom": {
"participantType": "CUSTOMER",
"participantSubtype": null,
"participantName": "user test",
"participantAddress": "test@customer.com",
"muted": false,
"isSelf": false
},
"messageEvent": null,
73
Widget API Events
"flags": {
"sensitivity": "PUBLIC",
"importance": "NORMAL",
"encoding": "PLAIN",
"doNotForward": false
},
"parts": [
{
"partId": "19285BFC-09CA-442E-8823-AB0C9A705F71",
"mimeType": "image/jpeg",
"name": "test_img.JPG",
"size": 8233,
"address":
"http://localhost/services/AgentControllerService/attachment/19285BFC-09CA-442E-
8823-AB0C9A705F71"
}
],
"sendTo": [],
"type": "WEBCHAT",
"chatMessageEvent": {
"type": null,
"subject": "",
"participants": [
{
"participantType": "AGENT",
"participantSubtype": null,
"participantName": "Test Agent",
"participantAddress": "(503) 421-9800",
"muted": false,
"isSelf": true
},
{
"participantType": "CUSTOMER",
"participantSubtype": null,
"participantName": "user test",
"participantAddress": "test@customer.com",
"muted": false,
"isSelf": false
}
],
"chatEventType": "CUSTOMER_DOWNLOAD_COMPLETE"
},
"customData": null,
"sensitivity": "PUBLIC",
"importance": "NORMAL"
}
}
74
Widget API Events
onInteractionEndedEvent
This event is triggered when a work card (interaction) has been ended. This occurs for all interaction types.
Note: This event is only useful when ACW is enabled so that the widget can be used to trigger some custom logic when an
interaction has ended. Otherwise, as per usual, the widget will be destroyed once the interaction has ended.
Note: This client side only event is quite limited as the backend does not support an ENDED interaction state, only
ALERTING, ACTIVE and HELD. Therefore, you will see that the event is triggered in the following scenarios for Voice:
Payload
{
"id": "bffae854-9219-4cfc-9fd3-7125f2e76844",
"workRequestId": "00142002901551796576",
"externalInteractionId": "14221",
"channel": "VOICE",
"state": "ACTIVE",
"stateReason": "DEFAULT",
"interactionType": "CALLED",
"title": "Stella Pavlova",
"topic": "Support",
"topicId": "3007",
"skill": "IT",
"skillId": "3009",
"direction": "INCOMING",
"isCustomerInteraction": false,
"isWebRtcCall": false,
"userToUserInfo": "172917",
"isConsult": false,
"workCode": "7277",
"originatingAddress": "14225",
"destinationAddress": "14221",
"contactId": "00142002901551796576"
}
75
Widget API Events
onCRMDataEvent
If CRM integration is enabled and configured in Workspaces this event is triggered when there is CRM customer data
available for the current work card interaction.
api.onDataEvent('onCRMDataEvent', callback);
function callback(data) {
// do something with event data
}
Payload
{
"attributes": {
"type": "Contact",
"url": "/services/data/v34.0/sobjects/Contact/00358000001aSR2AAM"
},
"birth_date": "1951-10-18",
"created_at": "2015-12-29T22:03:13.000+0000",
"description": null,
"email": "bond_john@grandhotels.com",
"phone_fax": "(312) 596-1500",
"first_name": "John",
"phone_home": "(312) 596-1000",
"user_id": "00358000001aSR2AAM",
"last_name": "Sutherland",
"address": {
"city": null,
"country": null,
"countryCode": null,
"geocodeAccuracy": null,
"latitude": null,
"longitude": null,
"postalCode": null,
"state": null,
"stateCode": null,
"street": "2334 N. Michigan Avenue, Suite 1500\r\nChicago, IL 60601, USA"
},
"address_city": null,
"address_country": null,
"geo_latitude": null,
"geo_longitude": null,
"address_zip": null,
"address_state": null,
"address_street": "2334 N. Michigan Avenue, Suite 1500\r\nChicago, IL 60601,
USA",
"phone_mobile": "(312) 596-1563",
"name": "John Sutherland",
"phone_primary": "(312) 596-1000",
"avatar_url": "/services/images/photo/00358000001aSR2AAM",
"title": "VP, Facilities",
76
Widget API Events
"id": "6625a233-abbb-4d0d-9c08-9c421526c614",
"cases": [
{
"attributes": {
"type": "Case",
"url": "/services/data/v34.0/sobjects/Case/50058000000o6e5AAA"
},
"case_number": "00001013",
"user_id": "00358000001aSR2AAM",
"created_at": "2015-12-29T22:03:13.000+0000",
"case_closed": true,
"case_deleted": false,
"case_escalated": false,
"case_origin": "Web",
"case_priority": "Medium",
"case_reason": "Equipment Design",
"case_status": "Closed",
"case_subject": "Starting up generator consumes excessive power",
"case_type": "Other"
},
{
"attributes": {
"type": "Case",
"url": "/services/data/v34.0/sobjects/Case/50058000000o6e6AAA"
},
"case_number": "00001014",
"user_id": "00358000001aSR2AAM",
"created_at": "2015-12-29T22:03:13.000+0000",
"case_closed": true,
"case_deleted": false,
"case_escalated": false,
"case_origin": "Phone",
"case_priority": "High",
"case_reason": "Installation",
"case_status": "Closed",
"case_subject": "Delay in installation; spare parts unavailable",
"case_type": "Other"
},
{
"attributes": {
"type": "Case",
"url": "/services/data/v34.0/sobjects/Case/50058000000x7z1AAA"
},
"case_number": "00001044",
"user_id": "00358000001aSR2AAM",
"created_at": "2016-05-13T13:34:03.000+0000",
"case_closed": false,
"case_deleted": false,
"case_escalated": false,
"case_origin": "Email",
"case_priority": "Medium",
77
Widget API Events
"case_reason": null,
"case_status": "New",
"case_subject": "Power generation below stated level",
"case_type": null
},
{
"attributes": {
"type": "Case",
"url": "/services/data/v34.0/sobjects/Case/50058000000x84zAAA"
},
"case_number": "00001079",
"user_id": "00358000001aSR2AAM",
"created_at": "2016-05-13T14:04:01.000+0000",
"case_closed": false,
"case_deleted": false,
"case_escalated": false,
"case_origin": "Phone",
"case_priority": "High",
"case_reason": "Breakdown",
"case_status": "Escalated",
"case_subject": "Frequent mechanical breakdown",
"case_type": "Mechanical"
},
{
"attributes": {
"type": "Case",
"url": "/services/data/v34.0/sobjects/Case/50058000000x80sAAA"
},
"case_number": "00001060",
"user_id": "00358000001aSR2AAM",
"created_at": "2016-05-13T13:46:30.000+0000",
"case_closed": false,
"case_deleted": false,
"case_escalated": false,
"case_origin": "Phone",
"case_priority": "High",
"case_reason": "Equipment Design",
"case_status": "Working",
"case_subject": "Motor design hindering performance",
"case_type": "Mechanical"
},
{
"attributes": {
"type": "Case",
"url": "/services/data/v34.0/sobjects/Case/50058000000x7wbAAA"
},
"case_number": "00001037",
"user_id": "00358000001aSR2AAM",
"created_at": "2016-05-13T13:22:44.000+0000",
"case_closed": false,
"case_deleted": false,
78
Widget API Events
"case_escalated": false,
"case_origin": "Phone",
"case_priority": "Low",
"case_reason": null,
"case_status": "New",
"case_subject": "Maintenance guidelines for generator unclear",
"case_type": null
},
{
"attributes": {
"type": "Case",
"url": "/services/data/v34.0/sobjects/Case/50058000000x89pAAA"
},
"case_number": "00001096",
"user_id": "00358000001aSR2AAM",
"created_at": "2016-05-13T14:49:40.000+0000",
"case_closed": false,
"case_deleted": false,
"case_escalated": false,
"case_origin": "Phone",
"case_priority": "Low",
"case_reason": null,
"case_status": "New",
"case_subject": "Customer reported another part DRP23423OD failed during
test",
"case_type": null
},
{
"attributes": {
"type": "Case",
"url": "/services/data/v34.0/sobjects/Case/50058000000x8AnAAI"
},
"case_number": "00001104",
"user_id": "00358000001aSR2AAM",
"created_at": "2016-05-13T14:55:50.000+0000",
"case_closed": false,
"case_deleted": false,
"case_escalated": false,
"case_origin": "Email",
"case_priority": "Low",
"case_reason": null,
"case_status": "Working",
"case_subject": "Component part DPR3423DOD was shipped to customer",
"case_type": null
},
{
"attributes": {
"type": "Case",
"url": "/services/data/v34.0/sobjects/Case/50058000000x7zuAAA"
},
"case_number": "00001052",
79
Widget API Events
"user_id": "00358000001aSR2AAM",
"created_at": "2016-05-13T13:39:55.000+0000",
"case_closed": false,
"case_deleted": false,
"case_escalated": false,
"case_origin": "Web",
"case_priority": "Low",
"case_reason": "Feedback",
"case_status": "New",
"case_subject": "Easy installation process",
"case_type": "Other"
},
{
"attributes": {
"type": "Case",
"url": "/services/data/v34.0/sobjects/Case/50058000000x891AAA"
},
"case_number": "00001089",
"user_id": "00358000001aSR2AAM",
"created_at": "2016-05-13T14:41:54.000+0000",
"case_closed": false,
"case_deleted": false,
"case_escalated": false,
"case_origin": "Email",
"case_priority": "Medium",
"case_reason": null,
"case_status": "New",
"case_subject": "Wrong component part ordered from manufacturer",
"case_type": null
},
{
"attributes": {
"type": "Case",
"url": "/services/data/v34.0/sobjects/Case/50058000000x83XAAQ"
},
"case_number": "00001072",
"user_id": "00358000001aSR2AAM",
"created_at": "2016-05-13T13:57:03.000+0000",
"case_closed": false,
"case_deleted": false,
"case_escalated": false,
"case_origin": "Email",
"case_priority": "Medium",
"case_reason": "Installation",
"case_status": "Escalated",
"case_subject": "Delay in installation; spare parts unavailable",
"case_type": "Other"
}
]
}
80
Widget API Events
onContextDataEvent
This event is triggered when customer and context data is available in Chat, SMS, Email and Social work cards. This event
can be used to obtain customer details and customer history data from Chat, SMS, Email and Social interactions.
Note: Here you can retrieve max allowed characters limitations (which is best to manage in your widget) using
clientValidation array passed within common data object. Depending on your interaction channel (Chat, SMS or
Social) you're going to get different validation entries with data.type field equal to WEBCHAT_MAX_CHAR , SMS_MAX_CHAR or
SOCIAL_MAX_CHAR respectively.
api.onDataEvent('onContextDataEvent', callback);
function callback(data) {
// do something with event data
}
Payload
{
"clientValidation": [
{
"data": {
"type": "WEBCHAT_MAX_CHAR",
"value": 10000
},
"type": "CLIENT_VALIDATION",
"description": "",
"id": "6194c3ef-676d-4743-a2a5-a86f5591ce52"
}
]
"customerDetails": [
{
"type": "CUSTOMER_DETAILS",
"data": {
"name": "name1",
"firstName": "firstName1",
"lastName": "lastName1",
"email": "customer@companyxyz.com",
"phonePrimary": "phonePrimary1",
"phoneHome": "phoneHome1",
"phoneMobile": "phoneMobile1",
"phoneFax": "phoneFax1",
"birthDate": "birthDate1",
"address": "address1",
"addressStreet": "addressStreet1",
"addressState": "addressState1",
"addressZip": "addressZip1",
"addressCity": "addressCity1",
"addressCountry": "addressCountry1",
81
Widget API Events
"geoLatitude": "geoLatitude1",
"geoLongitude": "geoLongitude1",
"avatarUrl": "avatarUrl1",
"title": "title1",
"description": "description1",
"department": "department1",
"createdDate": "2017-09-19T12:45:10.763Z"
},
"description": "",
"id": "87e79cf5-cfee-4960-b776-fa449ae1a98e"
}
],
"customerHistory": [
{
"type": "CUSTOMER_HISTORY",
"data": {
"status": "status1",
"subject": "subject1",
"priority": "priority1",
"type": "type1",
"href":
"https://10.134.146.163/services/AgentControllerService/gila/api/customerhistory/12
234",
"createdDate": "2017-09-19T12:45:10.763Z"
},
"description": "",
"id": "f514d6eb-58c3-4750-bb26-f0840b76dd37"
},
{
"type": "CUSTOMER_HISTORY",
"data": {
"status": "status2",
"subject": "subject2",
"priority": "priority2",
"type": "type2",
"href":
"https://10.134.146.163/services/AgentControllerService/gila/api/customerhistory/12
771",
"action": "action1",
"id": "id1",
"createdDate": "2017-09-19T12:45:10.763Z"
},
"description": "",
"id": "96d633e2-9f26-40b9-bf9c-3fbf5241dec3"
}
],
"contextStore": [
{
"type": "CONTEXT_STORE",
"data": "716391",
"description": "Prompted Digits Data",
82
Widget API Events
"id": "a9a65201-0c72-4c1f-8735-9635f064a016"
}
],
"campaignScripts": [
{
"type": "CAMPAIGN_SCRIPT",
"description": "",
"id": "a98416b5-f071-415c-9dfb-5e04af2c70cf",
"data": "https://irishtimes.com"
},
],
"cobrowse": [
{
"type": "COBROWSE",
"id": "45d8c424-796c-466d-8846-41a73c0f43b5",
"data": {
"url": "http://10.134.146.71/services/cobrowse/customer/index.html",
"description": "Cobrowse welcome page"
}
},
],
"fromAddresses": [
{
"type": "ORIGINATOR",
"data": {
"address": "info@info.com",
"description": "text1"
},
"description": "",
"id": "9e9c21d6-dc9e-4603-9046-fe8678d18b8a",
},
{
"type": "ORIGINATOR",
"data": {
"address": "sales@sales.com",
"description": "text2"
},
"description": "",
"id": "863bb132-912c-4013-93e3-8c2af6062dd2",
},
"id": "3bcac1e6-bb7a-4a51-91e7-9777447b70a9",
"interactionId": "db07dc7c-11e6-4f93-9abe-7924bb90b46f"
],
"pagePushUrl": [
{
"type": "PAGE_PUSH",
"data": {
"description": "description1",
"url": "url1"
},
"id": "dcb5e8ea-0d24-42fc-97ab-524f60e1991d",
83
Widget API Events
},
{
"type": "PAGE_PUSH",
"data": {
"description": "description2",
"url": "url2"
},
"id": "3d47b685-1167-44f0-8912-1d06d6a8bc21"
}
],
"screenPop": [
{
"type": "SCREEN_POP",
"id": "b6a9bc1c-ece7-4379-8c39-aaf5d46452c7",
"data": {
"action": "NONE"
"name": "Maps"
"scope": "INTERNAL"
"trigger": "ACTIVE"
"uri": "https://www.google.com/maps/embed?
pb=!1m18!1m12!1m3!1d152660.05036353657!2d-9.188836092077002!3d53"
}
},
{
"type": "SCREEN_POP",
"id": "7eb9082e-9bcf-45a9-a033-406a16961303",
"data": {
"action": "CLOSE_ON_END"
"name": "Google"
"scope": "INTERNAL"
"trigger": "ACTIVE"
"uri": "http://www.google.com"
}
},
],
"suggestedPhrase": [
{
"type": "SUGGESTED_PHRASE",
"data": {
"name": "name1",
"text": "text1"
},
"description"": "",
"id": "962641e5-544c-4eff-9321-3546a0511f0c",
},
{
"type": "SUGGESTED_PHRASE",
"data": {
"name": "name2",
"text": "text2"
},
84
Widget API Events
"description": "",
"id": "78ccd9c3-326f-436b-adb3-3e922f9937b0",
},
],
"Agent ID": "10002"
"Station ID": "1002"
}
onMediaEvent
This event is triggered when an incoming Chat, SMS, Email or Social interaction is accepted by the user
(Agent/Supervisor). This event can be used to obtain Chat, SMS, Email or Social related data such as participants or
previously sent media messages.
api.onDataEvent('onMediaEvent', callback);
function callback(data) {
// do something with event data
}
Payload
{
"interactionId": "803cdebe-a4b9-47d7-b0f6-27fa85dc654c",
"messages": [
{
"messageId": "9DBA8D4C-3BBD-435A-BEFC-031151146AA3",
"interactionMediaId": "02dc3a4c-6bdb-410e-8424-2fc26027884e",
"subject": "",
"body": "I would like to update some details on my car insurance policy.",
"arrivalDate": "2017-12-11T12:47:27.557Z",
"lastModifiedDate": "",
"receivedFrom": {
"participantType": "CUSTOMER",
"participantName": "Josh Davis",
"participantAddress": "(503) 421-9800",
"muted": false,
"isSelf": false
},
"messageEvent": null,
"flags": {
"read": true,
"sensitivity": "CONFIDENTIAL",
"importance": "LOW"
},
"parts": [],
"sendTo": [],
"type": "WEBCHAT",
85
Widget API Events
"chatMessageEvent": {
"subject": "messageEventSubject",
"participants": [
{
"participantType": "AGENT",
"participantName": "Name Steve",
"participantAddress": "1003",
"muted": false,
"isSelf": true
},
{
"participantType": "CUSTOMER",
"participantName": "Josh Davis",
"participantAddress": "(503) 421-9800",
"muted": false,
"isSelf": false
}
],
"chatEventType": "MESSAGE"
},
"read": true,
"sensitivity": "CONFIDENTIAL",
"importance": "LOW"
}
],
"participants": [
{
"participantType": "AGENT",
"participantName": "Name Steve",
"participantAddress": "1003",
"muted": false,
"isSelf": true
},
{
"participantType": "CUSTOMER",
"participantName": "Josh Davis",
"participantAddress": "(503) 421-9800",
"muted": false,
"isSelf": false
}
]
}
onMediaMessageEvent
This event is triggered when incoming Chat, SMS, Email or Social messages are sent to the user (Agent/Supervisor). This
event can be used to obtain Chat, SMS or Social messages and pass them to the widget. In the case of Email, data is
received as a single Email message and it can contain data formatted as text or HTML.
86
Widget API Events
api.onDataEvent('onMediaMessageEvent', callback);
function callback(data) {
scope.chatMessage = data.body;
}
Payload
{
"messageId": "059BB79E-FED2-42A7-9FEC-FC230904B09F",
"interactionMediaId": "67313d2d-18fe-4c4b-a457-662c71eed99a",
"subject": "",
"body": "I would like to update some details on my car insurance policy.",
"arrivalDate": "2017-09-20T12:54:08.064Z",
"lastModifiedDate": "",
"receivedFrom": {
"participantType": "CUSTOMER",
"participantName": "Stella Pavlova",
"participantAddress": "(212) 842-5500",
"muted": false,
"isSelf": false
},
"messageEvent": null,
"flags": {
"read": true,
"sensitivity": "CONFIDENTIAL",
"importance": "LOW"
},
"parts": [],
"sendTo": [],
"type": "WEBCHAT",
"chatMessageEvent": {
"subject": "messageEventSubject",
"participants": [
{
"participantType": "AGENT",
"participantName": "Name Steve",
"participantAddress": "1002",
"muted": false,
"isSelf": true
},
{
"participantType": "CUSTOMER",
"participantName": "Stella Pavlova",
"participantAddress": "(212) 842-5500",
"muted": false,
"isSelf": false
}
],
"chatEventType": "MESSAGE"
},
87
Widget API Events
"read": true,
"sensitivity": "CONFIDENTIAL",
"importance": "LOW"
}
onPagePushUrlEvent
This event is triggered when page push urls are sent from the Suggested Content widget while working on a Chat, SMS or
Social interaction.
api.onDataEvent('onPagePushUrlEvent', callback);
function callback(data) {
scope.pagePushUrl = data.body;
}
Payload
{
"messageId": "0ABE338F-50E7-4A80-AA8D-CDD7C6793AFC",
"interactionMediaId": "28b07b33-f916-4be9-a07a-c7a9d0a1afd1",
"subject": "",
"body": "https://www.google.com",
"arrivalDate": "2019-02-06T15:42:43.093Z",
"lastModifiedDate": "",
"receivedFrom": {
"participantType": "AGENT",
"participantName": "Agent Chat",
"participantAddress": "1003",
"muted": false,
"isSelf": true
},
"messageEvent": null,
"flags": {
"read": true,
"sensitivity": "PUBLIC",
"importance": "LOW"
},
"parts": [],
"sendTo": [],
"type": "WEBCHAT",
"chatMessageEvent": {
"subject": "messageEventSubject",
"participants": [
{
"participantType": "AGENT",
"participantName": "Agent Chat",
"participantAddress": "1003",
"muted": false,
88
Widget API Events
"isSelf": true
},
{
"participantType": "CUSTOMER",
"participantName": "Pat Stumuller",
"participantAddress": "(014) 427-4427",
"muted": false,
"isSelf": false
}
],
"chatEventType": "PAGE_PUSH"
},
"read": true,
"sensitivity": "PUBLIC",
"importance": "LOW"
}
onAgentStateEvent
This event is triggered whenever the agent state changes. This event provides information to widgets on the current state
and reason codes as well as the agent's current capabilities.
api.onDataEvent('onAgentStateEvent', callback);
function callback(data) {
// do something with event data
}
Payload
{
"state": "NOT_READY_PENDING",
"reasonCode": "999",
"agent": {
"capabilities": {
"canDeactivate": false,
"canLogin": false,
"canLogout": true,
"canMentorChat": false,
"canMentorSMS": false,
"canSetAfterContactWork": false,
"canSetNotReady": false,
"canSetWorkMode": false
}
}
}
89
Widget API Events
onNavigationEvent
This event is triggered whenever an icon in the sidebar is clicked. This event can inform widgets whenever the user
navigates or selects a sidebar icon.
api.onDataEvent('onNavigationEvent', callback);
function callback(data) {
// do something with event data
}
Payload
{
"viewName": "voice",
"context": {
"id": "d4286f6c-c6da-4e96-87e7-297b8d7679db",
"tabId": "aoc-warning-filled",
"userType": "AGENT"
},
"tab": "tab__ddf8bfc6-2604-4113-b7f1-63ba33c1da9b"
}
onLocaleUpdatedEvent
This event is triggered whenever the language setting changes in Workspaces.
api.onDataEvent('onLocaleUpdatedEvent', callback);
function callback(data) {
// do something with event data
}
Payload
{
"locale": "EN"
}
onBeforeTextDirectionChangedEvent
This event is triggered immediately before the document text direction changes (e.g. in case Agent switched from English
to Arabic language).
api.onDataEvent('onBeforeTextDirectionChangedEvent', callback);
function callback(data) {
console.log('Text direction is going to be changed from ', data.from, ' to ', data.to);
}
90
Widget API Events
Payload
{
"from": "ltr",
"to": "rtl"
}
onStylesheetsReadyEvent
This event is triggered whenever the bidi-alternative stylesheets (re)loading has completed.
This event is triggered only when actual document text direction changes, i.e. when agent switches from any LTR language
(EN, FR, RU) to any RTL language (AR, HE) and vice-versa. It won't be triggered if text direction of considered languages
remains the same.
Note: this event is triggered even if your widget doesn't use separated styles for LTR and RTL as far as Workspaces itself
has built-in bidi-alternative stylesheets.
api.onDataEvent('onStylesheetsReadyEvent', callback);
function callback() {
console.log('All bidi-alternative stylesheets are loaded!');
}
onObserveEvent
This event is triggered to indicate that the current interaction is being observed. This is limited to AWFOS and not to be
confused with supervisor observing of chats / sms.
api.onDataEvent('onObserveEvent', callback);
function callback(data) {
// do something with event data
}
Payload
{
id: '3ef1d1b9-a19a-485e-be17-94a16f523b75',
channel: 'Voice'
}
onCapabilitiesEvent
This event is triggered when the agent or interaction capabilities have been updated.
Note: The getCapabilities API method can also be used to retrieve the latest capabilities at any time.
api.onDataEvent('onCapabilitiesEvent', callback);
function callback(data) {
91
Widget API Events
Payload
{
interaction: {
canAccept: false,
canEnd: true,
canHold: true,
canUnhold: false,
canSingleStepTransfer: true,
canConsult: true,
canTransferComplete: false,
canConferenceComplete: false,
canSetDispositionCode: true,
canSetWorkCode: true,
canSendDtmf: true,
canSendMessage: true,
},
channels: {
canStartVoiceInteraction: true
}
}
onRequestServicesEvent
This event is triggered when an interaction requests its transfer to service list.
api.onDataEvent('onRequestServicesEvent', callback);
function callback() {
// do something when event is triggered
}
onMessageEvent
This event is triggered when other widgets broadcast a data message by using the sendMessage API method. This event is
used primarily for inter-widget communication.
This event will return anything that is sent via the sendMessage API method
api.onDataEvent('onMessageEvent', callback);
function callback(data) {
// do something with event data
}
92
Widget API Events
onTeamMemberEvent
This event is triggered when an agent is expanded in the supervisor dashboard. The object that is returned from this event
is the expanded agent object.
api.onDataEvent('onTeamMemberEvent', callback);
function callback(data) {
// do something with team member data
}
Payload
{
"userHandle":"mRuane",
"state":"READY",
"capabilities":{
"canLogin":false,
"canSetNotReady":true,
"canLogout":true,
"canSetReady":false,
"canDeactivate":false,
"canSupervisorSetReady":false,
"canSupervisorSetNotReady":true,
"canSupervisorLogout":true
},
"interactions":[
{
"id":"738fbd59-3e07-47fd-af4e-a280c8a08c7a",
"state":"ACTIVE",
"channel":"WEBCHAT",
"direction":"INCOMING",
"created":"2018-05-01T12:39:58.901Z",
"establishedTime":"2018-05-01T12:39:58.901Z",
"topic":"Oceana Service",
"isCustomerInteraction":true,
"originatingAddress":"(014) 427-4427",
"destinationAddress":"1001",
"workRequestId":"0074518545435242185724",
"capabilities":{
"canReject":false,
"canSetUui":true,
"canConsult":false,
"canTransferComplete":false,
"canEnd":true,
"canConferenceComplete":false,
"canSetWorkCode":true,
"canSetDispositionCode":true,
"canExtendACW":false,
"canSingleStepTransfer":true,
"canSingleStepTransferToService":true,
"canUnmute":false,
"canUnhold":false,
93
Widget API Events
"canCompleteACW":false,
"canMute":false,
"canSetACW":true,
"canHold":false,
"canIgnore":false,
"canAccept":false,
"canSendDtmf":false,
"canForward":true,
"canSendMessage":true,
"canObserve":true,
"canBarge":false,
"canCoach":false,
"canReply":true,
"canSingleStepConference":false,
"canDefer":false
},
"isObserved":false
}
],
"channels":[
{
"state":"READY",
"stateReason":"DEFAULT",
"reasonCode":"",
"providerName":"ngdemc",
"capabilities":{
"canSetCallForwarding":true,
"canCancelCallForwarding":true,
"canStartInteraction":true,
"canStartSupervisorInteraction":true
},
"channelType":"VOICE",
"id":"ad1cbec8-fe15-482b-8085-7d9c7f13f761",
"$$hashKey":"object:644"
},
{
"state":"READY",
"stateReason":"DEFAULT",
"reasonCode":"",
"providerName":"ngdemc",
"capabilities":{
"canSetCallForwarding":false,
"canCancelCallForwarding":false,
"canStartInteraction":false,
"canStartSupervisorInteraction":false
},
"channelType":"WEBCHAT",
"id":"0aeed53d-a50d-46bf-8e7d-681164d90746",
"$$hashKey":"object:645"
},
{
94
Widget API Events
"state":"READY",
"stateReason":"DEFAULT",
"reasonCode":"",
"providerName":"ngdemc",
"capabilities":{
"canSetCallForwarding":false,
"canCancelCallForwarding":false,
"canStartInteraction":true,
"canStartSupervisorInteraction":false,
"canRetrieveInteractions":false
},
"channelType":"EMAIL",
"id":"8cc86248-c214-4b27-81b7-c4ae103b637b",
"$$hashKey":"object:639"
},
{
"state":"READY",
"stateReason":"DEFAULT",
"reasonCode":"",
"providerName":"ngdemc",
"capabilities":{
"canSetCallForwarding":false,
"canCancelCallForwarding":false,
"canStartInteraction":false,
"canStartSupervisorInteraction":false
},
"channelType":"SMS",
"id":"2872a9e0-0edc-4126-9b1c-05b22b2c8beb",
"$$hashKey":"object:641"
},
{
"state":"READY",
"stateReason":"DEFAULT",
"reasonCode":"",
"providerName":"ngdemc",
"capabilities":{
"canSetCallForwarding":false,
"canCancelCallForwarding":false,
"canStartInteraction":false,
"canStartSupervisorInteraction":false
},
"channelType":"SOCIAL",
"id":"bb58757e-6115-4ca8-bb57-9075d32fa697",
"$$hashKey":"object:642"
},
{
"state":"READY",
"stateReason":"DEFAULT",
"reasonCode":"",
"providerName":"ngdemc",
"capabilities":{
95
Widget API Events
"canSetCallForwarding":true,
"canCancelCallForwarding":true,
"canStartInteraction":true,
"canStartSupervisorInteraction":true
},
"channelType":"VIDEO",
"id":"fefef219-05b0-4a46-9ad9-681e8e941edf",
"$$hashKey":"object:643"
},
{
"state":"READY",
"stateReason":"DEFAULT",
"reasonCode":"",
"providerName":"ngdemc",
"capabilities":{
"canSetCallForwarding":true,
"canCancelCallForwarding":true,
"canStartInteraction":true,
"canStartSupervisorInteraction":true
},
"channelType":"GENERIC",
"id":"dc3ad786-adef-4acb-8c56-8689e05dba72",
"$$hashKey":"object:640"
}
]
}
onEnterpriseContactsReceivedEvent
This event is triggered when an Enterprise Directory search has completed and contacts have been received.
Note: This event will return a maximum of 26 results. The Agent must refine in order to find a better match.
api.onDataEvent('onEnterpriseContactsReceivedEvent', callback);
function callback(data) {
scope.contacts = data.contacts;
}
Payload
[
{
id: '123456',
displayName: 'Joe Bloggs',
firstName: 'Joe',
lastName: 'Bloggs',
department: 'Sales',
isFavorite: true,
defaultNumber: '09156761334',
phones: [{
96
Widget API Events
number: '0044568413',
type: 'PHONE_NUMBER_WORK',
isDefault: true
},
{
number: '096879136',
type: 'PHONE_NUMBER_WORK',
isDefault: false
},
{
number: '0871234567',
type: 'PHONE_NUMBER_MOBILE',
isDefault: false
}],
emails: [{
address: 'jbloggs@company.com',
type: 'EMAIL_ADDRESS_WORK',
isDefault: true
}],
address: {
street: 'Rossaveel',
city: 'Galway',
state: 'Galway',
country: 'Ireland',
postalCode: 'H9189918'
}
},
{
id: '56789',
displayName: 'Mo Salah',
firstName: 'Mo',
lastName: 'Salah',
department: 'Sports',
isFavorite: true,
defaultNumber: '0916979143',
phones: [{
number: '0916979143',
type: 'PHONE_NUMBER_WORK',
isDefault: true
}],
emails: [{
address: 'mosalah@lfc.com',
type: 'EMAIL_ADDRESS_WORK',
isDefault: true
}],
address: {
street: 'Anfield Road',
city: 'Liverpool',
state: 'Liverpool',
country: 'UK',
postalCode: 'L40TH'
97
Widget API Events
}
}
]
onEnterpriseServiceAvailableEvent
This event is triggered when the Enterprise Directory service becomes available. Only when this is available should the
Agent be allowed to perform a search.
api.onDataEvent('onEnterpriseServiceAvailableEvent', callback);
function callback() {
// We can now perform a search of the enterprise directory
scope.isEnterpriseContactsServiceAvailable = true;
}
onEnterpriseServiceUnavailableEvent
This event is triggered when the Enterprise Directory service becomes unavailable. When this occurs the Agent should not
be allowed to perform a search from the widget. i.e search field should be disabled
api.onDataEvent('onEnterpriseServiceUnavailableEvent', callback);
function callback() {
// Search of the enterprise directory is no longer available
scope.isEnterpriseContactsServiceAvailable = false;
}
onCustomCardDeletedEvent
This event is triggered when a custom card has been deleted
api.onDataEvent('onCustomCardDeletedEvent', callback);
function callback() {
// do something with the event data
console.log(data);
}
onCardFocusedEvent
This event is triggered when the interaction is focused
98
Widget API Events
api.onDataEvent('onCardFocusedEvent', callback);
function callback(data) {
// We can do something when an interaction is focused
}
onSSOTokenRefreshEvent
This event is triggered when the SSO token is refreshed
api.onDataEvent('onSSOTokenRefreshEvent', callback);
function callback(data) {
// We can do something here with the new token
}
99
Widget Build Tools
Install
Download and unzip the sample-project.zip file:
unzip sample-project.zip
npm install
Usage
Create a widget
Use the following Grunt task to create a new widget:
Build a widget
Use the following Grunt task to build and bundle the widget:
grunt --build="my-widget"
Import a widget
Please see the Widget Manager section for information on how to import a widget.
grunt clean
100
Widget Build Tools
101
Using Sample Library
Install
Download and unzip the sample-library.zip file:
unzip sample-library.zip
npm install
Usage
grunt --build="hello-world"
102
Using Sample Library
103
Hosting Widgets
Hosting Widgets
Hosting the Sample Widget Library
To test your widgets, you need to host the sample widget library using a web server. You can use any standard web server (e.g.
http-server, nginx). You will need to deploy the web server using HTTPS and configure the security certificates appropriately.
If using self-signed certificates, you have to make sure the certificates are installed and trusted on the browser or OS environment.
Otherwise the browser will not trust the self-signed certificate and prevent Workspaces from loading the widgets.
It is also very important that the server is enabled with CORS. You can check how to enable CORS on your web server.
If you host the library on Breeze Snap-in, please refer to 'Administering HTTP CORS security' section in Administering
Avaya Breeze® platform document
If you host the library on Tomcat server, please refer to this instruction: https://tomcat.apache.org/tomcat-7.0-
doc/config/filter.html#CORS_Filter
You can also find more information for different servers on https://www.w3.org/wiki/CORS_Enabled
It is important that the directory hosted is the bundle directory. This is the output destination of the build process used to build the
sample library.
Here is an example using http-server which is a simple web server that can be installed via NodeJS:
# run the web server over HTTPS on port 8443 with CORS enabled
http-server ./sample-library/bundle -p 8443 --cors -S -C cert.pem -K key.pem
By default, http-server will start the server using your local IP address on port 8443. Once running, you should see something like
this:
104
Hosting Widgets
105
Widget Server Configuration
106
Widget Server Configuration
107
Capabilities
Capabilities
The Widget Framework uses the concept of capabilities to indicate the current capability of an Agent to perform an operation.
For example:
Interaction Capabilities
canAccept, canHold, canUnhold, canSendMessage etc.
Agent Capabilities
canLogin, canSetReady, canSetNotReady, canLogout, canSetAdditionalWork etc.
Capabilities are set by the Server, and should be taken as an indication that the operation will succeed if attempted. Please see the
getCapabilities method and onCapabilitiesChangedEvent event for usage.
108
Using Web Components
The attributes that will be applied to your Web Component by Workspaces need to be parsed and passed to the Widget API
constructor.
connectedCallback() {
// Get parameters passed to the web component as attributes by workspaces.
const interactionId = this.getAttribute("interaction-id");
const workRequestId = this.getAttribute("work-request-id");
const externalInteractionId = this.getAttribute("external-interaction-id");
The widget API is created by calling the globally available method NewAvayaWidgetAPI . This method returns a new instance of
the Widget API for use by the calling widget. Once the instance of the widget API has been created using the example above the
widget API can be used as it would normally be used within the AngularJS directive generated by the Widget Framework CLI.
The same rules apply to the below definition as listed here with the following additions:
configuration.files array should contain a single URL pointing to the Web Component source code
109
Using Web Components
The configuration.element property must match what the web component defines in its call to customElements.define
{
"metadata": {
"name": "Agent Component Test",
"description": "This is to test web component for agent state",
"tags": "agent, customer, details, salesforce, CRM, voice",
"version": "",
"date": "2017-01-24T12:01:51.684Z",
"id": "c79c964b-7427-4d5f-9384-ad316e9a3e21"
},
"configuration": {
"external": true,
"enabled": true,
"name": "c79c964b-7427-4d5f-9384-ad316e9a3e21",
"icon": "aoc-home",
"element": "<agent-web-component></agent-web-component>",
"permissions": [],
"shortcuts": [],
"localisation": [],
"files": ["http://localhost:4003/agent-web-component.js"]
}
}
connectedCallback() {
// Get parameters passed to the web component as attributes by context canvas.
const interactionId = this.getAttribute("interaction-id");
const workRequestId = this.getAttribute("work-request-id");
const externalInteractionId = this.getAttribute("external-interaction-id");
div.innerHTML = this.getTemplate();
div.style.height = "100%";
this.style.width = "100%";
this.style.height = "100%";
this.appendChild(div);
}
110
Using Web Components
</div>
</div>
</div>
</div>`;
}
replaceTemplate(data) {
const templateDiv = this.querySelector("#simpleTemplateDiv");
let innerHTML = `<table class="neo-table"><thead>
<th>Attribute</th>
<th>Value</th>
</thead>
<tbody>
<tr>
<td>
State
</td>
<td>
${data.state}
</td>
</tr>
<tr>
<td>
Reason Code
</td>
<td>
${data.reasonCode}
</td>
</tr>`;
innerHTML += `</tbody></table>`;
templateDiv.innerHTML = innerHTML;
}
}
// Define Web Component
customElements.define("agent-web-component", AgentComponent);
111
Hello World
Hello World
The hello-world widget demonstrates the Widget API and Widget API Events triggered when a work card appears.
angular.module('a04a5141-9a48-4dc5-a7b6-ecb913671060', [
'core.services.WidgetAPI'
]).directive('helloWorld', widgetComponent);
function widgetComponent(WidgetAPI) {
scope.sayHello = function(message) {
api.sendMessage(message, 'random-id');
api.sendNotification('info', 'Widget: ' + message);
};
// interaction event fired when a new interaction comes in or has been updated
api.onDataEvent('onInteractionEvent', function(data) {
scope.interaction = data;
});
// interaction ended event fired when the interaction card has ended
api.onDataEvent('onInteractionEndedEvent', function(data) {
scope.interactionEnded = data;
});
// media message data from chat, sms, email and social interactions
api.onDataEvent('onMediaMessageEvent', function(data) {
scope.media = data;
});
112
Hello World
scope.navigation = data;
});
return {
scope: {},
replace: true,
template: template,
link: widgetContainer
};
}
113
Widget Communication
Widget Communication
The Widget Framework has a feature to allow widgets to communicate with each other. Widget to widget communication is
intended so that two or more widgets can communicate with each other within a single instance of Workspaces and only when the
agent is presented a work card.
For example, when an agent receives a call and accepts the work card, two or more widgets can communicate and access details
about the call and perform actions such as querying a remote database or loading web page, etc.
Widget communication only occurs within the context of the work card, which means that if an agent has several work cards,
widgets can only communicate with each other and only within the bounds of their own work card type (voice, chat, email, etc.).
Widget to widget communication can be implemented by using the sendMessage() Widget API method. There are two modes
that widgets can use to communicate with each other: unicast and multicast.
In this example, we use the sendMessage() Widget API method to broadcast to all the widgets listening on the onMessageEvent
Widget API event.
function widgetComponent(WidgetAPI) {
function widgetContainer(scope, element, params) {
var api = new WidgetAPI(params);
// listen for a message event
api.onDataEvent('onMessageEvent', function(message) {
// do something with the message
console.log(message);
});
}
return {
114
Widget Communication
scope: {},
replace: true,
template: template,
link: widgetContainer
};
}
In this code example above, we use the sendMessage() Widget API method and use an unique identifier string as the second
argument.
The unique identifier string is used to send the message data to a specific widget that is listening for it, in this case Widget B. The
code example below, shows how Widget B listens for the onMessageEvent using the unique-random-id as the identifier for
receiving data.
function widgetComponent(WidgetAPI) {
function widgetContainer(scope, element, params) {
var api = new WidgetAPI(params);
// listen for a message event with ID 'unique-random-id'
api.onDataEvent('onMessageEvent:unique-random-id', function(message) {
// do something with the message
console.log(message);
});
}
return {
scope: {},
replace: true,
template: template,
link: widgetContainer
};
}
115
Widget Communication
Note: You can select any unique identifier as long as it is passed as a string.
To see a live code example, you can use the hello-world and message-echo widgets to send and receive messages. These
widgets are part of the Sample Widget Library included in the Widget Framework documentation.
116
Prompted Digits
Prompted Digits
Prompted digits can be obtained from Context Store data using the widget API. These digits can then be used to trigger behaviour
in workspaces such as opening a PDF relating to a customer ID as demonstrated in the prompt-digits sample widget.
The context store information is retrieved by subscribing to the 'onConextDataEvent' as shown below.
The prompt-digits widget subscribes to the onContextDataEvent and passes a url to an iFrame hosted by the widget that will
retrieve a pdf corresponding to the prompt digits retrieved from context store.
scope.trustAsResourceUrl = function(url) {
return $sce.trustAsResourceUrl(url);
};
api.onDataEvent('onContextDataEvent', function(data) {
scope.context = data.contextStore[0].data;
scope.pdfUrl = localStorage.getItem('_cc.libraryUrl') + '/prompt-digits/assets/' + data.contextStore[0].d
ata + '.pdf';
});
<div class="neo-widget">
<div class="neo-widget__content">
<iframe src="{% raw %}{{ ::pdfUrl }}{% endraw %}" width="100%" height="100%" frameborder="0" allowfullscreen
></iframe>
</div>
</div>
117
Localisation
Localisation of Widgets
The Widget Framework does not provide widget developers with a built-in facility for localising their widgets. You can use the
angular-gettext package or other packages to localise your widgets.
The angular-gettext package is the same package that Workspaces uses to perform localisation.
The angular-gettext package uses the gettext format (.po) which is commonly used in many web applications and Linux OS
distributions. You can read about some of the advantages of using the gettext format here.
In addition you may also want to implement Right-to-Left language support in your widget
Localisation Example
Here is a code example of a widget that angular-gettext package for localisation.
angular.module('831e9ed6-2416-427c-8f04-ccee6e89790a', [
'gettext',
'core.services.WidgetAPI'
]).directive('localisedWidget', widgetComponent);
function widgetComponent(WidgetAPI) {
function widgetContainer(scope, element, params) {
// widget API constructor
var api = new WidgetAPI(params);
}
return {
scope: {},
replace: true,
template: template,
link: widgetContainer
};
}
You need to use Angular's dependency injection (DI) system and include 'gettext' as a module in your widget (see code
above).
To perform the string annotations, angular-gettext uses the translate directive. You need to add the translate directive
to HTML elements you want angular-gettext to translate.
The HTML template below shows several examples on how to use the translate directive to annotate strings for translation.
<div class="neo-widget">
<div class="neo-widget__header aoc-home" translate>Localised Widget</div>
<div class="neo-widget__content neo-widget__content--indented">
<div class="row">
<div class="col-medium-12 col-large-12">
<p translate>This string will be translated</p>
<p translate>You can also use string interpolation, for example: {{ hello }}</p>
<p translate>Input attributes can also be translated: </p>
118
Localisation
<input type="text" placeholder="{% raw %}{{ 'Username' | translate }}{% endraw %}" />
</div>
</div>
</div>
</div>
You also need to include the angular-gettext JavaScript library in your widget's JSON configuration file so that angular-
gettext is loaded by your widget.
Here is an example of how your widget's JSON configuration should look like:
{
"metadata": {
"name": "Localised Widget",
"description": "Please add widget description here",
"tags": "demo, widget, example, other",
"library": "My Library",
"version": "1.0.0",
"date": "2017-09-26T12:32:15.618Z",
"id": "831e9ed6-2416-427c-8f04-ccee6e89790a"
},
"configuration": {
"external": true,
"timeout": 5000,
"serie": true,
"name": "831e9ed6-2416-427c-8f04-ccee6e89790a",
"element": "<localised-widget></localised-widget>",
"icon": "aoc-home",
"files": [
"localised-widget/libs/angular-gettext.min.js",
"localised-widget/localised-widget.css",
"localised-widget/localised-widget.js"]
}
}
Extracting strings
Now that you have annotated your widget. You can use the following Grunt plugin to extract the strings automatically from your
widget HML templates.
Follow the instructions on how to install and use the Grunt plugin.
Follow the instructions on how translate your strings (.po) files using the recommended tools.
Include the translations.js file to your widget's JSON configuration file.
In stylesheets
In order to support Right-To-Left languages you may need to change something in your widget stylesheets to prevent incorrect
widget rendering.
To write all the necessary RTL styles in the same stylesheet file using the [dir="rtl"] root selector
.my-widget-button {
margin-left: 15px;
}
119
Localisation
Or to split stylesheets for LTR and RTL into two different stylesheet files, like localised-widget.css and localised-
widget.rtl.css , so Workspaces will be able to lazy-load necessary stylesheet files of your widget when agent switches
between locales. Such an approach implies you to explicitly specify "bidi-alternative" stylesheet files in widget's JSON
configuration by surrounding these in sub-array (first filename entry stands for LTR, second - for RTL) as follows:
{
"metadata": {
"name": "Localised Widget",
"description": "Please add widget description here",
"tags": "demo, widget, example, other",
"library": "My Library",
"version": "1.0.0",
"date": "2017-09-26T12:32:15.618Z",
"id": "831e9ed6-2416-427c-8f04-ccee6e89790a"
},
"configuration": {
"external": true,
"timeout": 5000,
"serie": true,
"name": "831e9ed6-2416-427c-8f04-ccee6e89790a",
"element": "<localised-widget></localised-widget>",
"icon": "aoc-home",
"files": [
"localised-widget/libs/angular-gettext.min.js",
["localised-widget/localised-widget.css", "localised-widget/localised-widget.rtl.css"],
"localised-widget/localised-widget.js"]
}
}
In the 2nd case please note: executing grunt --build="..." command will concatenate all your stylesheet files into the
single one. In order to prevent LTR and RTL styles collision, just make sure that all your stylesheets for RTL have
.rtl.css in the filename ending. Thus all your stylesheets will be separately concatenated into localised-widget.css
In JavaScript code
Checkout the following WidgetAPI documentation entries to handle RTL issues in your JavaScript code:
bidi method
onLocaleUpdatedEvent event
onBeforeTextDirectionChangedEvent event
onStylesheetsReadyEvent event
120