Plugins SDK API
This part is still in the development process, changes may happen frequently.
After installing the SDK, you can now require it with:
import { App } from '@wazo/euc-plugins-sdk';
const app = new App();
Lifecycle
Plugins can be loaded and unloaded depending on some actions inside our product (ex: login/logout, tenant change, etc). Here's the lifecycle of a plugin with related listeners. That will help you build a robust system based on user actions.
Initializing
It's required to call app.initialize()
function to registerer and acknowledge your plugin inside our E-UC Application. Please note this method is asynchronous.
await app.initialize();
Getting the Context
When the application is initialized, you can retrieve the context surrounding your plugin. A context will give you access to the app information that your plugin will base its logic on it.
import { Context } from '@wazo/euc-plugins-sdk/types';
const context: Context = app.getContext();
Information that the context will give you access to:
app: AppInfo
: Information about the EUC applicationlocale: string
: The locale code of the application on 2 characters, likeen
orit
.theme: Object
: Colors used by the EUC app. It uses the Material UI theme palette structure, so you can use it directly withcreateTheme()
or just pick the color you want in your plugin.host: AppHostInfo
: Contains aclientType
value that can beweb
/desktop
/ios
orandroid
extra: Object
: Contains extra information about the app context, like thecontact
when you use thecontactTab
manifest context. Among extra parameters, you'll always receive:extra.baseUrl
: The base url of yourmanifest.json
fileextra.pluginId
: TheentityId
of the current plugin.
user: UserInfo
: Information about the connected user in the EUC app:token: string
: The token that can be used for API callsrefreshToken: string
: A refresh token that should be used if thetoken
expiresuuid: string
: The user uuidhost
: In the web or desktop application: representing the stack hostname where the user is connected. See theWDASession
and thePortalSession
types for more information.
Running
It's at this moment the magic happens, add your own logic inside our products. Depending on which product you're developing, there are many listeners or action creators that you can use with the SDK.
Unloading
When a plugin is unloaded because of a user action (ex: logout), this listener app.onPluginUnLoaded()
will be called. Other listeners will be disabled when unloaded. To prevent side effects, it's important to remove any watcher added in the initializing phase.
When the user logs in again, the backgroundScript
will be reloaded, please make sure to release everything in onPluginUnLoaded
.
If you're using a background script, it's important to close any WebSocket or listeners at this cycle of the plugin.
Global Events
Plugin's Interface Unloaded
UI Listener
app.onUnLoaded = () => {};
It's a sugar of window.onunload
, useful when you want to store information before page/tab exit. Important: You can't do an action here like API call because the app (iframe) can be closed before the action will be finished.
Background Script Listener
app.onAppUnLoaded = (tabId) => {};
Should be used in a backgroundScript
to know when a custom tab is unloaded. As app.onUnLoaded
is only triggered for tabs (iframes), and this event doesn't allow sophisticated actions (like sending messages to a background script, API calls, ...) we should use onAppUnLoaded
to perform an action when a tab is unloaded.
User Logs Out
app.onLogout = () => {};
User Session Refreshed
The token of the authenticated user has an expiration date; when the token expires, a session is created with a new token.
app.onNewSession = (session: WDASession | PortalSession) => {}
E-UC Apps (Web and Desktop)
Methods
Opening and closing the left panel
app.closeLeftPanel();
app.openLeftPanel();
Example:
await app.initialize();
// Closing the web/desktop left panel when the page is loaded
app.closeLeftPanel();
app.onUnLoaded = () => {
// Re-opening the panel when the page is unloaded
app.openLeftPanel();
};
Starting a call
app.startCall({ targets , requestedModalities = ['audio'] });
Example:
app.startCall({ targets: ['8008'], requestedModalities: ['video'] });
Opening a link in the application
app.openLink(url: string);
Example:
// Opening the internal phonebook
app.openLink('/phonebook/internal');
Creating a meeting
app.createMeeting(name: string, requireAuthorization = false, persistent = false);
Example:
app.createMeeting('My meeting from my custom app', true, true);
// Wait for the meeting to be available
app.onMeetingCreated = newMeeting => {};
Opening a meeting lobby
app.openMeetingLobby(extension: string);
Example:
// Open the lobby when a meeting is created
app.onMeetingCreated = newMeeting => {
app.openMeetingLobby(newMeeting.exten);
};
Ignoring an incoming call
app.onCallIncoming = call => {
app.ignoreCall(call);
};
Playing a sound
app.playNewMessageSound(); // Play the sound when we receive a text message
app.playIncomingCallSound(); // Play the incoming call sound (loop)
app.playProgressSound(); // Play the ringback sound when we make a call (loop)
app.playDoubleCallSound(); // Play the sound when another call is incoming
app.playHangupSound(); // Play the hangup sound
Stopping a sound
Sounds marked "loop" must be stopped using:
app.stopCurrentSound();
Configuring sounds
You can use your own sound files in the application, with:
app.configureSounds({
progress: 'http://example/com/progress.mpg', // Played when making an outgoing call (ringback)
ring: 'http://example/com/ring.wav', // Played for the first incoming call
message: 'http://example/com/message.ogg', // Played when the user receives a chat message
hangup: 'http://example/com/hangup.ogg',// Played when the call is hung up
inboundCall: 'http://example/com/inbound.vaw', // Played when we are in call and another call is incoming. Also played in Switchboard.
})
You can omit a value, the default sound will be used.
Resetting sounds
You can reset all application sounds with:
app.resetSounds();
Displaying a notification
Wazo will display browser or desktop notification depending on the environment where WDA is running.
app.displayNotification(title: string, text: string);
Changing the navigation bar color
We can change the navigation bar color with a valid CSS color:
app.changeNavBarColor(color: string);
Example:
app.changeNavBarColor('#8e6a3a');
app.changeNavBarColor('white');
Resetting the navigation bar color
We can reset to the default navigation bar color with:
app.resetNavBarColor();
Displaying a modal
We can display a modal in the backgroundScript
with:
app.displayModal({ url, title, text, htmlText, height, width, hideCloseButton });
If url
is present, the modal will display an iframe with the content of the url.
If htmlText
is present, the modal will display this text in a html contact, otherwise the text
attribute will be used.
The height
and width
accept valid CSS values, like 500px
or 80%
.
hideCloseButton
(default to false) determines if the close button should be displayed, or if the user should handle closing of the modal in the html content (through app.removeModal()
method).
On mobile, links with a target="_blank"
attribute will be opened in the user's default browser.
Example:
Displaying client data when receiving a call
app.onCallIncoming = async call => {
console.log('background onCallIncoming', call);
const clientData = await fetchClientData(call.number); // Where `fetchClientData` is a method that return client information from an extension
app.displayModal({
title: `Incoming call for ${call.displayName}`,
text: `Last call was: ${clientData.lastCall} for : ${clientData.lastCallSubject}`,
height: '50%',
width: '70%',
});
};
Displaying a banner (mobile only)
We can display a banner in the backgroundScript
with:
app.displayBanner({ url, height, width, hideCloseButton });
If url
is present, the modal will display an iframe with the content of the url.
The height
accepts valid CSS values, like 500px
or 80%
.
The width
accepts valid CSS values, like 500px
or 80%
, used on WDA (min: 300px
).
hideCloseButton
(default to false) determines if the close button should be displayed, or if the user should handle closing of the modal in the html content (through app.removeModal()
method).
We can then call app.removeBanner()
in the backgroundScript
or the loaded content.
On mobile, links with a target="_blank"
attribute will be opened in the user's default browser.
On WDA, the banner will be integrated with other banners like incoming calls. Other banners will be displayed below.
Checking if a call has a local video stream
app.hasLocalVideoStream(call: Call);
Example:
app.onCallAnswered = (call) => {
const hasLocalVideo = app.hasLocalVideoStream(call);
}
Retrieving the local video stream of a call
app.getLocalCurrentVideoStream(call: Call);
Example:
app.onCallAnswered = (call) => {
const stream = app.getLocalCurrentVideoStream(call);
}
Checking if a call has a remote video stream
app.hasRemoteVideoStream(call: Call);
Example:
app.onCallAnswered = (call) => {
const hasRemoteVideo = app.hasRemoteVideoStream(call);
}
Retrieving the remote video stream of a call
app.getRemoteCurrentVideoStream(call: Call);
Example:
app.onCallAnswered = (call) => {
const stream = app.getRemoteCurrentVideoStream(call);
}
Sending and receiving message between iframe and background script
Inside an iframe
// Sending message to background
app.sendMessageToBackground({ value: 'ping' });
// Receiving a message from the background script
app.onIframeMessage = (msg) => {
console.log('onIframeMessage', msg);
}
In the background script
// Sending a message to the iframe
app.sendMessageToIframe({ value: 'pong' });
// Receiving a message from the iframe
app.onBackgroundMessage = msg => {
console.log('onBackgroundMessage', msg);
}
Display a notification next to the navigation bar icon button
Uses MUI's Badge component to display a notification, generally an integer. When used in background.js
, it requires entityId
as set in a tab in the staticTabs
section of manifest.json
, and that tab must include "sidebarTab" in its context (entityId
should automatically be set when called from the iframe).
app.updateBadge({ badgeContent: number, color?: string = 'error', variant?: string, max?: number, overlap?: string, anchorOrigin?: Object, showZero?: boolean });
⚠️ On Wazo Mobile, only the field badgeContent: number
is used to display the badge.
Events
A call for the current user is incoming
app.onCallIncoming = (call: Call) => {
// Useful to react in a `backgroundScript`.
};
A call is made by the user (eg: outgoing call)
app.onCallMade = (call: Call) => {
// Useful to react in a `backgroundScript`.
};
An incoming call is answered by the current user
app.onCallAnswered = (call: Call) => {
// Useful to react in a `backgroundScript`.
};
A call is answered (by one or the other side)
app.onCallAccepted = (call: Call) => {
// Useful to react in a `backgroundScript`.
};
A call is hung up
app.onCallHungUp = (call: Call) => {
// Useful to react in a `backgroundScript`.
};
Listening to Wazo Websocket message
app.onWebsocketMessage = (message: MessageEvent) => {
// Useful to react in a `backgroundScript`.
};
Listening to meeting creation
app.onMeetingCreated = (meeting: Meeting) => { };
Listening navigation change in the app
app.onRouteChanged = (location: Object, action: string) => { };
Listening when a user enters a Room
app.onUserJoinRoom = (room) => {};
Listening when a user leavers a Room
app.onUserLeaveRoom = (room) => {};
Listening when a participant enters a Room
app.onParticipantJoinRoom = (room, participant) => {};
Listening when a participant leavers a Room
app.onParticipantLeaveRoom = (room, participant) => {};
E-UC Portal
Methods
Changing the display of the toolbar in a custom form
app.changeToolbarDisplay(displayed: boolean);
Events
Check when the user is connected to a stack
app.onConnectedToStack = (stackSession: Object) => {};
Check when the user is connected or switch to a tenant
app.onSwitchTenant = (uuid: string, name: string) => {};
E-UC Mobile
Methods
Change the header
title
: Changes the label displayed in the header. Set this value to null
to set it back to the default value.
callback
: Handles the back button click. If a callback is registered, the app will forgo its normal behavior and run it. Setting the value to null
reinstates the original behavior.
app.setMobileHeader({ title?: string | null, callback?: Function | null });
Show / hide bottom navigation
Define whether you want to show or hide the bottom navigation
app.setMobileShowBottomNav(show: boolean);