Skip to content

Commit 94dd415

Browse files
authored
feat(widgets): added-relogin-logic (webex#357)
1 parent 61b5ea9 commit 94dd415

File tree

9 files changed

+146
-21
lines changed

9 files changed

+146
-21
lines changed

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {useState} from 'react';
1+
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
@@ -8,17 +8,23 @@ export const useStationLogin = (props: UseStationLoginProps) => {
88
const loginCb = props.onLogin;
99
const logoutCb = props.onLogout;
1010
const logger = props.logger;
11+
const [isAgentLoggedIn, setIsAgentLoggedIn] = useState(props.isAgentLoggedIn);
1112
const [dialNumber, setDialNumber] = useState('');
1213
const [deviceType, setDeviceType] = useState('');
1314
const [team, setTeam] = useState('');
1415
const [loginSuccess, setLoginSuccess] = useState<StationLoginSuccess>();
1516
const [loginFailure, setLoginFailure] = useState<Error>();
1617
const [logoutSuccess, setLogoutSuccess] = useState<StationLogoutSuccess>();
1718

19+
useEffect(() => {
20+
setIsAgentLoggedIn(props.isAgentLoggedIn);
21+
}, [props.isAgentLoggedIn]);
22+
1823
const login = () => {
1924
cc.stationLogin({teamId: team, loginOption: deviceType, dialNumber: dialNumber})
2025
.then((res: StationLoginSuccess) => {
2126
setLoginSuccess(res);
27+
setIsAgentLoggedIn(true)
2228
store.setSelectedLoginOption(deviceType);
2329
if (loginCb) {
2430
loginCb();
@@ -36,6 +42,7 @@ export const useStationLogin = (props: UseStationLoginProps) => {
3642
cc.stationLogout({logoutReason: 'User requested logout'})
3743
.then((res: StationLogoutSuccess) => {
3844
setLogoutSuccess(res);
45+
setIsAgentLoggedIn(false);
3946
if (logoutCb) {
4047
logoutCb();
4148
}
@@ -47,15 +54,24 @@ export const useStationLogin = (props: UseStationLoginProps) => {
4754
});
4855
};
4956

57+
function relogin() {
58+
store.setSelectedLoginOption(deviceType);
59+
if (loginCb) {
60+
loginCb();
61+
}
62+
}
63+
5064
return {
5165
name: 'StationLogin',
5266
setDeviceType,
5367
setDialNumber,
5468
setTeam,
5569
login,
5670
logout,
71+
relogin,
5772
loginSuccess,
5873
loginFailure,
5974
logoutSuccess,
75+
isAgentLoggedIn,
6076
};
6177
};

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

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

99
const StationLogin: React.FunctionComponent<StationLoginProps> = observer(({onLogin, onLogout}) => {
10-
const {cc, teams, loginOptions, logger} = store;
11-
const result = useStationLogin({cc, onLogin, onLogout, logger});
10+
const {cc, teams, loginOptions, logger, deviceType, isAgentLoggedIn} = store;
11+
const result = useStationLogin({cc, onLogin, onLogout, logger, isAgentLoggedIn});
1212

1313
const props = {
1414
...result,
1515
teams,
1616
loginOptions,
17+
deviceType,
1718
};
1819
return <StationLoginPresentational {...props} />;
1920
});

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

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
1-
import React, {useEffect} from 'react';
1+
import React, {useEffect, useRef} from 'react';
22
import {StationLoginPresentationalProps} from './station-login.types';
33

44
import './station-login.style.scss';
55

66
const StationLoginPresentational: React.FunctionComponent<StationLoginPresentationalProps> = (props) => {
7-
const {name, teams, loginOptions, login, logout, setDeviceType, setDialNumber, setTeam} = props; // TODO: Use the loginSuccess, loginFailure, logoutSuccess props returned fromthe API response via helper file to reflect UI changes
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
820

921
useEffect(() => {
1022
const teamsDropdown = document.getElementById('teamsDropdown') as HTMLSelectElement;
@@ -34,6 +46,16 @@ const StationLoginPresentational: React.FunctionComponent<StationLoginPresentati
3446
}
3547
}, [teams, loginOptions]);
3648

49+
useEffect(() => {
50+
if (!isAgentLoggedIn) return;
51+
const agentLogin = document.querySelector('#LoginOption') as HTMLSelectElement;
52+
if (agentLogin && !agentLogin.value) {
53+
setDeviceType(deviceType);
54+
agentLogin.value = deviceType;
55+
relogin();
56+
}
57+
}, [isAgentLoggedIn]);
58+
3759
const selectLoginOption = (event: { target: { value: string; }; }) => {
3860
const dialNumber = document.querySelector('#dialNumber') as HTMLInputElement;
3961
const deviceType = event.target.value;
@@ -68,8 +90,11 @@ const StationLoginPresentational: React.FunctionComponent<StationLoginPresentati
6890
<option value="" hidden>Choose Agent Login Option...</option>
6991
</select>
7092
<input className='input' id="dialNumber" name="dialNumber" placeholder="Extension/Dial Number" type="text" onInput={updateDN} />
71-
<button id="AgentLogin" className='btn' onClick={login}>Login</button>
72-
<button id="logoutAgent" className='btn' onClick={logout}>Logout</button>
93+
{isAgentLoggedIn ? (
94+
<button id="logoutAgent" className='btn' onClick={logout}>Logout</button>
95+
) : (
96+
<button id="AgentLogin" className='btn' onClick={login}>Login</button>
97+
)}
7398
</fieldset>
7499
</div>
75100
</div>

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ export interface IStationLoginProps {
4949
*/
5050
logoutSuccess?: StationLogoutSuccess;
5151

52+
/**
53+
* Flag to indicate if the agent is logged in
54+
*/
55+
isAgentLoggedIn: boolean;
56+
57+
/**
58+
* The selected device type for agent login
59+
*/
60+
deviceType: string;
61+
5262
/**
5363
* Callback function to be invoked once the agent login is successful
5464
*/
@@ -78,6 +88,11 @@ export interface IStationLoginProps {
7888
* The logger instance from SDK
7989
*/
8090
logger: ILogger;
91+
92+
/**
93+
* Handler to relogin the agent
94+
*/
95+
relogin: () => void;
8196
}
8297

8398
export type StationLoginPresentationalProps = Pick<
@@ -87,14 +102,17 @@ export type StationLoginPresentationalProps = Pick<
87102
| 'loginOptions'
88103
| 'login'
89104
| 'logout'
105+
| 'relogin'
90106
| 'loginSuccess'
91107
| 'loginFailure'
92108
| 'logoutSuccess'
93109
| 'setDeviceType'
94110
| 'setDialNumber'
95111
| 'setTeam'
112+
| 'isAgentLoggedIn'
113+
| 'deviceType'
96114
>;
97115

98-
export type UseStationLoginProps = Pick<IStationLoginProps, 'cc' | 'onLogin' | 'onLogout' | 'logger'>;
116+
export type UseStationLoginProps = Pick<IStationLoginProps, 'cc' | 'onLogin' | 'onLogout' | 'logger' | 'isAgentLoggedIn'>;
99117

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

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

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const logoutCb = jest.fn();
3131
const logger = {
3232
error: jest.fn()
3333
};
34+
const isAgentLoggedIn = false;
3435

3536
describe('useStationLogin Hook', () => {
3637
afterEach(() => {
@@ -67,7 +68,7 @@ describe('useStationLogin Hook', () => {
6768
ccMock.stationLogin.mockResolvedValue(successResponse);
6869
const setSelectedLoginOptionSpy = jest.spyOn(require('@webex/cc-store'), 'setSelectedLoginOption');
6970

70-
const {result} = renderHook(() => useStationLogin({cc: ccMock, onLogin: loginCb, onLogout: logoutCb, logger}));
71+
const {result} = renderHook(() => useStationLogin({cc: ccMock, onLogin: loginCb, onLogout: logoutCb, logger, isAgentLoggedIn}));
7172

7273
act(() => {
7374
result.current.setDeviceType(loginParams.loginOption);
@@ -89,6 +90,7 @@ describe('useStationLogin Hook', () => {
8990

9091
expect(result.current).toEqual({
9192
name: 'StationLogin',
93+
isAgentLoggedIn: true,
9294
setDeviceType: expect.any(Function),
9395
setDialNumber: expect.any(Function),
9496
setTeam: expect.any(Function),
@@ -97,6 +99,7 @@ describe('useStationLogin Hook', () => {
9799
loginSuccess: successResponse,
98100
loginFailure: undefined,
99101
logoutSuccess: undefined,
102+
relogin: expect.any(Function),
100103
});
101104

102105
expect(setSelectedLoginOptionSpy).toHaveBeenCalledWith(loginParams.loginOption);
@@ -109,7 +112,7 @@ describe('useStationLogin Hook', () => {
109112
const setSelectedLoginOptionSpy = jest.spyOn(require('@webex/cc-store'), 'setSelectedLoginOption');
110113

111114
loginCb.mockClear();
112-
const {result} = renderHook(() => useStationLogin({cc: ccMock, onLogin: loginCb, onLogout: logoutCb, logger}));
115+
const {result} = renderHook(() => useStationLogin({cc: ccMock, onLogin: loginCb, onLogout: logoutCb, logger, isAgentLoggedIn}));
113116

114117
act(() => {
115118
result.current.setDeviceType(loginParams.loginOption);
@@ -131,6 +134,7 @@ describe('useStationLogin Hook', () => {
131134

132135
expect(result.current).toEqual({
133136
name: 'StationLogin',
137+
isAgentLoggedIn: false,
134138
setDeviceType: expect.any(Function),
135139
setDialNumber: expect.any(Function),
136140
setTeam: expect.any(Function),
@@ -139,6 +143,7 @@ describe('useStationLogin Hook', () => {
139143
loginSuccess: undefined,
140144
loginFailure: errorResponse,
141145
logoutSuccess: undefined,
146+
relogin: expect.any(Function),
142147
});
143148

144149
expect(setSelectedLoginOptionSpy).not.toHaveBeenCalled();
@@ -150,7 +155,7 @@ describe('useStationLogin Hook', () => {
150155
ccMock.stationLogin.mockResolvedValue({});
151156

152157
const { result } = renderHook(() =>
153-
useStationLogin({cc: ccMock, onLogout: logoutCb, logger})
158+
useStationLogin({cc: ccMock, onLogout: logoutCb, logger, isAgentLoggedIn})
154159
);
155160

156161
await act(async () => {
@@ -167,7 +172,7 @@ describe('useStationLogin Hook', () => {
167172
ccMock.stationLogin.mockRejectedValue(errorResponse);
168173

169174
loginCb.mockClear();
170-
const {result} = renderHook(() => useStationLogin({cc: ccMock, onLogin: loginCb, onLogout: logoutCb, logger}));
175+
const {result} = renderHook(() => useStationLogin({cc: ccMock, onLogin: loginCb, onLogout: logoutCb, logger, isAgentLoggedIn}));
171176

172177
act(() => {
173178
result.current.setDeviceType(loginParams.loginOption);
@@ -190,6 +195,7 @@ describe('useStationLogin Hook', () => {
190195

191196
expect(result.current).toEqual({
192197
name: 'StationLogin',
198+
isAgentLoggedIn: true,
193199
setDeviceType: expect.any(Function),
194200
setDialNumber: expect.any(Function),
195201
setTeam: expect.any(Function),
@@ -198,6 +204,7 @@ describe('useStationLogin Hook', () => {
198204
loginSuccess: undefined,
199205
loginFailure: errorResponse,
200206
logoutSuccess: undefined,
207+
relogin: expect.any(Function),
201208
});
202209
});
203210
});
@@ -220,7 +227,7 @@ describe('useStationLogin Hook', () => {
220227

221228
ccMock.stationLogout.mockResolvedValue(successResponse);
222229

223-
const {result} = renderHook(() => useStationLogin({cc: ccMock, onLogin: loginCb, onLogout: logoutCb, logger}));
230+
const {result} = renderHook(() => useStationLogin({cc: ccMock, onLogin: loginCb, onLogout: logoutCb, logger, isAgentLoggedIn}));
224231

225232
await act(async () => {
226233
await result.current.logout();
@@ -232,6 +239,7 @@ describe('useStationLogin Hook', () => {
232239

233240
expect(result.current).toEqual({
234241
name: 'StationLogin',
242+
isAgentLoggedIn: false,
235243
setDeviceType: expect.any(Function),
236244
setDialNumber: expect.any(Function),
237245
setTeam: expect.any(Function),
@@ -240,6 +248,7 @@ describe('useStationLogin Hook', () => {
240248
loginSuccess: undefined,
241249
loginFailure: undefined,
242250
logoutSuccess: successResponse,
251+
relogin: expect.any(Function),
243252
});
244253
});
245254
});
@@ -248,7 +257,7 @@ describe('useStationLogin Hook', () => {
248257
ccMock.stationLogout.mockRejectedValue(new Error('Logout failed'));
249258

250259
const {result} = renderHook(() =>
251-
useStationLogin({cc: ccMock, onLogin: loginCb, onLogout: logoutCb, logger})
260+
useStationLogin({cc: ccMock, onLogin: loginCb, onLogout: logoutCb, logger, isAgentLoggedIn})
252261
);
253262

254263
await act(async () => {
@@ -266,7 +275,7 @@ describe('useStationLogin Hook', () => {
266275
it('should not call logout callback if not present', async () => {
267276
ccMock.stationLogout.mockResolvedValue({});
268277

269-
const {result} = renderHook(() => useStationLogin({cc: ccMock, onLogin: loginCb, logger}));
278+
const {result} = renderHook(() => useStationLogin({cc: ccMock, onLogin: loginCb, logger, isAgentLoggedIn}));
270279

271280
await act(async () => {
272281
await result.current.logout();
@@ -276,4 +285,19 @@ describe('useStationLogin Hook', () => {
276285
expect(logoutCb).not.toHaveBeenCalled();
277286
});
278287
});
288+
289+
it('should call relogin and set device type', async () => {
290+
const setSelectedLoginOptionSpy = jest.spyOn(require('@webex/cc-store'), 'setSelectedLoginOption');
291+
292+
const { result } = renderHook(() => useStationLogin({ cc: ccMock, onLogin: loginCb, onLogout: logoutCb, logger, isAgentLoggedIn }));
293+
294+
act(() => {
295+
result.current.relogin();
296+
});
297+
298+
await waitFor(() => {
299+
expect(setSelectedLoginOptionSpy).toHaveBeenCalled();
300+
expect(loginCb).toHaveBeenCalled();
301+
});
302+
});
279303
});

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import '@testing-library/jest-dom';
77
const teams = ['team123', 'team456'];
88

99
const loginOptions = ['EXTENSION', 'AGENT_DN', 'BROWSER'];
10+
const deviceType = 'BROWSER';
1011

1112
// Mock the store import
1213
jest.mock('@webex/cc-store', () => {return {
1314
cc: {},
1415
teams,
15-
loginOptions
16+
loginOptions,
17+
deviceType,
1618
}});
1719

1820
const loginCb = jest.fn();

0 commit comments

Comments
 (0)