Skip to main content
Embedded Softphone

Embedded Softphone

Here's an interactive introduction on how Wazo Embedded works. Want to learn from a technical approch, please refer to the E-UC Plugins SDK documentation to see how the SDK works.

Assign the softphone to your stack​

warning

Please enter you stack domain! Otherwise the interactive demo will be limited to the login form

First of all, we need to define a server associated to the softphone, it's required to fully enable the full interactive demo.

Show​

softphone.show();
πŸš€ Show me

Hide​

softphone.hide();
πŸ™ˆ Hide it

Minimize / restore the embedded softphone​

You can minimize and restore the embedded softphone the way you would any regular window by adding your buttons to the wrapper element, which will allow you to position your buttons relative to the iframe.

const minimizeButton = document.createElement('button');
minimizeButton.addEventListener('click', softphone.hide.bind(softphone));
softphone.wrapper.appendChild(minimizeButton);

const maximizeButton = document.createElement('button');
minimizeButton.addEventListener('click', softphone.show.bind(softphone));
softphone.wrapper.appendChild(minimizeButton);

Move it right​

softphone.init({
server: 'my-server',
width: 400,
iframeCss: {
position: 'fixed',
right: 0,
top: '80px',
},
});
softphone.show();
πŸ‘‰ This way

Login directly from a token​

const login = document.querySelector('#login').value;
const password = document.querySelector('#password').value;
const server = document.querySelector('#server').value;

Wazo.Auth.init('softphone-example');
Wazo.Auth.setHost(server);
const session = await Wazo.Auth.logIn(login, password);

softphone.loginWithToken(session.token, session.refreshToken);

Making a call​

softphone.makeCall('*10');
☎️ Call *10

We can parse links contains tel:// and callto:// on the current page.

This is a link to call *10

Link are already parsed when we authenticate, so we have to call removeParsedLinksEvent to be able to parse them again.

softphone.onLinkEnabled = (link => {
link.style.color = 'red';
});

// We have to remove the previous parsing of the links
softphone.removeParsedLinksEvent();
softphone.parseLinks();
πŸ”— Parse call links on this page

Injecting CSS in the Embedded Softphone​

softphone.injectCss(`
a button {
background-color: green !important;
}
`);
✨ Make the dialer button green

Changing the appearance of the Embedded Softphone​

softphone.customizeAppearance({
colors: {
primary: '#d06c2b',
button: '#4b2bd7',
secondary: '#29877c',
},
}, {
// Translation
// Set `debug: true` to know where to change translations, like below:
en: {
call: {
searchInWazo: 'Type a number here !',
},
user: {
login: 'My login button', // will be displayed as `user:login` in the button when settings `debug: true` in the init() method
},
},
}, {
// Assets
logo: 'my-logo.png',
});
🌈 Customize the Embedded Softphone

Adding a card form​

We can add form so the user can fill some information during a call, it uses the React Json schema form :

softphone.setFormSchema({
type: 'object',
required: ['title', 'phone'],
properties: {
subject: ["Support", "Greetings", "Whant to talk to Bob"],
title: { type: 'string', title: 'Title' },
note: { type: 'string', title: 'Note' },
},
}, {
note: { 'ui:widget': 'textarea' },
});
πŸ“ Add a form during the call

Changing the value in the form​

softphone.setCardValue('title', 'My new title !');
β˜€οΈ Update the call form value

Advanced card form​

We can add a new field to select the client and allow creating new one.

softphone.setFormSchema({
type: 'object',
required: ['title', 'clientId'],
properties: {
clientId: {
type: 'object',
title: 'Client id',
// triggers the `onDisplayLinkedOption` event when changing the value
triggerDisplay: true,
// createForm is another JSON schema the description the add option form.
createForm: {
optionLabel: '%firstname% %lastname%',
schema: {
type: 'object',
required: ['phone'],
properties: {
firstname: { type: 'string', title: 'Firstname' },
lastname: { type: 'string', title: 'Lastname' },
phone: { type: 'string', title: 'Phone' },
}
},
uiSchema: {}
},
},
title: { type: 'string', title: 'Title' },
note: { type: 'string', title: 'Note' },
},
}, {
note: { 'ui:widget': 'textarea' },
clientId :{ 'ui:field': 'autocomplete'},
});

// Add select values
softphone.onOptionsResults('clientId', [{ label: 'Alice', id: 1 }, { label: 'Bob', id: 2 }, { label: 'Charlies', id: 3 }]);

softphone.onSearchOptions = (fieldId, query) => {
// Call you API here with `query`
// const results = await fetchClient();
const results = [{ label: 'Charles', id: 4}, { label: 'David', id: 5 }, { label: 'Henry', id: 6 }];
softphone.onOptionsResults(fieldId, results);
};
πŸ‘Œ Raise up the form game !

Events​

Iframe loaded​

softphone.onIFrameLoaded = () => {
document.getElementById('iframe-loaded-event').innerText = 'Embedded Softphone iframe is loaded';
}

⏰ Will react when the iframe is loaded

User authenticated​

softphone.onAuthenticated = session => {
document.getElementById('authenticated-event').innerText = `User authenticated, token: ${session.token}`;
}

⏰ Will react when the user logs in

User logged out​

softphone.onLoggedOut = () => {
document.getElementById('logout-event').innerText = 'Current user logged out';
}

⏰ Will react when the user logs out

Call Incoming​

softphone.onCallIncoming = call => {
document.getElementById('call-incoming-event').innerText = `Incoming call from ${call.displayName}, number: ${call.number}`
};

⏰ Will react on incoming calls

Call answered locally​

softphone.onCallLocallyAnswered = call => {
document.getElementById('call-locally-answered-event').innerText = `Call answered here, number: ${call.number}`
};

⏰ Will react on call answered by the user

Call established​

softphone.onCallEstablished = call => {
document.getElementById('call-established-event').innerText = `Call answered, number: ${call.number}`
};

⏰ Will react on call answered

Call created locally​

softphone.onOutgoingCallMade = call => {
document.getElementById('call-outgoing-event').innerText = `Call created here, number: ${call.number}`
};

⏰ Will react on call created locally

Call rejected locally​

softphone.onCallRejected = call => {
document.getElementById('call-rejected-event').innerText = `Call rejected here, number: ${call.number}`
};

⏰ Will react on call rejected locally

Call ended​

softphone.onCallEnded = call => {
document.getElementById('call-ended-event').innerText = `Call ended, duration: ${(call.endTime - call.answerTime) / 1000}s`;
};

⏰ Will react on call ended

User saved the call form​

softphone.onCardSaved = card => {
document.getElementById('card-saved-event').innerHTML = `Client: ${card.clientId.label}<br /> title: ${card.title}<br /> note: ${card.note}`;
};

⏰ Will react when the form is saved by the user

User cancels the call form​

softphone.onCardCanceled = () => {
document.getElementById('card-canceled-event').innerHTML = 'Card canceled πŸ™';
};

⏰ Will react when the form is canceled by the user

User select a value in the select field of the call form​

softphone.onDisplayLinkedOption = optionId => {
document.getElementById('display-linked-option-event').innerHTML = `Selected identified: ${optionId}`;
};

⏰ Will react when the user choose a value in a select field of the call form

User select search for a contact​

softphone.onWazoContactSearch = query => {
document.getElementById('wazo-search-contact-event').innerHTML = `Searching for: ${query}`;
};

⏰ Will react when the user searches for a contact

User logs in as an agent​

softphone.onAgentLoggedIn = () => {
document.getElementById('agent-logged-in-event').innerHTML = 'Agent logged in !';
};

⏰ Will react when the user logs as an agent

User logs out as an agent​

softphone.onAgentLoggedOut = () => {
document.getElementById('agent-logged-out-event').innerHTML = 'Agent logged out !';
};

⏰ Will react when the user logs out as an agent

User pauses the agent​

softphone.onAgentPaused = () => {
document.getElementById('agent-paused-event').innerHTML = 'Agent paused !';
};

⏰ Will react when the user pauses the agent

User resumes the agent​

softphone.onAgentResumed = () => {
document.getElementById('agent-resumed-event').innerHTML = 'Agent resumed !';
};

⏰ Will react when the user pauses the agent

User changes the language​

softphone.onLanguageChanged = language => {
document.getElementById('language-changed-event').innerHTML = `Language changed: ${language}!`;
};

⏰ Will react when the user changes the language

Current call is held​

softphone.onCallHeld = () => {
document.getElementById('call-held-event').innerHTML = 'Current call is held ⏸️';
};

⏰ Will react when the current call is held

Current call is resumed​

softphone.onCallResumed = () => {
document.getElementById('call-resumed-event').innerHTML = 'Current call is resumed ▢️️';
};

⏰ Will react when the current call is resumed

Current call is muted​

softphone.onCallMuted = () => {
document.getElementById('call-muted-event').innerHTML = 'Current call is muted 🀐';
};

⏰ Will react when the current is muted

Current call is un-muted​

softphone.onCallUnMuted = () => {
document.getElementById('call-unmuted-event').innerHTML = 'Current call is un-muted πŸ”Š';
};

⏰ Will react when the current is un-muted

When the user send a DTMF in the current call​

softphone.onDtmfSent = tone => {
document.getElementById('call-dtmf-event').innerHTML = `DTMF sent: ${tone}`;
};

⏰ Will react when a DTMF is sent in the current call

When the user transfers directly the current call​

softphone.onDirectTransfer = number => {
document.getElementById('call-direct-transfer-event').innerHTML = `Call directly transfered to: ${number}`;
};

⏰ Will react when the current call is transferred

When the user creates an indirect transfer​

softphone.onCreateIndirectTransfer = number => {
document.getElementById('call-indirect-transfer-event').innerHTML = `Indirect transfer created to: ${number}`;
};

⏰ Will react when the user creates an indirect transfer

When the indirect transfer call is created​

softphone.onIndirectCallMade = call => {
document.getElementById('call-indirect-transfer-made-event').innerHTML = `Indirect transfer answered from: ${call.number}`;
};

⏰ Will react when the user creates an indirect transfer

When the user cancels an indirect transfer​

softphone.onCancelIndirectTransfer = () => {
document.getElementById('call-indirect-transfer-cancel-event').innerHTML = 'Indirect transfer canceled';
};

⏰ Will react when the user cancels an indirect transfer

When the user confirms an indirect transfer​

softphone.onConfirmIndirectTransfer = () => {
document.getElementById('call-indirect-transfer-confirm-event').innerHTML = 'Indirect transfer confirmed';
};

⏰ Will react when the user confirms an indirect transfer

When the user records the current call​

softphone.onStartRecording = () => {
document.getElementById('call-start-record-event').innerHTML = 'Current call recorded';
};

⏰ Will react when the user records the current call

When the user stops the record of the current call​

softphone.onStopRecording = () => {
document.getElementById('call-stop-record-event').innerHTML = 'Current record stopped';
};

⏰ Will react when the user stops the record of the current call

When the user receives a call log​

softphone.onCallLogCreated = callLog => {
document.getElementById('call-log-event').innerHTML = `A new call log was created, its duration: ${callLog.duration}`;
};

⏰ Will react when the user receives a call log

When the user receive a message from the Wazo's Websocket​

softphone.onWebsocketMessage = (message) => {
document.getElementById('websocket-event').innerHTML = `A new websocket message was received: ${JSON.stringify(message)}`;
};

⏰ Will react when the user receives a websocket message