Skip to content

Instantly share code, notes, and snippets.

@akkikumar72
Created November 20, 2019 15:04
Show Gist options
  • Save akkikumar72/d37ce0c6022bf262381d6995a00f69b5 to your computer and use it in GitHub Desktop.
Save akkikumar72/d37ce0c6022bf262381d6995a00f69b5 to your computer and use it in GitHub Desktop.
Using useReducer
import React, { useState, useReducer } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import Select from 'react-select';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faSpinner } from '@fortawesome/free-solid-svg-icons';
import { scanRepo } from '../../actions/scanActions';
import { Redirect } from 'react-router-dom';
import './scan.scss';
import Toggle from '../../common/toggle/toggle';
import { RenderError } from '../../common/notification/notification';
import { NOTIFICATION_ID } from '../../actions/scanActions';
import DropdownIndicator from '../../common/dropDownIndicator/dropDownIndicator';
const options = [{ value: 'all', label: 'All' }, { value: 'soapui', label: 'SoapUI' }]; //TODO: This should come from BE
const intialState = {
scanType: [0],
notify: true,
scanName: '',
repoUrl: '',
branch: '',
accessToken: '',
userName: '',
password: '',
redirectToScanList: false
};
const reducer = (state, action) => {
switch (action.type) {
case 'SETSCANNAME':
return { ...state, scanName: action.value };
case 'SETBRANCH':
return { ...state, branch: action.value };
case 'SETSCANTYPE':
return { ...state, scanType: action.value };
case 'SETNOTIFY':
return { ...state, notify: !state.notify };
case 'SETREPORTURL':
return { ...state, repoUrl: action.value };
default:
throw new Error();
}
};
const ScanForm = () => {
const dispatchForRedux = useDispatch();
const { scan } = useSelector((state) => ({ scan: state.scan }));
const { notifications } = useSelector((state) => ({ notifications: state.notifications }));
const [state, dispatch] = useReducer(reducer, intialState);
//TODO convert it to useReducer
const [accessToken, setAccessToken] = useState('');
const [userName, setUserName] = useState('');
const [password, setPassword] = useState('');
const [redirectToScanList, setRedirectToScanList] = useState(false);
const { scanType, scanName, branch, notify, repoUrl } = state;
if ((scan.scanInfo && scan.scanInfo.status === 'scanning') || redirectToScanList) {
return <Redirect to='/scan-list' />;
}
const handleScanTypeChange = (scanType) => {
dispatch({
type: 'SETSCANTYPE',
value: scanType
});
};
const toggleNotify = () => {
dispatch({ type: 'SETNOTIFY' });
};
const isFormValid = () => {
return scanType && scanName && repoUrl;
};
const renderSaveButtonLabel = () => {
if (scan.isSaving) {
return (
<>
<FontAwesomeIcon className='icon' icon={faSpinner} spin /> Saving
</>
);
} else {
return <>Save</>;
}
};
const renderSaveAndScanButtonLabel = () => {
if (scan.isScanAndSaving) {
return (
<>
<FontAwesomeIcon className='icon' icon={faSpinner} spin /> Scan & Saving
</>
);
} else {
return <>Scan & Save</>;
}
};
const handleSubmit = () => {
const formData = {
scanType, //TODO:might need to change when it is decided in the BE
name: scanName.trim(),
notify, //TODO:might need to change when it is decided in the BE
url: repoUrl.trim(),
branch: branch.trim(),
secret: accessToken.trim(),
username: userName.trim(),
password: password.trim()
};
dispatchForRedux(scanRepo(formData));
};
console.log(state);
return (
<div className='page-wrapper'>
<div className='scan'>
<div className='main-header'>
<div className='header'>Scan Configuration</div>
<button className='button button-small-ghost cancel' onClick={() => setRedirectToScanList(true)}>
Cancel
</button>
<button className='button button-small save' disabled={!isFormValid()} onClick={handleSubmit}>
{renderSaveButtonLabel()}
</button>
<button className='button button-small save-scan' disabled={!isFormValid()} onClick={handleSubmit}>
{renderSaveAndScanButtonLabel()}
</button>
</div>
<div className='form-info'>
<Toggle id={NOTIFICATION_ID}>
<RenderError message={scan.error} notificationId={NOTIFICATION_ID} />
</Toggle>
{(!scan.error || !notifications[NOTIFICATION_ID]) && (
<>Enter the required information to scan your repository and retrieve Test Assets.</>
)}
</div>
<div className='row'>
<div className='column'>
<div className='white-background'>
<div className='title'>Details</div>
<div>
<label htmlFor='scan-type' className='form-label required-field'>
Select Scan Type
</label>
<Select
className='select-container'
classNamePrefix='scan-type'
value={scanType}
onChange={handleScanTypeChange}
options={options}
isMulti={true}
placeholder=''
isSearchable={false}
components={{ DropdownIndicator }}
/>
</div>
<div className='form-field'>
<label htmlFor='scan-name' className='form-label required-field'>
Name Scan
</label>
<input
type='text'
className='form-control'
value={state.scanName}
onChange={(e) => dispatch({ type: 'SETSCANNAME', value: e.target.value })}
/>
</div>
<div className='form-field form-info'>
<div>Depending on repository size, scanning may take some time.</div>
<div className='notify'>
<div className='checkbox-wrapper'>
<input type='checkbox' id='notify' name='notify' checked={notify} onChange={toggleNotify} />
<label htmlFor='notify' />
</div>
<div className='notify-label'>
<label htmlFor='notify'>Send notification when scan is complete </label>
</div>
</div>
</div>
<div className='form-field'>
<label htmlFor='repo-url' className='form-label required-field'>
Repository URL
</label>
<input
type='text'
className='form-control'
value={repoUrl}
onChange={(e) => dispatch({ type: 'SETREPORTURL', value: e.target.value })}
/>
</div>
<div className='form-field'>
<label htmlFor='branch' className='form-label'>
Specify Branch
</label>
<input
type='text'
className='form-control'
value={branch}
onChange={(e) => dispatch({ type: 'SETBRANCH', value: e.target.value })}
/>
</div>
</div>
</div>
<div className='column'>
<div className='white-background'>
<div className='title'>Credentials</div>
<div className='form-info'>If required by your repository, enter the appropriate credentials.</div>
<div className='form-field'>
<label htmlFor='access-token' className='form-label'>
Personal Access Token
</label>
<input
type='password'
className='form-control'
value={accessToken}
onChange={(e) => setAccessToken(e.target.value)}
/>
</div>
<div className='form-field'>
<label htmlFor='username' className='form-label or'>
- Or -
</label>
</div>
<div className='form-field'>
<label htmlFor='username' className='form-label'>
Username
</label>
<input
type='text'
className='form-control'
value={userName}
onChange={(e) => setUserName(e.target.value)}
disabled={accessToken}
/>
</div>
<div className='form-field'>
<label htmlFor='password' className='form-label'>
Password
</label>
<input
type='password'
className='form-control'
value={password}
onChange={(e) => setPassword(e.target.value)}
disabled={accessToken}
/>
</div>
</div>
</div>
</div>
</div>
<div className='add-tags'>
<div className='row'>
<div className='column'>
<div className='white-background'>
<div className='title'>Add Tags</div>
<div className='form-info'>Apply tags to your assets to help identify and organize them.</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default ScanForm;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment