From 57015ae4976222d3616fbd8376659c42e468e221 Mon Sep 17 00:00:00 2001 From: Rajesh Kumar Date: Tue, 29 Oct 2024 15:22:30 +0530 Subject: [PATCH] feat(plugin-cc): add agent logout --- docs/samples/contact-center/app.js | 15 ++++++++++ docs/samples/contact-center/index.html | 3 +- packages/@webex/plugin-cc/src/cc.ts | 24 +++++++++++++++- .../@webex/plugin-cc/src/features/Agent.ts | 17 ++++++++++- .../plugin-cc/src/services/AgentService.ts | 28 +++++++++++++++++-- .../plugin-cc/src/services/constants.ts | 1 + .../@webex/plugin-cc/src/services/types.ts | 13 +++++++++ .../test/unit/spec/features/Agent.ts | 27 +++++++++++++++++- 8 files changed, 122 insertions(+), 6 deletions(-) diff --git a/docs/samples/contact-center/app.js b/docs/samples/contact-center/app.js index 5776f561046..b6d8dc19a40 100644 --- a/docs/samples/contact-center/app.js +++ b/docs/samples/contact-center/app.js @@ -27,6 +27,7 @@ const agentLogin = document.querySelector('#AgentLogin'); const agentLoginButton = document.querySelector('#loginAgent'); const dialNumber = document.querySelector('#dialNumber'); const registerStatus = document.querySelector('#ws-connection-status'); +const logoutAgentElm = document.querySelector('#logoutAgent'); // Store and Grab `access-token` from localstorage if (localStorage.getItem('date') > new Date().getTime()) { @@ -151,12 +152,26 @@ 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); + logoutAgentElm.style.display = 'block'; } ).catch((error) => { console.log('Agent Login failed', error); }); } +function logoutAgent() { + webex.cc.stationLogout({logoutReason: 'logout'}).then((response) => { + console.log('Agent logged out successfully', response); + + setTimeout(() => { + logoutAgentElm.style.display = 'none'; + }, 1000); + } + ).catch((error) => { + console.log('Agent logout failed', error); + }); +} + const allCollapsibleElements = document.querySelectorAll('.collapsible'); allCollapsibleElements.forEach((el) => { el.addEventListener('click', (event) => { diff --git a/docs/samples/contact-center/index.html b/docs/samples/contact-center/index.html index f6a2cdbf6e1..a2c02f5df2f 100644 --- a/docs/samples/contact-center/index.html +++ b/docs/samples/contact-center/index.html @@ -76,7 +76,7 @@

-

Not Registered

+

Not Subscribed

@@ -112,6 +112,7 @@

+
Agent status diff --git a/packages/@webex/plugin-cc/src/cc.ts b/packages/@webex/plugin-cc/src/cc.ts index b3f052f202b..869c71f50bf 100644 --- a/packages/@webex/plugin-cc/src/cc.ts +++ b/packages/@webex/plugin-cc/src/cc.ts @@ -14,7 +14,7 @@ import {READY, CC_FILE} from './constants'; import Agent from './features/Agent'; import HttpRequest from './services/HttpRequest'; import WebRTCCalling from './WebRTCCalling'; -import {StationLoginSuccess} from './services/types'; +import {LogoutSuccess, StationLoginSuccess} from './services/types'; export default class ContactCenter extends WebexPlugin implements IContactCenter { namespace = 'cc'; @@ -136,4 +136,26 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter return Promise.reject(error); } } + + /** + * This is used for agent logout. + * @param options + * @returns Promise + * @throws Error + */ + public async stationLogout(options: {logoutReason: string}): Promise { + try { + const response = await this.agent.stationLogout(options); + + if (this.webRTCCalling) { + this.webRTCCalling.deregisterWebCallingLine(); + } + + return response; + } catch (error) { + this.$webex.logger.error('LOGOUT API FAILED'); + + return Promise.reject(new Error('Error while performing agent logout', error.message)); + } + } } diff --git a/packages/@webex/plugin-cc/src/features/Agent.ts b/packages/@webex/plugin-cc/src/features/Agent.ts index 14f7ed8afcc..1fa9be73c87 100644 --- a/packages/@webex/plugin-cc/src/features/Agent.ts +++ b/packages/@webex/plugin-cc/src/features/Agent.ts @@ -1,7 +1,7 @@ import {STATION_LOGIN_TYPE, WebexSDK} from '../types'; import HttpRequest from '../services/HttpRequest'; import AgentService from '../services/AgentService'; -import {StationLoginSuccess} from '../services/types'; +import {LogoutSuccess, StationLoginSuccess} from '../services/types'; export default class Agent { private webex: WebexSDK; @@ -34,4 +34,19 @@ export default class Agent { return Promise.reject(new Error('Error while performing agent login', error)); } } + + public async stationLogout(options: {logoutReason: string}): Promise { + const {logoutReason} = options; + + try { + const response = await this.agentService.stationLogout({ + logoutReason, + }); + this.webex.logger.log('Logout API SUCCESS'); + + return response; + } catch (error) { + return Promise.reject(error); + } + } } diff --git a/packages/@webex/plugin-cc/src/services/AgentService.ts b/packages/@webex/plugin-cc/src/services/AgentService.ts index 8eeb8f5bbbd..968dc7bd9b9 100644 --- a/packages/@webex/plugin-cc/src/services/AgentService.ts +++ b/packages/@webex/plugin-cc/src/services/AgentService.ts @@ -1,7 +1,7 @@ import {STATION_LOGIN_TYPE, WebexSDK, HTTP_METHODS} from '../types'; -import {AGENT, LOGIN_API, WCC_API_GATEWAY, WEB_RTC_PREFIX} from './constants'; +import {AGENT, LOGIN_API, LOGOUT_API, WCC_API_GATEWAY, WEB_RTC_PREFIX} from './constants'; import HttpRequest from './HttpRequest'; -import {StationLoginSuccess} from './types'; +import {LogoutSuccess, StationLoginSuccess} from './types'; export default class AgentService { private webex: WebexSDK; @@ -56,4 +56,28 @@ export default class AgentService { return Promise.reject(error); } } + + public async stationLogout(options: {logoutReason: string}): Promise { + try { + const {logoutReason} = options; + const payload = { + logoutReason, + }; + const data = await this.httpRequest.sendRequestWithEvent({ + service: WCC_API_GATEWAY, + resource: LOGOUT_API, + method: HTTP_METHODS.PUT, + payload, + eventType: 'Logout', + success: ['AgentLogoutSuccess'], + failure: ['AgentLogoutFailed'], + }); + + return data; + } catch (error) { + this.webex.logger.error(`Error during station logout: ${error}`); + + return Promise.reject(error); + } + } } diff --git a/packages/@webex/plugin-cc/src/services/constants.ts b/packages/@webex/plugin-cc/src/services/constants.ts index 24198ef0e33..d171227e485 100644 --- a/packages/@webex/plugin-cc/src/services/constants.ts +++ b/packages/@webex/plugin-cc/src/services/constants.ts @@ -6,4 +6,5 @@ export const AGENT = 'agent'; // CC GATEWAY API URL PATHS export const SUBSCRIBE_API = 'v1/notification/subscribe'; export const LOGIN_API = 'v1/agents/login'; +export const LOGOUT_API = 'v1/agents/logout'; export const WEB_RTC_PREFIX = 'webrtc-'; diff --git a/packages/@webex/plugin-cc/src/services/types.ts b/packages/@webex/plugin-cc/src/services/types.ts index 112b0ab65b6..4148fd0a636 100644 --- a/packages/@webex/plugin-cc/src/services/types.ts +++ b/packages/@webex/plugin-cc/src/services/types.ts @@ -236,3 +236,16 @@ export type SubscribeResponse = { }; message: string | null; }; + +export interface LogoutSuccess { + eventType: 'AgentDesktopMessage'; + agentId: string; + trackingId: string; + agentSessionId: string; + orgId: string; + status: string; + subStatus: string; + loggedOutBy?: string; + roles?: string[]; + type: 'AgentLogoutSuccess'; +} diff --git a/packages/@webex/plugin-cc/test/unit/spec/features/Agent.ts b/packages/@webex/plugin-cc/test/unit/spec/features/Agent.ts index ba35a86774f..b9b981af268 100644 --- a/packages/@webex/plugin-cc/test/unit/spec/features/Agent.ts +++ b/packages/@webex/plugin-cc/test/unit/spec/features/Agent.ts @@ -85,4 +85,29 @@ describe('Agent', () => { expect(webexMock.logger.log).toHaveBeenCalledWith('LOGIN API SUCCESS'); expect(response).toBe(loginResponse); }); -}); \ No newline at end of file + + describe('#stationLogout', () => { + it('should successfully log out the agent', async () => { + const options = { logoutReason: 'End of shift' }; + + const logoutResponse = { success: true }; + agentServiceMock.stationLogout.mockResolvedValue(logoutResponse); + + const result = await agent.stationLogout(options); + + expect(result).toBe(logoutResponse); + expect(agentServiceMock.stationLogout).toHaveBeenCalledWith(options); + expect(webex.logger.log).toHaveBeenCalledWith('Logout API SUCCESS'); + }); + + it('should handle logout error', async () => { + const options = { logoutReason: 'End of shift' }; + + const error = new Error('Logout failed'); + agentServiceMock.stationLogout.mockRejectedValue(error); + + await expect(agent.stationLogout(options)).rejects.toThrow('Error while performing agent Logout'); + expect(agentServiceMock.stationLogout).toHaveBeenCalledWith(options); + }); + }); +});