Skip to content

Commit f7d75ca

Browse files
pagour98parv_gour
and
parv_gour
authored
feat(cc-widgets): added Agent-Multi-Login-Alert Feature (webex#364)
Co-authored-by: parv_gour <parv_gour@PAGOUR-M-D8B2>
1 parent 1965742 commit f7d75ca

File tree

9 files changed

+379
-85
lines changed

9 files changed

+379
-85
lines changed

packages/contact-center/station-login/src/helper.ts

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {useState, useEffect} from 'react';
22
import {StationLoginSuccess, StationLogoutSuccess} from '@webex/plugin-cc';
33
import {UseStationLoginProps} from './station-login/station-login.types';
44
import store from '@webex/cc-store'; // we need to import as we are losing the context of this in store
5+
import {AGENT_MULTI_LOGIN} from './station-login/constants';
56

67
export const useStationLogin = (props: UseStationLoginProps) => {
78
const cc = props.cc;
@@ -15,21 +16,60 @@ export const useStationLogin = (props: UseStationLoginProps) => {
1516
const [loginSuccess, setLoginSuccess] = useState<StationLoginSuccess>();
1617
const [loginFailure, setLoginFailure] = useState<Error>();
1718
const [logoutSuccess, setLogoutSuccess] = useState<StationLogoutSuccess>();
19+
const [showMultipleLoginAlert, setShowMultipleLoginAlert] = useState(false);
20+
21+
useEffect(() => {
22+
const handleMultiLoginCloseSession = (data) => {
23+
if (data && typeof data === 'object' && data.type === 'AgentMultiLoginCloseSession') {
24+
setShowMultipleLoginAlert(true);
25+
}
26+
};
27+
28+
cc.on(AGENT_MULTI_LOGIN, handleMultiLoginCloseSession);
29+
30+
return () => {
31+
cc.off(AGENT_MULTI_LOGIN, handleMultiLoginCloseSession);
32+
};
33+
}, [cc]);
1834

1935
useEffect(() => {
2036
setIsAgentLoggedIn(props.isAgentLoggedIn);
2137
}, [props.isAgentLoggedIn]);
2238

39+
const handleContinue = async () => {
40+
try {
41+
setShowMultipleLoginAlert(false);
42+
const profile = await cc.register();
43+
if (profile.isAgentLoggedIn) {
44+
logger.log(`Agent Relogin Success`, {
45+
module: 'widget-station-login#station-login/helper.ts',
46+
method: 'handleContinue',
47+
});
48+
} else {
49+
logger.error(`Agent Relogin Failed`, {
50+
module: 'widget-station-login#station-login/helper.ts',
51+
method: 'handleContinue',
52+
});
53+
}
54+
} catch (error) {
55+
logger.error(`Error handling agent multi login continue: ${error}`, {
56+
module: 'widget-station-login#station-login/index.tsx',
57+
method: 'handleContinue',
58+
});
59+
}
60+
};
61+
2362
const login = () => {
2463
cc.stationLogin({teamId: team, loginOption: deviceType, dialNumber: dialNumber})
2564
.then((res: StationLoginSuccess) => {
2665
setLoginSuccess(res);
27-
setIsAgentLoggedIn(true)
66+
setIsAgentLoggedIn(true);
2867
store.setSelectedLoginOption(deviceType);
2968
if (loginCb) {
3069
loginCb();
3170
}
32-
}).catch((error: Error) => {
71+
})
72+
.catch((error: Error) => {
3373
logger.error(`Error logging in: ${error}`, {
3474
module: 'widget-station-login#helper.ts',
3575
method: 'login',
@@ -46,7 +86,8 @@ export const useStationLogin = (props: UseStationLoginProps) => {
4686
if (logoutCb) {
4787
logoutCb();
4888
}
49-
}).catch((error: Error) => {
89+
})
90+
.catch((error: Error) => {
5091
logger.error(`Error logging out: ${error}`, {
5192
module: 'widget-station-login#helper.ts',
5293
method: 'logout',
@@ -72,6 +113,8 @@ export const useStationLogin = (props: UseStationLoginProps) => {
72113
loginSuccess,
73114
loginFailure,
74115
logoutSuccess,
116+
showMultipleLoginAlert,
75117
isAgentLoggedIn,
118+
handleContinue,
76119
};
77120
};
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
.modal {
2+
width: 400px;
3+
border: none;
4+
border-radius: 10px;
5+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
6+
padding: 20px;
7+
text-align: center;
8+
}
9+
10+
.modal-content {
11+
display: flex;
12+
justify-content: flex-end; // Aligns the button to the right
13+
}
14+
15+
.modal::backdrop {
16+
background: rgba(0, 0, 0, 0.5);
17+
}
18+
19+
h2 {
20+
margin-top: 0;
21+
}
22+
23+
#ContinueButton {
24+
background-color: #0078d4;
25+
color: white;
26+
border: none;
27+
padding: 10px 20px;
28+
border-radius: 5px;
29+
cursor: pointer;
30+
font-size: 16px;
31+
cursor: pointer;
32+
}
33+
34+
#ContinueButton:hover {
35+
background-color: #005a9e;
36+
}
37+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const MULTIPLE_SIGN_IN_ALERT_MESSAGE =
2+
'You are signed in to the Desktop in multiple application instances. Click Continue to proceed with the Desktop in this application instance. Else, close this window.';
3+
4+
export const MULTIPLE_SIGN_IN_ALERT_TITLE = 'Multiple Sign In Alert';
5+
6+
export const AGENT_MULTI_LOGIN = 'agent:multiLogin';

packages/contact-center/station-login/src/station-login/index.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,16 @@ import {useStationLogin} from '../helper';
77
import {StationLoginProps} from './station-login.types';
88

99
const StationLoginComponent: React.FunctionComponent<StationLoginProps> = ({onLogin, onLogout}) => {
10-
const {cc, teams, loginOptions, logger, deviceType, isAgentLoggedIn} = store;
11-
const result = useStationLogin({cc, onLogin, onLogout, logger, isAgentLoggedIn});
10+
const {cc, teams, loginOptions, logger, deviceType, isAgentLoggedIn, handleContinue, showMultipleLoginAlert} = store;
11+
const result = useStationLogin({
12+
cc,
13+
onLogin,
14+
onLogout,
15+
logger,
16+
isAgentLoggedIn,
17+
handleContinue,
18+
showMultipleLoginAlert,
19+
});
1220

1321
const props = {
1422
...result,
Lines changed: 82 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,12 @@
1-
import React, {useEffect, useRef} from 'react';
2-
import {StationLoginPresentationalProps} from './station-login.types';
3-
1+
import React, { useEffect, useRef} from 'react';
2+
import { StationLoginPresentationalProps } from './station-login.types';
43
import './station-login.style.scss';
4+
import { MULTIPLE_SIGN_IN_ALERT_MESSAGE, MULTIPLE_SIGN_IN_ALERT_TITLE } from './constants';
5+
import './alert-modal.scss';
56

67
const StationLoginPresentational: React.FunctionComponent<StationLoginPresentationalProps> = (props) => {
7-
const {
8-
name,
9-
teams,
10-
loginOptions,
11-
login,
12-
logout,
13-
relogin,
14-
setDeviceType,
15-
setDialNumber,
16-
setTeam,
17-
isAgentLoggedIn,
18-
deviceType
19-
} = props; // TODO: Use the loginSuccess, loginFailure, logoutSuccess props returned fromthe API response via helper file to reflect UI changes
8+
const { name, teams, loginOptions, login, logout, relogin, setDeviceType, setDialNumber, setTeam, isAgentLoggedIn, deviceType, showMultipleLoginAlert, handleContinue} = props; // TODO: Use the loginSuccess, loginFailure, logoutSuccess props returned fromthe API response via helper file to reflect UI changes
9+
const modalRef = useRef<HTMLDialogElement>(null);
2010

2111
useEffect(() => {
2212
const teamsDropdown = document.getElementById('teamsDropdown') as HTMLSelectElement;
@@ -37,7 +27,7 @@ const StationLoginPresentational: React.FunctionComponent<StationLoginPresentati
3727
}
3828
}
3929
if (loginOptions.length > 0) {
40-
loginOptions.forEach((options)=> {
30+
loginOptions.forEach((options) => {
4131
const option = document.createElement('option');
4232
option.text = options;
4333
option.value = options;
@@ -46,6 +36,13 @@ const StationLoginPresentational: React.FunctionComponent<StationLoginPresentati
4636
}
4737
}, [teams, loginOptions]);
4838

39+
useEffect(() => {
40+
const modal = modalRef.current;
41+
if (showMultipleLoginAlert && modal) {
42+
modal.showModal();
43+
}
44+
}, [showMultipleLoginAlert, modalRef]);
45+
4946
useEffect(() => {
5047
if (!isAgentLoggedIn) return;
5148
const agentLogin = document.querySelector('#LoginOption') as HTMLSelectElement;
@@ -56,7 +53,7 @@ const StationLoginPresentational: React.FunctionComponent<StationLoginPresentati
5653
}
5754
}, [isAgentLoggedIn]);
5855

59-
const selectLoginOption = (event: { target: { value: string; }; }) => {
56+
const selectLoginOption = (event: { target: { value: string } }) => {
6057
const dialNumber = document.querySelector('#dialNumber') as HTMLInputElement;
6158
const deviceType = event.target.value;
6259
setDeviceType(deviceType);
@@ -67,41 +64,80 @@ const StationLoginPresentational: React.FunctionComponent<StationLoginPresentati
6764
}
6865
};
6966

67+
const continueClicked = () => {
68+
const modal = modalRef.current;
69+
if (modal) {
70+
modal.close();
71+
handleContinue();
72+
}
73+
};
74+
7075
function updateDN() {
7176
const dialNumber = document.querySelector('#dialNumber') as HTMLInputElement;
7277
setDialNumber(dialNumber.value);
7378
}
7479

7580
return (
76-
<><h1 data-testid="station-login-heading">{name}</h1>
77-
<div className='box'>
78-
<section className="section-box">
79-
<fieldset className='fieldset'>
80-
<legend className='legend-box'>Agent</legend>
81-
<div style={{ display: 'flex', flexDirection: 'column', flexGrow: 1 }}>
82-
<div style={{ display: 'flex', gap: '1rem' }}>
83-
<fieldset style={{border: '1px solid #ccc', borderRadius: '5px', padding: '10px', marginBottom: '20px', flex: 0.69 }}>
84-
<legend className='legend-box'>Select Team</legend>
85-
<select id="teamsDropdown" className='select'>Teams</select>
86-
</fieldset>
87-
<fieldset className='fieldset'>
88-
<legend className='legend-box'>Agent Login</legend>
89-
<select name="LoginOption" id="LoginOption" className='select' onChange={selectLoginOption}>
90-
<option value="" hidden>Choose Agent Login Option...</option>
91-
</select>
92-
<input className='input' id="dialNumber" name="dialNumber" placeholder="Extension/Dial Number" type="text" onInput={updateDN} />
93-
{isAgentLoggedIn ? (
94-
<button id="logoutAgent" className='btn' onClick={logout}>Logout</button>
95-
) : (
96-
<button id="AgentLogin" className='btn' onClick={login}>Login</button>
97-
)}
98-
</fieldset>
99-
</div>
81+
<div>
82+
{showMultipleLoginAlert && (
83+
<dialog ref={modalRef} className="modal">
84+
<h2>{MULTIPLE_SIGN_IN_ALERT_TITLE}</h2>
85+
<p>{MULTIPLE_SIGN_IN_ALERT_MESSAGE}</p>
86+
<div className='modal-content'>
87+
<button id="ContinueButton" data-testid="ContinueButton" onClick={continueClicked}>Continue</button>
10088
</div>
101-
</fieldset>
102-
</section>
103-
</div></>
89+
</dialog>
90+
)}
91+
<h1 data-testid="station-login-heading">{name}</h1>
92+
<div className="box">
93+
<section className="section-box">
94+
<fieldset className="fieldset">
95+
<legend className="legend-box">Agent</legend>
96+
<div style={{ display: 'flex', flexDirection: 'column', flexGrow: 1 }}>
97+
<div style={{ display: 'flex', gap: '1rem' }}>
98+
<fieldset
99+
style={{
100+
border: '1px solid #ccc',
101+
borderRadius: '5px',
102+
padding: '10px',
103+
marginBottom: '20px',
104+
flex: 0.69,
105+
}}
106+
>
107+
<legend className="legend-box">Select Team</legend>
108+
<select id="teamsDropdown" className="select">
109+
Teams
110+
</select>
111+
</fieldset>
112+
<fieldset className="fieldset">
113+
<legend className="legend-box">Agent Login</legend>
114+
<select name="LoginOption" id="LoginOption" className="select" onChange={selectLoginOption}>
115+
<option value="" hidden>
116+
Choose Agent Login Option...
117+
</option>
118+
</select>
119+
<input
120+
className="input"
121+
id="dialNumber"
122+
name="dialNumber"
123+
placeholder="Extension/Dial Number"
124+
type="text"
125+
onInput={updateDN}
126+
/>
127+
<button id="AgentLogin" className="btn" onClick={login}>
128+
Login
129+
</button>
130+
<button id="logoutAgent" className="btn" onClick={logout}>
131+
Logout
132+
</button>
133+
</fieldset>
134+
</div>
135+
</div>
136+
</fieldset>
137+
</section>
138+
</div>
139+
</div>
104140
);
105141
};
106142

107-
export default StationLoginPresentational;
143+
export default StationLoginPresentational;

packages/contact-center/station-login/src/station-login/station-login.types.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {AgentLogin, IContactCenter, StationLoginSuccess, StationLogoutSuccess, Team} from '@webex/plugin-cc';
1+
import {IContactCenter, StationLoginSuccess, StationLogoutSuccess, Team} from '@webex/plugin-cc';
22
import {ILogger} from '@webex/cc-store';
33
/**
44
* Interface representing the properties for the Station Login component.
@@ -93,6 +93,16 @@ export interface IStationLoginProps {
9393
* Handler to relogin the agent
9494
*/
9595
relogin: () => void;
96+
97+
/**
98+
* Handler to relogin the agent when the agent is already logged in
99+
*/
100+
handleContinue: () => void;
101+
102+
/**
103+
* Flag to indicate if the alert should be shown
104+
*/
105+
showMultipleLoginAlert: boolean;
96106
}
97107

98108
export type StationLoginPresentationalProps = Pick<
@@ -110,9 +120,15 @@ export type StationLoginPresentationalProps = Pick<
110120
| 'setDialNumber'
111121
| 'setTeam'
112122
| 'isAgentLoggedIn'
123+
| 'handleContinue'
113124
| 'deviceType'
114-
>;
125+
> & {
126+
showMultipleLoginAlert: boolean;
127+
};
115128

116-
export type UseStationLoginProps = Pick<IStationLoginProps, 'cc' | 'onLogin' | 'onLogout' | 'logger' | 'isAgentLoggedIn'>;
129+
export type UseStationLoginProps = Pick<
130+
IStationLoginProps,
131+
'cc' | 'onLogin' | 'onLogout' | 'logger' | 'isAgentLoggedIn' | 'handleContinue' | 'showMultipleLoginAlert'
132+
>;
117133

118134
export type StationLoginProps = Pick<IStationLoginProps, 'onLogin' | 'onLogout'>;

0 commit comments

Comments
 (0)