Added loading button to all places I could

This commit is contained in:
bourquecharles
2021-06-05 08:06:04 -04:00
parent 4cb0621ddb
commit 148ba2dbe9
6 changed files with 228 additions and 249 deletions

View File

@@ -2,8 +2,8 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { CButton, CSpinner } from '@coreui/react'; import { CButton, CSpinner } from '@coreui/react';
const LoadingButton = ({ isLoading, label, isLoadingLabel, action, color, variant}) => ( const LoadingButton = ({ isLoading, label, isLoadingLabel, action, color, variant, block, disabled}) => (
<CButton variant={variant} disabled={isLoading} color={color} onClick={() => action()} block> <CButton variant={variant} color={color} onClick={() => action()} block={block} disabled={isLoading || disabled}>
{isLoading ? isLoadingLabel : label} {isLoading ? isLoadingLabel : label}
<CSpinner hidden={!isLoading} component="span" size="sm" /> <CSpinner hidden={!isLoading} component="span" size="sm" />
</CButton> </CButton>
@@ -11,6 +11,8 @@ const LoadingButton = ({ isLoading, label, isLoadingLabel, action, color, varian
LoadingButton.propTypes = { LoadingButton.propTypes = {
isLoading: PropTypes.bool.isRequired, isLoading: PropTypes.bool.isRequired,
block: PropTypes.bool,
disabled: PropTypes.bool,
label: PropTypes.string.isRequired, label: PropTypes.string.isRequired,
isLoadingLabel: PropTypes.string.isRequired, isLoadingLabel: PropTypes.string.isRequired,
action: PropTypes.func.isRequired, action: PropTypes.func.isRequired,
@@ -20,7 +22,9 @@ LoadingButton.propTypes = {
LoadingButton.defaultProps = { LoadingButton.defaultProps = {
color: "primary", color: "primary",
variant: "" variant: "",
block: true,
disabled: false
} }
export default LoadingButton; export default LoadingButton;

View File

@@ -0,0 +1,26 @@
import React from 'react';
import PropTypes from 'prop-types';
import { CButton, CModalBody, CModalFooter } from '@coreui/react';
const SuccessfulActionModalBody = ({ toggleModal }) => (
<div>
<CModalBody>
<h6>Command submitted succesfuly</h6>
</CModalBody>
<CModalFooter>
<CButton
onClick={() => toggleModal()}
block
>
Dismiss
</CButton>
</CModalFooter>
</div>
);
SuccessfulActionModalBody.propTypes = {
toggleModal: PropTypes.func.isRequired
};
export default SuccessfulActionModalBody;

View File

@@ -19,6 +19,8 @@ import 'react-widgets/styles.css';
import { getToken } from '../../utils/authHelper'; import { getToken } from '../../utils/authHelper';
import axiosInstance from '../../utils/axiosInstance'; import axiosInstance from '../../utils/axiosInstance';
import eventBus from '../../utils/EventBus'; import eventBus from '../../utils/EventBus';
import LoadingButton from '../../components/LoadingButton';
import SuccessfulActionModalBody from '../../components/SuccessfulActionModalBody';
const ActionModal = ({ show, toggleModal, title, directions, action }) => { const ActionModal = ({ show, toggleModal, title, directions, action }) => {
const [hadSuccess, setHadSuccess] = useState(false); const [hadSuccess, setHadSuccess] = useState(false);
@@ -28,17 +30,8 @@ const ActionModal = ({ show, toggleModal, title, directions, action }) => {
const [chosenDate, setChosenDate] = useState(new Date().toString()); const [chosenDate, setChosenDate] = useState(new Date().toString());
const [doingNow, setDoingNow] = useState(false); const [doingNow, setDoingNow] = useState(false);
const [responseBody, setResponseBody] = useState(''); const [responseBody, setResponseBody] = useState('');
const [checkingIfSure, setCheckingIfSure] = useState(false);
const selectedDeviceId = useSelector((state) => state.selectedDeviceId); const selectedDeviceId = useSelector((state) => state.selectedDeviceId);
const formValidation = () => {
if (chosenDate === '') {
setValidDate(false);
return false;
}
return true;
};
const setDateToLate = () => { const setDateToLate = () => {
const date = convertDateToUtc(new Date()); const date = convertDateToUtc(new Date());
if (date.getHours() >= 3) { if (date.getHours() >= 3) {
@@ -56,23 +49,20 @@ const ActionModal = ({ show, toggleModal, title, directions, action }) => {
} }
}; };
const confirmingIfSure = () => {
setCheckingIfSure(true);
};
useEffect(() => { useEffect(() => {
setHadSuccess(false); if(show) {
setHadFailure(false); setHadSuccess(false);
setWaiting(false); setHadFailure(false);
setDoingNow(false); setWaiting(false);
setChosenDate(new Date().toString()); setDoingNow(false);
setResponseBody(''); setChosenDate(new Date().toString());
setValidDate(true); setResponseBody('');
setCheckingIfSure(false); setValidDate(true);
}
}, [show]); }, [show]);
const doAction = (isNow) => { const doAction = (isNow) => {
setDoingNow(isNow); if(isNow !== undefined) setDoingNow(isNow);
setHadFailure(false); setHadFailure(false);
setHadSuccess(false); setHadSuccess(false);
setWaiting(true); setWaiting(true);
@@ -103,7 +93,6 @@ const ActionModal = ({ show, toggleModal, title, directions, action }) => {
}) })
.finally(() => { .finally(() => {
setDoingNow(false); setDoingNow(false);
setCheckingIfSure(false);
setWaiting(false); setWaiting(false);
eventBus.dispatch('actionCompleted', { message: 'An action has been completed' }); eventBus.dispatch('actionCompleted', { message: 'An action has been completed' });
}); });
@@ -114,69 +103,65 @@ const ActionModal = ({ show, toggleModal, title, directions, action }) => {
<CModalHeader closeButton> <CModalHeader closeButton>
<CModalTitle>{title}</CModalTitle> <CModalTitle>{title}</CModalTitle>
</CModalHeader> </CModalHeader>
<CModalBody> {hadSuccess ?
<h6>{directions}</h6> <SuccessfulActionModalBody toggleModal={toggleModal} />
<CRow style={{ marginTop: '20px' }}> :
<CCol> <div>
<CButton onClick={() => doAction(true)} disabled={waiting} block color="primary"> <CModalBody>
{waiting && doingNow ? 'Loading...' : 'Do Now!'} <h6>{directions}</h6>
<CSpinner hidden={!waiting || !doingNow} component="span" size="sm" /> <CRow style={{ marginTop: '20px' }}>
</CButton> <CCol>
</CCol> <CButton onClick={() => doAction(true)} disabled={waiting} block color="primary">
<CCol> {waiting && doingNow ? 'Loading...' : 'Do Now!'}
<CButton disabled={waiting} block color="primary" onClick={() => setDateToLate()}> <CSpinner hidden={!waiting || !doingNow} component="span" size="sm" />
Later tonight </CButton>
</CButton> </CCol>
</CCol> <CCol>
</CRow> <CButton disabled={waiting} block color="primary" onClick={() => setDateToLate()}>
<CRow style={{ marginTop: '20px' }}> Later tonight
<CCol md="4" style={{ marginTop: '7px' }}> </CButton>
<p>Date:</p> </CCol>
</CCol> </CRow>
<CCol xs="12" md="8"> <CRow style={{ marginTop: '20px' }}>
<DatePicker <CCol md="4" style={{ marginTop: '7px' }}>
selected={new Date(chosenDate)} <p>Date:</p>
includeTime </CCol>
className={('form-control', { 'is-invalid': !validDate })} <CCol xs="12" md="8">
value={new Date(chosenDate)} <DatePicker
placeholder="Select custom date" selected={new Date(chosenDate)}
disabled={waiting} includeTime
onChange={(date) => setDate(date)} className={('form-control', { 'is-invalid': !validDate })}
min={convertDateToUtc(new Date())} value={new Date(chosenDate)}
/> placeholder="Select custom date"
</CCol> disabled={waiting}
</CRow> onChange={(date) => setDate(date)}
<CInvalidFeedback>You need a date...</CInvalidFeedback> min={convertDateToUtc(new Date())}
/>
</CCol>
</CRow>
<CInvalidFeedback>You need a date...</CInvalidFeedback>
<div hidden={!hadSuccess && !hadFailure}> <div hidden={!hadSuccess && !hadFailure}>
<div> <div>
<pre className="ignore">{responseBody}</pre> <pre className="ignore">{responseBody}</pre>
</div> </div>
</div> </div>
</CModalBody> </CModalBody>
<CModalFooter> <CModalFooter>
<div hidden={!checkingIfSure}>Are you sure?</div> <LoadingButton
<CButton label="Schedule"
hidden={checkingIfSure} isLoadingLabel="Loading..."
disabled={waiting} isLoading={waiting}
color="primary" action={doAction}
onClick={() => (formValidation() ? confirmingIfSure() : null)} variant="outline"
> block={false}
Schedule disabled={waiting}
</CButton> />
<CButton <CButton color="secondary" onClick={toggleModal}>
hidden={!checkingIfSure} Cancel
disabled={waiting} </CButton>
color="primary" </CModalFooter>
onClick={() => (formValidation() ? doAction(false) : null)} </div>}
>
{waiting && !doingNow ? 'Loading...' : 'Yes'} {' '}
<CSpinner hidden={!waiting || doingNow} component="span" size="sm" />
</CButton>
<CButton color="secondary" onClick={toggleModal}>
Cancel
</CButton>
</CModalFooter>
</CModal> </CModal>
); );
}; };

View File

@@ -22,6 +22,8 @@ import 'react-widgets/styles.css';
import { getToken } from '../../utils/authHelper'; import { getToken } from '../../utils/authHelper';
import axiosInstance from '../../utils/axiosInstance'; import axiosInstance from '../../utils/axiosInstance';
import eventBus from '../../utils/EventBus'; import eventBus from '../../utils/EventBus';
import SuccessfulActionModalBody from '../../components/SuccessfulActionModalBody';
import LoadingButton from '../../components/LoadingButton';
const BlinkModal = ({ show, toggleModal }) => { const BlinkModal = ({ show, toggleModal }) => {
const [hadSuccess, setHadSuccess] = useState(false); const [hadSuccess, setHadSuccess] = useState(false);
@@ -31,7 +33,6 @@ const BlinkModal = ({ show, toggleModal }) => {
const [chosenDate, setChosenDate] = useState(new Date().toString()); const [chosenDate, setChosenDate] = useState(new Date().toString());
const [chosenPattern, setPattern] = useState('on'); const [chosenPattern, setPattern] = useState('on');
const [responseBody, setResponseBody] = useState(''); const [responseBody, setResponseBody] = useState('');
const [checkingIfSure, setCheckingIfSure] = useState(false);
const selectedDeviceId = useSelector((state) => state.selectedDeviceId); const selectedDeviceId = useSelector((state) => state.selectedDeviceId);
const setDateToLate = () => { const setDateToLate = () => {
@@ -51,23 +52,20 @@ const BlinkModal = ({ show, toggleModal }) => {
} }
}; };
const confirmingIfSure = () => {
setCheckingIfSure(true);
};
useEffect(() => { useEffect(() => {
setHadSuccess(false); if(show){
setHadFailure(false); setWaiting(false);
setWaiting(false); setChosenDate(new Date().toString());
setChosenDate(new Date().toString()); setResponseBody('');
setResponseBody(''); setPattern('on');
setPattern('on'); setDoingNow(false);
setCheckingIfSure(false); setHadSuccess(false);
setDoingNow(false); setHadFailure(false);
}
}, [show]); }, [show]);
const doAction = (isNow) => { const doAction = (isNow) => {
setDoingNow(isNow); if(isNow !== undefined) setDoingNow(isNow);
setHadFailure(false); setHadFailure(false);
setHadSuccess(false); setHadSuccess(false);
setWaiting(true); setWaiting(true);
@@ -100,7 +98,6 @@ const BlinkModal = ({ show, toggleModal }) => {
}) })
.finally(() => { .finally(() => {
setDoingNow(false); setDoingNow(false);
setCheckingIfSure(false);
setWaiting(false); setWaiting(false);
eventBus.dispatch('actionCompleted', { message: 'An action has been completed' }); eventBus.dispatch('actionCompleted', { message: 'An action has been completed' });
}); });
@@ -111,106 +108,102 @@ const BlinkModal = ({ show, toggleModal }) => {
<CModalHeader closeButton> <CModalHeader closeButton>
<CModalTitle>LEDs of Device</CModalTitle> <CModalTitle>LEDs of Device</CModalTitle>
</CModalHeader> </CModalHeader>
<CModalBody> {hadSuccess ?
<h6>When would you like make the LEDs of this device blink?</h6> <SuccessfulActionModalBody toggleModal={toggleModal} />
<CRow style={{ marginTop: '20px' }}> :
<CCol> <div>
<CButton onClick={() => doAction(true)} disabled={waiting} block color="primary"> <CModalBody>
{waiting && doingNow ? 'Loading...' : 'Do Now!'} <h6>When would you like make the LEDs of this device blink?</h6>
<CSpinner hidden={!waiting || !doingNow} component="span" size="sm" /> <CRow style={{ marginTop: '20px' }}>
</CButton> <CCol>
</CCol> <CButton onClick={() => doAction(true)} disabled={waiting} block color="primary">
<CCol> {waiting && doingNow ? 'Loading...' : 'Do Now!'}
<CButton disabled={waiting} block color="primary" onClick={() => setDateToLate()}> <CSpinner hidden={!waiting || !doingNow} component="span" size="sm" />
Later tonight </CButton>
</CButton> </CCol>
</CCol> <CCol>
</CRow> <CButton disabled={waiting} block color="primary" onClick={() => setDateToLate()}>
<CRow style={{ marginTop: '20px' }}> Later tonight
<CCol md="4" style={{ marginTop: '7px' }}> </CButton>
<p>Date:</p> </CCol>
</CCol> </CRow>
<CCol xs="12" md="8"> <CRow style={{ marginTop: '20px' }}>
<DatePicker <CCol md="4" style={{ marginTop: '7px' }}>
selected={new Date(chosenDate)} <p>Date:</p>
includeTime </CCol>
value={new Date(chosenDate)} <CCol xs="12" md="8">
placeholder="Select custom date" <DatePicker
disabled={waiting} selected={new Date(chosenDate)}
onChange={(date) => setDate(date)} includeTime
min={convertDateToUtc(new Date())} value={new Date(chosenDate)}
/> placeholder="Select custom date"
</CCol> disabled={waiting}
</CRow> onChange={(date) => setDate(date)}
<CRow style={{ marginTop: '20px' }}> min={convertDateToUtc(new Date())}
<CCol md="7">Choose a pattern you would like to use:</CCol> />
<CCol> </CCol>
<CForm> </CRow>
<CFormGroup variant="checkbox" onClick={() => setPattern('on')}> <CRow style={{ marginTop: '20px' }}>
<CInputRadio <CCol md="7">Choose a pattern you would like to use:</CCol>
defaultChecked={chosenPattern === 'on'} <CCol>
id="radio1" <CForm>
name="radios" <CFormGroup variant="checkbox" onClick={() => setPattern('on')}>
value="option1" <CInputRadio
/> defaultChecked={chosenPattern === 'on'}
<CLabel variant="checkbox" htmlFor="radio1"> id="radio1"
On name="radios"
</CLabel> value="option1"
</CFormGroup> />
<CFormGroup variant="checkbox" onClick={() => setPattern('off')}> <CLabel variant="checkbox" htmlFor="radio1">
<CInputRadio On
defaultChecked={chosenPattern === 'off'} </CLabel>
id="radio2" </CFormGroup>
name="radios" <CFormGroup variant="checkbox" onClick={() => setPattern('off')}>
value="option2" <CInputRadio
/> defaultChecked={chosenPattern === 'off'}
<CLabel variant="checkbox" htmlFor="radio2"> id="radio2"
Off name="radios"
</CLabel> value="option2"
</CFormGroup> />
<CFormGroup variant="checkbox" onClick={() => setPattern('blink')}> <CLabel variant="checkbox" htmlFor="radio2">
<CInputRadio Off
defaultChecked={chosenPattern === 'blink'} </CLabel>
id="radio2" </CFormGroup>
name="radios" <CFormGroup variant="checkbox" onClick={() => setPattern('blink')}>
value="option2" <CInputRadio
/> defaultChecked={chosenPattern === 'blink'}
<CLabel variant="checkbox" htmlFor="radio2"> id="radio2"
Blink name="radios"
</CLabel> value="option2"
</CFormGroup> />
</CForm> <CLabel variant="checkbox" htmlFor="radio2">
</CCol> Blink
</CRow> </CLabel>
<div hidden={!hadSuccess && !hadFailure}> </CFormGroup>
<div> </CForm>
<pre className="ignore">{responseBody}</pre> </CCol>
</CRow>
<div hidden={!hadSuccess && !hadFailure}>
<div>
<pre className="ignore">{responseBody}</pre>
</div>
</div> </div>
</div> </CModalBody>
</CModalBody> <CModalFooter>
<CModalFooter> <LoadingButton
<div hidden={!checkingIfSure}>Are you sure?</div> label="Schedule"
<CButton isLoadingLabel="Loading..."
disabled={waiting} isLoading={waiting && !doingNow}
hidden={checkingIfSure} action={doAction}
color="primary" variant="outline"
onClick={() => confirmingIfSure()} block={false}
> disabled={waiting}
Schedule />
</CButton> <CButton color="secondary" onClick={toggleModal}>
<CButton Cancel
hidden={!checkingIfSure} </CButton>
disabled={waiting} </CModalFooter>
color="primary" </div>}
onClick={() => doAction(false)}
>
{waiting && !doingNow ? 'Loading...' : 'Yes'} {' '}
<CSpinner hidden={!waiting || doingNow} component="span" size="sm" />
</CButton>
<CButton color="secondary" onClick={toggleModal}>
Cancel
</CButton>
</CModalFooter>
</CModal> </CModal>
); );
}; };

View File

@@ -5,8 +5,6 @@ import {
CModalTitle, CModalTitle,
CModalBody, CModalBody,
CModalFooter, CModalFooter,
CSpinner,
CBadge,
CCol, CCol,
CRow, CRow,
CInvalidFeedback, CInvalidFeedback,
@@ -21,6 +19,7 @@ import 'react-widgets/styles.css';
import { getToken } from '../../utils/authHelper'; import { getToken } from '../../utils/authHelper';
import axiosInstance from '../../utils/axiosInstance'; import axiosInstance from '../../utils/axiosInstance';
import eventBus from '../../utils/EventBus'; import eventBus from '../../utils/EventBus';
import LoadingButton from '../../components/LoadingButton';
const TraceModal = ({ show, toggleModal }) => { const TraceModal = ({ show, toggleModal }) => {
const [hadSuccess, setHadSuccess] = useState(false); const [hadSuccess, setHadSuccess] = useState(false);
@@ -31,7 +30,6 @@ const TraceModal = ({ show, toggleModal }) => {
const [packets, setPackets] = useState(100); const [packets, setPackets] = useState(100);
const [chosenDate, setChosenDate] = useState(new Date().toString()); const [chosenDate, setChosenDate] = useState(new Date().toString());
const [responseBody, setResponseBody] = useState(''); const [responseBody, setResponseBody] = useState('');
const [checkingIfSure, setCheckingIfSure] = useState(false);
const selectedDeviceId = useSelector((state) => state.selectedDeviceId); const selectedDeviceId = useSelector((state) => state.selectedDeviceId);
const setDate = (date) => { const setDate = (date) => {
@@ -40,17 +38,12 @@ const TraceModal = ({ show, toggleModal }) => {
} }
}; };
const confirmingIfSure = () => {
setCheckingIfSure(true);
};
useEffect(() => { useEffect(() => {
setHadSuccess(false); setHadSuccess(false);
setHadFailure(false); setHadFailure(false);
setWaiting(false); setWaiting(false);
setChosenDate(new Date().toString()); setChosenDate(new Date().toString());
setResponseBody(''); setResponseBody('');
setCheckingIfSure(false);
setDuration(20); setDuration(20);
setPackets(100); setPackets(100);
}, [show]); }, [show]);
@@ -99,7 +92,6 @@ const TraceModal = ({ show, toggleModal }) => {
setHadFailure(true); setHadFailure(true);
}) })
.finally(() => { .finally(() => {
setCheckingIfSure(false);
setWaiting(false); setWaiting(false);
eventBus.dispatch('actionCompleted', { message: 'An action has been completed' }); eventBus.dispatch('actionCompleted', { message: 'An action has been completed' });
}); });
@@ -199,25 +191,15 @@ const TraceModal = ({ show, toggleModal }) => {
</div> </div>
</CModalBody> </CModalBody>
<CModalFooter> <CModalFooter>
<div hidden={!checkingIfSure}>Are you sure?</div> <LoadingButton
<CButton hidden={checkingIfSure} color="primary" onClick={() => confirmingIfSure()}> label="Schedule"
Schedule isLoadingLabel="Loading..."
</CButton> isLoading={waiting}
<CButton action={doAction}
hidden={!checkingIfSure} variant="outline"
block={false}
disabled={waiting} disabled={waiting}
color="primary" />
onClick={() => doAction()}
>
{waiting ? 'Loading...' : 'Yes'} {' '}
<CSpinner hidden={!waiting} component="span" size="sm" />
<CBadge hidden={waiting || !hadSuccess} color="success" shape="pill">
Success
</CBadge>
<CBadge hidden={waiting || !hadFailure} color="danger" shape="pill">
Request Failed
</CBadge>
</CButton>
<CButton color="secondary" onClick={toggleModal}> <CButton color="secondary" onClick={toggleModal}>
Cancel Cancel
</CButton> </CButton>

View File

@@ -5,7 +5,6 @@ import {
CModalTitle, CModalTitle,
CModalBody, CModalBody,
CModalFooter, CModalFooter,
CSpinner,
CRow, CRow,
CForm, CForm,
CSwitch, CSwitch,
@@ -18,6 +17,7 @@ import 'react-widgets/styles.css';
import { getToken } from '../../utils/authHelper'; import { getToken } from '../../utils/authHelper';
import axiosInstance from '../../utils/axiosInstance'; import axiosInstance from '../../utils/axiosInstance';
import eventBus from '../../utils/EventBus'; import eventBus from '../../utils/EventBus';
import LoadingButton from '../../components/LoadingButton';
const WifiScanModal = ({ show, toggleModal }) => { const WifiScanModal = ({ show, toggleModal }) => {
const [hadSuccess, setHadSuccess] = useState(false); const [hadSuccess, setHadSuccess] = useState(false);
@@ -25,23 +25,17 @@ const WifiScanModal = ({ show, toggleModal }) => {
const [waiting, setWaiting] = useState(false); const [waiting, setWaiting] = useState(false);
const [choseVerbose, setVerbose] = useState(true); const [choseVerbose, setVerbose] = useState(true);
const [channelList, setChannelList] = useState([]); const [channelList, setChannelList] = useState([]);
const [checkingIfSure, setCheckingIfSure] = useState(false);
const selectedDeviceId = useSelector((state) => state.selectedDeviceId); const selectedDeviceId = useSelector((state) => state.selectedDeviceId);
const toggleVerbose = () => { const toggleVerbose = () => {
setVerbose(!choseVerbose); setVerbose(!choseVerbose);
}; };
const confirmingIfSure = () => {
setCheckingIfSure(true);
};
useEffect(() => { useEffect(() => {
setHadSuccess(false); setHadSuccess(false);
setHadFailure(false); setHadFailure(false);
setWaiting(false); setWaiting(false);
setChannelList([]); setChannelList([]);
setCheckingIfSure(false);
setVerbose(true); setVerbose(true);
}, [show]); }, [show]);
@@ -108,7 +102,6 @@ const WifiScanModal = ({ show, toggleModal }) => {
setHadFailure(true); setHadFailure(true);
}) })
.finally(() => { .finally(() => {
setCheckingIfSure(false);
setWaiting(false); setWaiting(false);
eventBus.dispatch('actionCompleted', { message: 'An action has been completed' }); eventBus.dispatch('actionCompleted', { message: 'An action has been completed' });
}); });
@@ -138,19 +131,15 @@ const WifiScanModal = ({ show, toggleModal }) => {
</div> </div>
</CModalBody> </CModalBody>
<CModalFooter> <CModalFooter>
<div hidden={!checkingIfSure}>Are you sure?</div> <LoadingButton
<CButton hidden={checkingIfSure} color="primary" onClick={() => confirmingIfSure()}> label="Schedule"
{hadSuccess || hadFailure ? 'Re-Scan' : 'Scan'} isLoadingLabel="Loading..."
</CButton> isLoading={waiting}
<CButton action={doAction}
hidden={!checkingIfSure} variant="outline"
block={false}
disabled={waiting} disabled={waiting}
color="primary" />
onClick={() => doAction()}
>
{waiting ? 'Loading...' : 'Yes'} {' '}
<CSpinner hidden={!waiting} component="span" size="sm" />
</CButton>
<CButton color="secondary" onClick={toggleModal}> <CButton color="secondary" onClick={toggleModal}>
Cancel Cancel
</CButton> </CButton>