Skip to content
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(widget-cc-station-login): Spark 575845 login widget #239

Open
wants to merge 33 commits into
base: feat/cc-widgets
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
383aafc
fix: convert npm to yarn
mkesavan13 Oct 21, 2024
520fac9
Merge remote-tracking branch 'upstream/master' into convert_to_yarn
mkesavan13 Oct 21, 2024
a9d5669
fix: yarn lock
mkesavan13 Oct 21, 2024
c9fe972
fix: rename folder to match package name
mkesavan13 Oct 22, 2024
6d24f89
fix: move to yarn 4.5.1
mkesavan13 Oct 22, 2024
09adcc5
fix: nitpick self review comments
mkesavan13 Oct 24, 2024
debdaaa
feat(cc-widgets): inital-packages-setup
ShreyasSharma28 Oct 24, 2024
f775ae2
fix(cc-widgets): move-widgets-inside-webex-folder
ShreyasSharma28 Oct 24, 2024
11a111b
fix(cc-widgets): remove-yarn-changes
ShreyasSharma28 Oct 24, 2024
840074c
fix(cc-widgets): added-babel-webpack-configs
ShreyasSharma28 Oct 24, 2024
72173d2
feat(setup): update-setup
ShreyasSharma28 Nov 4, 2024
f195b14
fix(cc-widgets): add-react-w2x-and-mobx
ShreyasSharma28 Nov 5, 2024
d8309fe
feat(cc-widgets): add-tests-for-widgets
ShreyasSharma28 Nov 5, 2024
5ce6996
feat(react-samples): add-widgets-samples-with-react
ShreyasSharma28 Nov 5, 2024
6505954
feat(cc-widgets): samples-app-for-widgets-as-web-component
ShreyasSharma28 Nov 5, 2024
e1ca859
fix(cc-widgets): review-comments
ShreyasSharma28 Nov 5, 2024
842e311
Merge remote-tracking branch 'upstream/feat/cc-widgets' into packages…
ShreyasSharma28 Nov 5, 2024
0aa1ad6
fix(cc-widgets): create-common-webpack-config
ShreyasSharma28 Nov 6, 2024
dd165c9
fix(cc-widgets): add-ts-doc-fix-babelrc
ShreyasSharma28 Nov 6, 2024
e3d4569
fix(cc-widgets): minor-fixes
ShreyasSharma28 Nov 6, 2024
e0646ad
fix(webpack): remove-react-react-dom-as-external
ShreyasSharma28 Nov 11, 2024
b6a0f69
feat(cc-widgets): review-comments
ShreyasSharma28 Nov 11, 2024
1cfd42a
feat(cc-widgets): add-home-page-for-samples
ShreyasSharma28 Nov 11, 2024
dd7a176
feat(station-login): Added code for UI and functional logic for stati…
Kesari3008 Nov 12, 2024
de0be73
feat(station-login): tested and refined changes
Kesari3008 Nov 15, 2024
cddf823
fix(station-login): latest merge
Kesari3008 Nov 18, 2024
091c3a9
feat(station-login): review comments
Kesari3008 Nov 18, 2024
692fed1
feat(station-login): review comments
Kesari3008 Nov 18, 2024
e1ed912
feat(station-login): review comments 2
Kesari3008 Nov 18, 2024
0771768
feat(station-login): tests updated
Kesari3008 Nov 19, 2024
6980358
feat(station-login): minor change
Kesari3008 Nov 19, 2024
2f38760
feat(station-login): styles fixes
Kesari3008 Nov 19, 2024
9339aea
feat(station-login): review comments
Kesari3008 Nov 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,17 @@
],
"packageManager": "[email protected]",
"devDependencies": {
"@testing-library/react-hooks": "^8.0.1",
"crypto-browserify": "^3.12.1",
"html-webpack-plugin": "^5.6.3",
"mini-css-extract-plugin": "^2.9.2",
"node-gyp": "^10.2.0",
"os-browserify": "^0.3.0",
"process": "^0.11.10",
"querystring-es3": "^0.2.1",
"stream-browserify": "^3.0.0",
"typescript": "^5.6.3",
"vm-browserify": "^1.1.2",
"webpack": "^5.96.1",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^5.1.0"
Expand Down
8 changes: 6 additions & 2 deletions packages/contact-center/station-login/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
"@webex/cc-store": "workspace:*",
"mobx-react": "9.1.1",
"react": "18.3.1",
"react-dom": "18.3.1",
"typescript": "5.6.3"
"react-dom": "18.3.1"
},
"devDependencies": {
"@babel/core": "7.25.2",
Expand All @@ -29,10 +28,15 @@
"@types/react-test-renderer": "18",
"babel-jest": "29.7.0",
"babel-loader": "9.2.1",
"css-loader": "^7.1.2",
"file-loader": "6.2.0",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"sass": "1.69.5",
"sass-loader": "^16.0.3",
sreenara marked this conversation as resolved.
Show resolved Hide resolved
"style-loader": "^4.0.0",
"ts-loader": "9.5.1",
"typescript": "5.6.3",
"webpack": "5.94.0",
"webpack-cli": "5.1.4",
"webpack-merge": "6.0.1"
Expand Down
39 changes: 36 additions & 3 deletions packages/contact-center/station-login/src/helper.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
export const useStationLogin = () => {
return {name: 'StationLogin'};
};
import {useState} from "react";
import {StationLoginSuccess, StationLogoutSuccess} from '@webex/plugin-cc';
import {UseStationLoginProps} from "./station-login/station-login.types";

export const useStationLogin = (props: UseStationLoginProps) => {
const webex = props.webex;
const loginReqParam= props.loginReqParam;
const [loginSuccess, setLoginSuccess] = useState<StationLoginSuccess>();
const [loginFailure, setLoginFailure] = useState<Error>();
const [logoutSuccess, setLogoutSuccess] = useState<StationLogoutSuccess>();

const login = () => {
webex.cc.stationLogin({teamId: loginReqParam.teamId, loginOption: loginReqParam.loginOption, dialNumber: loginReqParam.dialNumber})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we introduce type safety by utilising IcontactCenter?

.then((res: StationLoginSuccess) => {
console.log('Successful Agent login: ', res);
setLoginSuccess(res);

}).catch((error: Error) => {
console.error(error);
setLoginFailure(error);
});
};

const logout = () => {
webex.cc.stationLogout({logoutReason: 'User requested logout'})
.then((res: StationLogoutSuccess) => {
console.log('Successful Agent logout: ', res);
setLogoutSuccess(res);
}).catch((error: any) => {
console.error(error);
});
};

return {name: 'StationLogin', login, logout, loginSuccess, loginFailure, logoutSuccess};
}

Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ import StationLoginPresentational from './station-login.presentational';
import {useStationLogin} from '../helper';

const StationLogin: React.FunctionComponent = observer(() => {
const {loginState, setLoginState, ccSdk, isAvailable} = store;
const result = useStationLogin();
const {webex, teams, loginOptions, loginReqParam, setDeviceType, setDialNumber, setTeam} = store;
const result = useStationLogin({webex, loginReqParam});

const props = {
...result,
loginState,
setLoginState,
ccSdk,
isAvailable,
teams,
loginOptions,
setDeviceType,
setDialNumber,
setTeam
};
return <StationLoginPresentational {...props} />;
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,137 @@
import React from 'react';
import React, {useEffect} from 'react';
import {StationLoginPresentationalProps} from './station-login.types';

import {IStationLoginProps} from './station-login.types';
const StationLoginPresentational: React.FunctionComponent<StationLoginPresentationalProps> = (props) => {
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

useEffect(() => {
const teamsDropdown = document.getElementById('teamsDropdown') as HTMLSelectElement;
sreenara marked this conversation as resolved.
Show resolved Hide resolved
const agentLogin = document.querySelector('#LoginOption') as HTMLSelectElement;
const dialNumber = document.querySelector('#dialNumber') as HTMLInputElement;
if (teamsDropdown) {
teamsDropdown.innerHTML = '';
if (teams) {
teams.forEach((team) => {
const option = document.createElement('option');
option.value = team.id;
option.text = team.name;
teamsDropdown.add(option);
});
setTeam(teamsDropdown.value);
dialNumber.value = '';
dialNumber.disabled = true;
}
}
if (loginOptions.length > 0) {
loginOptions.forEach((options)=> {
const option = document.createElement('option');
option.text = options;
option.value = options;
agentLogin.add(option);
});
}
}, [teams, loginOptions]);

const selectLoginOption = (event: { target: { value: string; }; }) => {
const dialNumber = document.querySelector('#dialNumber') as HTMLInputElement;
const deviceType = event.target.value;
setDeviceType(deviceType);
if (deviceType === 'AGENT_DN' || deviceType === 'EXTENSION') {
dialNumber.disabled = false;
} else {
dialNumber.disabled = true;
}
};

function updateDN() {
const dialNumber = document.querySelector('#dialNumber') as HTMLInputElement;
setDialNumber(dialNumber.value);
}

const styles = {
box: {
backgroundColor: '#ffffff',
borderRadius: '8px',
boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',
padding: '20px',
maxWidth: '800px',
margin: '0 auto'
},

sectionBox: {
padding: '10px',
border: '1px solid #ddd',
borderRadius: '8px'
},

fieldset: {
border: '1px solid #ccc',
borderRadius: '5px',
padding: '10px',
marginBottom: '20px'
},

legendBox: {
fontWeight: 'bold',
color: '#0052bf'
},

btn: {
padding: '10px 20px',
backgroundColor: '#0052bf',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
transition: 'background-color 0.3s',
marginRight: '8px'
},

select: {
width: '100%',
padding: '8px',
marginTop: '8px',
marginBottom: '12px',
border: '1px solid #ccc',
borderRadius: '4px'
},

input: {
width: '97%',
padding: '8px',
marginTop: '8px',
marginBottom: '12px',
border: '1px solid #ccc',
borderRadius: '4px'
}
}

const StationLoginPresentational: React.FunctionComponent<IStationLoginProps> = (props) => {
return (
<>
<h1 data-testid="station-login-heading">{props.name}</h1>
<h4>Station Login State: {props.loginState}</h4>
<button onClick={() => props.setLoginState('Logged In')}>Click to change state</button>
</>
<><h1 data-testid="station-login-heading">{name}</h1>
<div style={styles.box}>
<section style={styles.sectionBox}>
<fieldset style={styles.fieldset}>
<legend style={styles.legendBox}>Agent</legend>
<div style={{ display: 'flex', flexDirection: 'column', flexGrow: 1 }}>
<div style={{ display: 'flex', gap: '1rem' }}>
<fieldset style={{border: '1px solid #ccc', borderRadius: '5px', padding: '10px', marginBottom: '20px', flex: 0.69 }}>
<legend style={styles.legendBox}>Select Team</legend>
<select id="teamsDropdown" style={styles.select}>Teams</select>
</fieldset>
<fieldset style={styles.fieldset}>
<legend style={styles.legendBox}>Agent Login</legend>
<select name="LoginOption" id="LoginOption" style={styles.select} onChange={selectLoginOption}>
<option value="" selected hidden>Choose Agent Login Option...</option>
</select>
<input style={styles.input} id="dialNumber" name="dialNumber" placeholder="Extension/Dial Number" type="text" onInput={updateDN} />
<button id="AgentLogin" style={styles.btn} onClick={login}>Login</button>
<button id="logoutAgent" style={styles.btn} onClick={logout}>Logout</button>
</fieldset>
</div>
</div>
</fieldset>
</section>
</div></>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import Webex from 'webex';
import {AgentLogin, StationLoginSuccess, StationLogoutSuccess, Team} from '@webex/plugin-cc';
/**
* Interface representing the properties for the Station Login component.
*/
Expand All @@ -8,22 +10,66 @@ export interface IStationLoginProps {
name: string;

/**
* The current login state of the station.
* Webex instance.
*/
loginState: any;
webex: Webex;

/**
* Function to set the login state of the station.
* Array of the team IDs that agent belongs to
*/
setLoginState: any;
teams: Team[];

/**
* Station login options available for the agent
*/
loginOptions: string[];

/**
* Request Param object to be sent to the SDK station login method
*/
loginReqParam: AgentLogin;

/**
* Handler to initiate the agent login
*/
login: () => void;

/**
* Handler for agent logout
*/
logout: () => void;

/**
* Response data received on agent login success
*/
loginSuccess?: StationLoginSuccess;

/**
* Error received on agent login failure
*/
loginFailure?: Error;

/**
* Response data received on agent login success
*/
logoutSuccess?: StationLogoutSuccess;

/**
* Handler to set device type
*/
setDeviceType: (deviceType: string) => void;

/**
* The Customer Care SDK instance.
* Handler to set the entered dial number
*/
ccSdk: any;
setDialNumber: (dn: string) => void;

/**
* Indicates whether the station is available.
* Handler to set the selected agent team
*/
isAvailable: any;
setTeam: (team: string) => void;
}

export type StationLoginPresentationalProps = Pick<IStationLoginProps, 'name' | 'teams' | 'loginOptions' | 'login' | 'logout' | 'loginSuccess' | 'loginFailure' | 'logoutSuccess' | 'setDeviceType' | 'setDialNumber' | 'setTeam'>;

export type UseStationLoginProps = Pick<IStationLoginProps, 'webex' | 'loginReqParam'>;
Empty file.
Loading