-
Notifications
You must be signed in to change notification settings - Fork 0
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(cc): getBuddyAgents() implementation #1
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -148,11 +148,41 @@ async function handleAgentLogin(e) { | |
} | ||
} | ||
|
||
async function fetchBuddyAgents() { | ||
try { | ||
const buddyAgentsResponse = await webex.cc.getBuddyAgents({channelName: 'telephony', state: 'Available'}); | ||
const buddyAgentsDropdown = document.getElementById('buddyAgentsDropdown'); | ||
buddyAgentsDropdown.innerHTML = ''; // Clear previous options | ||
|
||
if (buddyAgentsResponse.agentList.length === 0) { | ||
const option = document.createElement('option'); | ||
option.text = 'No buddy agents available'; | ||
option.disabled = true; | ||
buddyAgentsDropdown.add(option); | ||
return; | ||
} | ||
|
||
buddyAgentsResponse.agentList.forEach((agent) => { | ||
const option = document.createElement('option'); | ||
option.text = `${agent.agentName} - ${agent.state}`; | ||
option.value = agent.agentId; | ||
buddyAgentsDropdown.add(option); | ||
}); | ||
} catch (error) { | ||
const buddyAgentsDropdown = document.getElementById('buddyAgentsDropdown'); | ||
buddyAgentsDropdown.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. This line can be moved to |
||
const option = document.createElement('option'); | ||
option.text = `Failed to fetch buddy agents, ${error}`; | ||
option.disabled = true; | ||
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. All the three lines can be written in simple way From
To
Please check all other places as well. |
||
buddyAgentsDropdown.add(option); | ||
console.log('Failed to fetch buddy agents', error); | ||
} | ||
} | ||
|
||
function doAgentLogin() { | ||
webex.cc.stationLogin({teamId: teamsDropdown.value, loginOption: agentDeviceType, dialNumber: dialNumber.value}).then((response) => { | ||
console.log('Agent Logged in successfully', response); | ||
} | ||
).catch((error) => { | ||
}).catch((error) => { | ||
console.log('Agent Login failed', error); | ||
}); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,12 +9,14 @@ import { | |
SubscribeRequest, | ||
WelcomeEvent, | ||
STATION_LOGIN_TYPE, | ||
GetBuddyAgentsRequest, | ||
CHANNEL_NAME, | ||
} from './types'; | ||
import {BuddyAgentsSuccess, StationLoginSuccess} from './services/types'; | ||
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'; | ||
|
||
export default class ContactCenter extends WebexPlugin implements IContactCenter { | ||
namespace = 'cc'; | ||
|
@@ -136,4 +138,36 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter | |
return Promise.reject(error); | ||
} | ||
} | ||
|
||
/** | ||
* @param options - GetBuddyAgentsRequest | ||
* @returns Promise<BuddyAgentsSuccess> | ||
* @throws Error | ||
* @example | ||
* const buddyAgents = await webex.cc.getBuddyAgents({ | ||
* channelType: CHANNEL_TYPE.TELEPHONY, | ||
* state: BuddyAgentState.AVAILABLE, | ||
* }); | ||
*/ | ||
public async getBuddyAgents( | ||
options: GetBuddyAgentsRequest = { | ||
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 still have Get in the name here |
||
channelName: CHANNEL_NAME.TELEPHONY, | ||
} | ||
): Promise<BuddyAgentsSuccess> { | ||
try { | ||
const {channelName, state} = options; | ||
const buddyAgents = await this.agent.getBuddyAgents({ | ||
agentProfileId: this.agentConfig.agentProfileId, | ||
channelName, | ||
state, | ||
}); | ||
this.$webex.logger.log('Get Buddy Agents API SUCCESS'); | ||
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. Agent code is already logging the success message. This will add redundant log |
||
|
||
return buddyAgents; | ||
} catch (error) { | ||
this.$webex.logger.error('Get Buddy Agents API FAILED'); | ||
|
||
return Promise.reject(new Error('Error while retrieving buddy agents', error.message)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,15 @@ | ||
import {STATION_LOGIN_TYPE, WebexSDK, HTTP_METHODS} from '../types'; | ||
import {AGENT, LOGIN_API, WCC_API_GATEWAY, WEB_RTC_PREFIX} from './constants'; | ||
import { | ||
AGENT, | ||
GET_BUDDY_AGENTS_API, | ||
BuddyAgentsEvent, | ||
BuddyAgentsRetrieveFailedEvent, | ||
LOGIN_API, | ||
WCC_API_GATEWAY, | ||
WEB_RTC_PREFIX, | ||
} from './constants'; | ||
import HttpRequest from './HttpRequest'; | ||
import {StationLoginSuccess} from './types'; | ||
import {BuddyAgentsSuccess, BuddyAgents, StationLoginSuccess} from './types'; | ||
|
||
export default class AgentService { | ||
private webex: WebexSDK; | ||
|
@@ -56,4 +64,28 @@ export default class AgentService { | |
return Promise.reject(error); | ||
} | ||
} | ||
|
||
public async getBuddyAgents(options: BuddyAgents): Promise<BuddyAgentsSuccess> { | ||
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. Return type for all the methods should be generic not just associated with success |
||
try { | ||
const data = await this.httpRequest.sendRequestWithEvent({ | ||
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. Suggestion (Not to be fixed in this PR) - We should allow cc - @Kesari3008, Ravi |
||
service: WCC_API_GATEWAY, | ||
resource: GET_BUDDY_AGENTS_API, | ||
method: HTTP_METHODS.POST, | ||
payload: { | ||
agentProfileId: options.agentProfileId, | ||
mediaType: options.channelName, | ||
state: options.state || undefined, | ||
}, | ||
eventType: BuddyAgentsEvent, | ||
success: [BuddyAgentsEvent], | ||
failure: [BuddyAgentsRetrieveFailedEvent], | ||
}); | ||
|
||
return data as BuddyAgentsSuccess; | ||
} catch (error) { | ||
this.webex.logger.error(`Error during get buddy agents: ${error}`); | ||
|
||
return Promise.reject(new Error('Error while retrieving buddy agents', error)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -87,14 +87,24 @@ class HttpRequest { | |
try { | ||
const {service, resource, method, payload, eventType, success, failure} = options; | ||
|
||
// prune undefined values | ||
Object.keys(payload).forEach((key) => payload[key] === undefined && delete payload[key]); | ||
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. What is this code supposed to be doing ? 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. {
"someKey": "someValue",
"someOtherKey": undefined
} will get transformed to {
"someKey": "someValue"
} 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. In which case we are going to pass a key with |
||
|
||
// Send the service request | ||
const response = await this.webex.request({ | ||
service, | ||
resource, | ||
method, | ||
body: payload, | ||
}); | ||
this.webex.logger.log(`Service request sent successfully: ${response}`); | ||
// @ts-ignore | ||
const trackingid = response.headers.trackingid; | ||
|
||
this.webex.logger.log( | ||
`Service request sent successfully to ${service}/${resource} with payload: ${JSON.stringify( | ||
payload | ||
)}, Request TrackingID: ${trackingid}` | ||
); | ||
|
||
// Listen for the event | ||
return new Promise((resolve, reject) => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,4 +6,10 @@ 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 GET_BUDDY_AGENTS_API = 'v1/agents/buddyList'; | ||
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. Remove Get from here as well |
||
export const WEB_RTC_PREFIX = 'webrtc-'; | ||
|
||
export const AgentDesktopMessage = 'AgentDesktopMessage'; | ||
|
||
export const BuddyAgentsEvent = 'BuddyAgents'; | ||
export const BuddyAgentsRetrieveFailedEvent = 'BuddyAgentsRetrieveFailed'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -148,3 +148,24 @@ export interface SubscribeRequest { | |
} | ||
|
||
export type EventResult = IAgentProfile; | ||
|
||
export const CHANNEL_NAME = { | ||
TELEPHONY: 'telephony', | ||
CHAT: 'chat', | ||
SOCIAL: 'social', | ||
EMAIL: 'email', | ||
} as const; | ||
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. Why are we using For this we can create 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. @rarajes2 This is the new way of creating enum. Please refer to this document: https://confluence-eng-gpk2.cisco.com/conf/display/WTWC/How+to+use+enums+and+alternatives |
||
|
||
export type CHANNEL_NAME = Enum<typeof CHANNEL_NAME>; | ||
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 don't have to create a separate type like this. The constant defined above can be converted to an 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. @rarajes2 , Can you please provide an example on how to do this? |
||
|
||
export const BUDDY_AGENT_STATE = { | ||
AVAILABLE: 'Available', | ||
IDLE: 'Idle', | ||
} as const; | ||
|
||
export type BUDDY_AGENT_STATE = Enum<typeof BUDDY_AGENT_STATE>; | ||
|
||
export type GetBuddyAgentsRequest = { | ||
channelName: CHANNEL_NAME; | ||
state?: BUDDY_AGENT_STATE; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
import { STATION_LOGIN_TYPE, WebexSDK } from '../../../../src/types'; | ||
import {STATION_LOGIN_TYPE, WebexSDK, CHANNEL_NAME, BUDDY_AGENT_STATE} from '../../../../src/types'; | ||
import HttpRequest from '../../../../src/services/HttpRequest'; | ||
import AgentService from '../../../../src/services/AgentService'; | ||
import Agent from '../../../../src/features/Agent'; | ||
import { StationLoginSuccess } from '../../../../src/services/types'; | ||
import {BuddyAgents, BuddyAgentsSuccess, StationLoginSuccess} from '../../../../src/services/types'; | ||
|
||
// Mock dependencies | ||
jest.mock('../../../../src/services/AgentService'); | ||
|
@@ -85,4 +85,49 @@ describe('Agent', () => { | |
expect(webexMock.logger.log).toHaveBeenCalledWith('LOGIN API SUCCESS'); | ||
expect(response).toBe(loginResponse); | ||
}); | ||
}); | ||
|
||
describe('getBuddyAgents', () => { | ||
const options: BuddyAgents = { | ||
channelName: CHANNEL_NAME.TELEPHONY, | ||
state: BUDDY_AGENT_STATE.AVAILABLE, | ||
agentProfileId: '123', | ||
}; | ||
|
||
it('should return buddy agents on success', async () => { | ||
const buddyAgentsSuccess: BuddyAgentsSuccess = { | ||
agentId: 'agentId1', | ||
eventType: 'AgentDesktopMessage', | ||
agentList: [ | ||
{ | ||
agentId: '12345', | ||
state: 'Available', | ||
teamId: 'abcd', | ||
dn: '1001', | ||
agentName: 'Agent1 Name1', | ||
siteId: 'site1', | ||
}, | ||
], | ||
orgId: 'org1', | ||
trackingId: 'track1', | ||
agentSessionId: 'session1', | ||
type: 'BuddyAgents', | ||
}; | ||
agentServiceMock.getBuddyAgents.mockResolvedValue(buddyAgentsSuccess); | ||
|
||
const result = await agent.getBuddyAgents(options); | ||
|
||
expect(result).toEqual(buddyAgentsSuccess); | ||
expect(agentServiceMock.getBuddyAgents).toHaveBeenCalledWith(options); | ||
}); | ||
|
||
it('should throw an error when getBuddyAgents fails', async () => { | ||
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 should have one testcase for error response as well |
||
const error = new Error('API Error'); | ||
agentServiceMock.getBuddyAgents.mockRejectedValue(error); | ||
|
||
await expect(agent.getBuddyAgents(options)).rejects.toThrow( | ||
'Error while retrieving buddy agents' | ||
); | ||
expect(agentServiceMock.getBuddyAgents).toHaveBeenCalledWith(options); | ||
}); | ||
}); | ||
}); |
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.
Please add this to the top of file. Please remove from the try block as well.