-
Notifications
You must be signed in to change notification settings - Fork 355
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(plugin-cc): added-call-control #4015
Merged
Merged
Changes from 32 commits
Commits
Show all changes
46 commits
Select commit
Hold shift + click to select a range
1122f07
feat(plugin-cc): call accept implemented
Kesari3008 acba03a
feat(plugin-cc): latest merge
Kesari3008 39a55a4
feat(plugin-cc): added ut, added sample app changes
Kesari3008 616d973
feat(plugin-cc): fixes in code
Kesari3008 555289d
feat(plugin-cc): manual testing for call answer and decline finished
Kesari3008 3754f66
feat(plugin-cc): small fixes in sample app
Kesari3008 d3809b2
feat(plugin-cc): fixed ut
Kesari3008 9b40fde
feat(plugin-cc): fixed ut
Kesari3008 e756062
feat(plugin-cc): ut fix
Kesari3008 cfe40f6
feat(plugin-cc): review comments
Kesari3008 963fa03
feat(plugin-cc): ut fixes
Kesari3008 37ec111
feat(plugin-cc): ut fixes
Kesari3008 e8dcefd
feat(plugin-cc): merge conflict
Kesari3008 c9f2e2c
feat(plugin-cc): review comments thrid round
Kesari3008 2d3b7ee
feat(plugin-cc): sample app fixes
Kesari3008 cc99ac8
feat(plugin-cc): test file import fixes
Kesari3008 4ac05c2
feat(cc-sdk): added-call-control
adhmenon ac450ed
fix(plugin-cc): rename folders
sreenara 8f6563f
feat(cc-sdk): added-log-changes
adhmenon 064328f
feat(cc-sdk): fixed-sample-app-issue
adhmenon 8917ab4
feat(cc-sdk): added-wrapup-dropdown
adhmenon 5b290c5
Merge branch 'SPARK-562169-Task-API-Implementation' of https://github…
adhmenon ee6908a
feat(plugin-cc): review comments
Kesari3008 847f0cc
Merge branch 'SPARK-562169-Task-API-Implementation' of github.com:Kes…
Kesari3008 338202d
feat(cc-sdk): fixed-renaming-issue
adhmenon f381fab
fix(plugin-cc): ut-fixes
Kesari3008 890e2be
Merge branch 'SPARK-562169-Task-API-Implementation' of https://github…
adhmenon 4c6a2bc
fix(plugin-cc): ut added for off listeners
Kesari3008 fa4c42e
feat(plugin-cc): added types and add ut for cc file
Kesari3008 d65c4fd
Merge branch 'SPARK-562169-Task-API-Implementation' of https://github…
adhmenon 352315f
feat(cc-sdk): fixed-pipeline-fix
adhmenon 93dc3d0
feat(plugin-cc): updated logs
Kesari3008 a0d93ca
feat(cc-sdk): added-recording-pause-and-resume
adhmenon 098948e
feat(cc-sdk): added-task-response-unit-tests
adhmenon 2f154e3
feat(cc-sdk): added-end-call-edge-case
adhmenon 1f2cee9
Merge branch 'SPARK-562169-Task-API-Implementation' of https://github…
adhmenon daeb3e5
feat(cc-sdk): added-cleanup-on-call-wrapup
adhmenon 7988048
feat(plugin-cc): fixed the issue with incoming call being received wi…
Kesari3008 441c992
Merge branch 'SPARK-562169-Task-API-Implementation' of https://github…
adhmenon 05b9ace
feat(cc-sdk): added-tests-for-edge-cases
adhmenon 1d7a016
fix(plugin-cc): review comments
Kesari3008 f058339
Merge branch 'SPARK-562169-Task-API-Implementation' of https://github…
adhmenon 57f71e1
fix(plugin-cc): review comments
Kesari3008 65cd8fe
Merge branch 'SPARK-562169-Task-API-Implementation' of https://github…
adhmenon 83c4345
Merge branch 'wxcc' of https://github.com/webex/webex-js-sdk into dev…
adhmenon 1f56afa
feat(wxcc): fixed-merge-conflicts
adhmenon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,3 @@ | ||
/* eslint-disable no-underscore-dangle */ | ||
/* eslint-env browser */ | ||
|
||
/* global Webex */ | ||
|
||
/* eslint-disable require-jsdoc */ | ||
/* eslint-disable no-unused-vars */ | ||
/* eslint-disable no-console */ | ||
/* eslint-disable no-global-assign */ | ||
/* eslint-disable no-multi-assign */ | ||
/* eslint-disable max-len */ | ||
|
||
// Globals | ||
let webex; | ||
let sdk; | ||
|
@@ -18,6 +6,10 @@ let deviceId; | |
let agentStatusId; | ||
let agentStatus; | ||
let agentId; | ||
let taskControl; | ||
let task; | ||
let taskId; | ||
let wrapupCodes = []; // Add this to store wrapup codes | ||
|
||
const authTypeElm = document.querySelector('#auth-type'); | ||
const credentialsFormElm = document.querySelector('#credentials'); | ||
|
@@ -27,13 +19,24 @@ const authStatusElm = document.querySelector('#access-token-status'); | |
const registerBtn = document.querySelector('#webexcc-register'); | ||
const teamsDropdown = document.querySelector('#teamsDropdown'); | ||
const agentLogin = document.querySelector('#AgentLogin'); | ||
const agentLoginButton = document.querySelector('#loginAgent'); | ||
const loginAgentElm = document.querySelector('#loginAgent'); | ||
const dialNumber = document.querySelector('#dialNumber'); | ||
const registerStatus = document.querySelector('#ws-connection-status'); | ||
const idleCodesDropdown = document.querySelector('#idleCodesDropdown') | ||
const setAgentStatusButton = document.querySelector('#setAgentStatus'); | ||
const logoutAgentElm = document.querySelector('#logoutAgent'); | ||
const buddyAgentsDropdownElm = document.getElementById('buddyAgentsDropdown'); | ||
const incomingCallListener = document.querySelector('#incomingsection'); | ||
const incomingDetailsElm = document.querySelector('#incoming-call'); | ||
const answerElm = document.querySelector('#answer'); | ||
const declineElm = document.querySelector('#decline'); | ||
const callControlListener = document.querySelector('#callcontrolsection'); | ||
const holdResumeElm = document.querySelector('#hold-resume'); | ||
const pauseResumeRecordingElm = document.querySelector('#pause-resume-recording'); | ||
const endElm = document.querySelector('#end'); | ||
const wrapupElm = document.querySelector('#wrapup'); | ||
const wrapupCodesDropdownElm = document.querySelector('#wrapupCodesDropdown'); | ||
const autoResumeCheckboxElm = document.querySelector('#auto-resume-checkbox'); // Add this | ||
|
||
// Store and Grab `access-token` from sessionStorage | ||
if (sessionStorage.getItem('date') > new Date().getTime()) { | ||
|
@@ -70,6 +73,26 @@ function toggleDisplay(elementId, status) { | |
} | ||
} | ||
|
||
const taskEvents = new CustomEvent('task:incoming', { | ||
detail: { | ||
task: task, | ||
}, | ||
}); | ||
|
||
// TODO: Activate the call control buttons once the call is accepted and refctor this | ||
function registerTaskListeners(task) { | ||
task.on('task:assigned', (task) => { | ||
console.info('Call has been accepted for task: ', task.data.interactionId); | ||
}); | ||
task.on('task:media', (track) => { | ||
document.getElementById('remote-audio').srcObject = new MediaStream([track]); | ||
}); | ||
task.on('task:end', (task) => { | ||
// Need to add check here to enable wrapup if the end button is not pressed | ||
console.info('Call ended'); | ||
}); | ||
} | ||
|
||
function generateWebexConfig({credentials}) { | ||
return { | ||
appName: 'sdk-samples', | ||
|
@@ -122,6 +145,8 @@ function register() { | |
teamsDropdown.innerHTML = ''; // Clear previously selected option on teamsDropdown | ||
const listTeams = agentProfile.teams; | ||
agentId = agentProfile.agentId; | ||
wrapupCodes = agentProfile.wrapupCodes; | ||
populateWrapupCodesDropdown(); | ||
listTeams.forEach((team) => { | ||
const option = document.createElement('option'); | ||
option.value = team.id; | ||
|
@@ -132,7 +157,7 @@ function register() { | |
agentLogin.innerHTML = '<option value="" selected>Choose Agent Login ...</option>'; // Clear previously selected option on agentLogin. | ||
dialNumber.value = agentProfile.defaultDn ? agentProfile.defaultDn : ''; | ||
dialNumber.disabled = agentProfile.defaultDn ? false : true; | ||
if(loginVoiceOptions.length > 0) agentLoginButton.disabled = false; | ||
if (loginVoiceOptions.length > 0) loginAgentElm.disabled = false; | ||
loginVoiceOptions.forEach((voiceOptions)=> { | ||
const option = document.createElement('option'); | ||
option.text = voiceOptions; | ||
|
@@ -142,6 +167,7 @@ function register() { | |
}); | ||
|
||
if (agentProfile.isAgentLoggedIn) { | ||
loginAgentElm.disabled = true; | ||
logoutAgentElm.classList.remove('hidden'); | ||
} | ||
|
||
|
@@ -157,10 +183,25 @@ function register() { | |
idleCodesDropdown.add(option); | ||
} | ||
}); | ||
|
||
}).catch((error) => { | ||
console.error('Event subscription failed', error); | ||
}) | ||
|
||
webex.cc.eventEmitter.on('task:incoming', (task) => { | ||
taskEvents.detail.task = task; | ||
|
||
incomingCallListener.dispatchEvent(taskEvents); | ||
}) | ||
} | ||
|
||
function populateWrapupCodesDropdown() { | ||
wrapupCodesDropdownElm.innerHTML = ''; // Clear previous options | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need name and id for the payload for wrapupm hence we store only that as of now. |
||
wrapupCodes.forEach((code) => { | ||
const option = document.createElement('option'); | ||
option.text = code.name; | ||
option.value = code.id; | ||
wrapupCodesDropdownElm.add(option); | ||
}); | ||
} | ||
|
||
async function handleAgentLogin(e) { | ||
|
@@ -178,6 +219,7 @@ async function handleAgentLogin(e) { | |
function doAgentLogin() { | ||
webex.cc.stationLogin({teamId: teamsDropdown.value, loginOption: agentDeviceType, dialNumber: dialNumber.value}).then((response) => { | ||
console.log('Agent Logged in successfully', response); | ||
loginAgentElm.disabled = true; | ||
logoutAgentElm.classList.remove('hidden'); | ||
} | ||
).catch((error) => { | ||
|
@@ -205,6 +247,7 @@ function setAgentStatus() { | |
function logoutAgent() { | ||
webex.cc.stationLogout({logoutReason: 'logout'}).then((response) => { | ||
console.log('Agent logged out successfully', response); | ||
loginAgentElm.disabled = false; | ||
|
||
setTimeout(() => { | ||
logoutAgentElm.classList.add('hidden'); | ||
|
@@ -247,6 +290,41 @@ async function fetchBuddyAgents() { | |
} | ||
} | ||
|
||
incomingCallListener.addEventListener('task:incoming', (event) => { | ||
taskId = event.detail.task.data.interactionId; | ||
task = event.detail.task; | ||
const callerDisplay = event.detail.task.data.interaction.callAssociatedDetails.ani; | ||
registerTaskListeners(task); | ||
|
||
if (task.webCallingService.loginOption === 'BROWSER') { | ||
answerElm.disabled = false; | ||
declineElm.disabled = false; | ||
|
||
incomingDetailsElm.innerText = `Call from ${callerDisplay}`; | ||
} else { | ||
incomingDetailsElm.innerText = `Call from ${callerDisplay}...please answer on the endpoint where the agent's extension is registered`; | ||
} | ||
}); | ||
|
||
function answer() { | ||
answerElm.disabled = true; | ||
declineElm.disabled = true; | ||
holdResumeElm.disabled = false; | ||
holdResumeElm.innerText = 'Hold'; | ||
pauseResumeRecordingElm.disabled = false; | ||
pauseResumeRecordingElm.innerText = 'Pause Recording'; | ||
endElm.disabled = false; | ||
task.accept(taskId); | ||
incomingDetailsElm.innerText = 'Call Accepted'; | ||
} | ||
|
||
function decline() { | ||
answerElm.disabled = true; | ||
declineElm.disabled = true; | ||
task.decline(taskId); | ||
incomingDetailsElm.innerText = 'No incoming calls'; | ||
} | ||
|
||
const allCollapsibleElements = document.querySelectorAll('.collapsible'); | ||
allCollapsibleElements.forEach((el) => { | ||
el.addEventListener('click', (event) => { | ||
|
@@ -304,3 +382,82 @@ function expandAll() { | |
}); | ||
} | ||
|
||
function holdResumeCall() { | ||
if (holdResumeElm.innerText === 'Hold') { | ||
holdResumeElm.disabled = true; | ||
task.hold().then(() => { | ||
console.info('Call held successfully'); | ||
holdResumeElm.innerText = 'Resume'; | ||
holdResumeElm.disabled = false; | ||
}).catch((error) => { | ||
console.error('Failed to hold the call', error); | ||
holdResumeElm.disabled = false; | ||
}); | ||
} else { | ||
holdResumeElm.disabled = true; | ||
task.resume().then(() => { | ||
console.info('Call resumed successfully'); | ||
holdResumeElm.innerText = 'Hold'; | ||
holdResumeElm.disabled = false; | ||
}).catch((error) => { | ||
console.error('Failed to resume the call', error); | ||
holdResumeElm.disabled = false; | ||
}); | ||
} | ||
} | ||
|
||
function togglePauseResumeRecording() { | ||
const autoResumed = autoResumeCheckboxElm.checked; | ||
if (pauseResumeRecordingElm.innerText === 'Pause Recording') { | ||
pauseResumeRecordingElm.disabled = true; | ||
task.pauseRecording().then(() => { | ||
console.info('Recording paused successfully'); | ||
pauseResumeRecordingElm.innerText = 'Resume Recording'; | ||
pauseResumeRecordingElm.disabled = false; | ||
autoResumeCheckboxElm.disabled = false; | ||
}).catch((error) => { | ||
console.error('Failed to pause recording', error); | ||
pauseResumeRecordingElm.disabled = false; | ||
}); | ||
} else { | ||
pauseResumeRecordingElm.disabled = true; | ||
task.resumeRecording({ autoResumed: autoResumed }).then(() => { | ||
console.info('Recording resumed successfully'); | ||
pauseResumeRecordingElm.innerText = 'Pause Recording'; | ||
pauseResumeRecordingElm.disabled = false; | ||
autoResumeCheckboxElm.disabled = true; | ||
}).catch((error) => { | ||
console.error('Failed to resume recording', error); | ||
pauseResumeRecordingElm.disabled = false; | ||
}); | ||
} | ||
} | ||
|
||
function endCall() { | ||
endElm.disabled = true; | ||
task.end().then(() => { | ||
console.log('Call ended successfully'); | ||
holdResumeElm.disabled = true; | ||
pauseResumeRecordingElm.disabled = true; | ||
wrapupElm.disabled = false; | ||
wrapupCodesDropdownElm.disabled = false; | ||
}).catch((error) => { | ||
console.error('Failed to end the call', error); | ||
endElm.disabled = false; | ||
}); | ||
} | ||
|
||
function wrapupCall() { | ||
wrapupElm.disabled = true; | ||
adhmenon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const wrapupReason = wrapupCodesDropdownElm.options[wrapupCodesDropdownElm.selectedIndex].text; | ||
const auxCodeId = wrapupCodesDropdownElm.options[wrapupCodesDropdownElm.selectedIndex].value; | ||
task.wrapup({wrapUpReason: wrapupReason, auxCodeId: auxCodeId}).then(() => { | ||
console.info('Call wrapped up successfully'); | ||
holdResumeElm.disabled = true; | ||
endElm.disabled = true; | ||
wrapupCodesDropdownElm.disabled = true; | ||
}).catch((error) => { | ||
console.error('Failed to wrap up the call', error); | ||
wrapupElm.disabled = false; | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We will now store the entire list of codes using this dropdown and populate the request accordingly.