mirror of
https://github.com/optim-enterprises-bv/OptimCloud-gw-ui.git
synced 2025-11-02 03:07:46 +00:00
Created modal component for actions
This commit is contained in:
23
package-lock.json
generated
23
package-lock.json
generated
@@ -5285,6 +5285,11 @@
|
|||||||
"whatwg-url": "^8.0.0"
|
"whatwg-url": "^8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"date-arithmetic": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/date-arithmetic/-/date-arithmetic-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-QWxYLR5P/6GStZcdem+V1xoto6DMadYWpMXU82ES3/RfR3Wdwr3D0+be7mgOJ+Ov0G9D5Dmb9T17sNLQYj9XOg=="
|
||||||
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
||||||
@@ -13230,6 +13235,24 @@
|
|||||||
"prop-types": "^15.6.2"
|
"prop-types": "^15.6.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-widgets": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-widgets/-/react-widgets-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-ON4PnsmBXnGJkLDmrDxQGwVSKfoCnmzm2NdiVjUlo8LcGeyw1SPjmhN0fAUc5rAdOJNgEYLkie+gA7OkW1czQg==",
|
||||||
|
"requires": {
|
||||||
|
"@restart/hooks": "^0.3.26",
|
||||||
|
"@types/classnames": "^2.2.11",
|
||||||
|
"@types/react-transition-group": "^4.4.0",
|
||||||
|
"classnames": "^2.2.6",
|
||||||
|
"date-arithmetic": "^4.0.1",
|
||||||
|
"dom-helpers": "^5.2.0",
|
||||||
|
"prop-types-extra": "^1.1.1",
|
||||||
|
"react-transition-group": "^4.4.1",
|
||||||
|
"tiny-warning": "^1.0.3",
|
||||||
|
"uncontrollable": "^7.2.1",
|
||||||
|
"warning": "^4.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"reactstrap": {
|
"reactstrap": {
|
||||||
"version": "8.9.0",
|
"version": "8.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-8.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-8.9.0.tgz",
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "4.0.3",
|
"react-scripts": "4.0.3",
|
||||||
"react-select": "^4.3.0",
|
"react-select": "^4.3.0",
|
||||||
|
"react-widgets": "^5.1.1",
|
||||||
"reactstrap": "^8.9.0",
|
"reactstrap": "^8.9.0",
|
||||||
"sass": "^1.32.8",
|
"sass": "^1.32.8",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
|
|||||||
@@ -5,37 +5,22 @@ import {
|
|||||||
CCardHeader,
|
CCardHeader,
|
||||||
CCardBody,
|
CCardBody,
|
||||||
CRow,
|
CRow,
|
||||||
CCol,
|
CCol
|
||||||
CModal,
|
|
||||||
CModalHeader,
|
|
||||||
CModalTitle,
|
|
||||||
CModalBody,
|
|
||||||
CModalFooter,
|
|
||||||
CForm,
|
|
||||||
CInput,
|
|
||||||
CInvalidFeedback,
|
|
||||||
CSpinner,
|
|
||||||
CBadge
|
|
||||||
} from '@coreui/react'
|
} from '@coreui/react'
|
||||||
import { useSelector } from 'react-redux';
|
import ActionModalWidget from '../widgets/ActionModalWidget';
|
||||||
import axiosInstance from '../utils/axiosInstance';
|
|
||||||
import { getToken } from '../utils/authHelper';
|
|
||||||
|
|
||||||
const DeviceActions = () => {
|
const DeviceActions = () => {
|
||||||
const [showModal, setShowModal] = useState(false);
|
const [showRebootModal, setShowRebootModal] = useState(false);
|
||||||
|
const [showBlinkModal, setShowBlinkModal] = useState(false);
|
||||||
const [firmwareUri, setFirmwareUri] = useState('');
|
const [firmwareUri, setFirmwareUri] = useState('');
|
||||||
const [validField, setValidField] = useState(true);
|
const [validField, setValidField] = useState(true);
|
||||||
const [rebootIsLoading, setRebootLoading] = useState(false);
|
|
||||||
const [hadRebootSuccess, setRebootSuccess] = useState(false);
|
|
||||||
const [hadRebootFailure, setRebootFailure] = useState(false);
|
|
||||||
const [blinkIsLoading, setBlinkLoading] = useState(false);
|
|
||||||
const [hadBlinkSuccess, setBlinkSuccess] = useState(false);
|
|
||||||
const [hadBlinkFailure, setBlinkFailure] = useState(false);
|
|
||||||
|
|
||||||
let selectedDevice = useSelector(state => state.selectedDevice);
|
const toggleRebootModal = (e) => {
|
||||||
|
setShowRebootModal(!showRebootModal);
|
||||||
|
}
|
||||||
|
|
||||||
const toggleModal = (e) => {
|
const toggleBlinkModal = (e) => {
|
||||||
setShowModal(!showModal);
|
setShowBlinkModal(!showBlinkModal);
|
||||||
}
|
}
|
||||||
|
|
||||||
const formChange = (fieldValue) => {
|
const formChange = (fieldValue) => {
|
||||||
@@ -53,62 +38,6 @@ const DeviceActions = () => {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const reboot = () => {
|
|
||||||
setRebootSuccess(false);
|
|
||||||
setRebootFailure(false);
|
|
||||||
setRebootLoading(true);
|
|
||||||
const token = getToken();
|
|
||||||
|
|
||||||
const headers = {
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'Authorization': `Bearer ${token}`,
|
|
||||||
'serialNumber': selectedDevice.serialNumber
|
|
||||||
};
|
|
||||||
|
|
||||||
axiosInstance.post(`/device/${selectedDevice.serialNumber}/reboot`, {
|
|
||||||
serialNumber : selectedDevice.serialNumber
|
|
||||||
},{ headers: headers})
|
|
||||||
.then((response) => {
|
|
||||||
setRebootSuccess(true);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
setRebootFailure(true);
|
|
||||||
console.log(error);
|
|
||||||
console.log(error.response);
|
|
||||||
})
|
|
||||||
.finally (() => {
|
|
||||||
setRebootLoading(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const blink = () => {
|
|
||||||
setBlinkSuccess(false);
|
|
||||||
setBlinkFailure(false);
|
|
||||||
setBlinkLoading(true);
|
|
||||||
const token = getToken();
|
|
||||||
|
|
||||||
const headers = {
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'Authorization': `Bearer ${token}`,
|
|
||||||
'serialNumber': selectedDevice.serialNumber
|
|
||||||
};
|
|
||||||
|
|
||||||
axiosInstance.post(`/device/${selectedDevice.serialNumber}/leds`, {
|
|
||||||
serialNumber : selectedDevice.serialNumber
|
|
||||||
},{ headers: headers})
|
|
||||||
.then((response) => {
|
|
||||||
setBlinkSuccess(true);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
setBlinkFailure(true);
|
|
||||||
console.log(error);
|
|
||||||
console.log(error.response);
|
|
||||||
})
|
|
||||||
.finally (() => {
|
|
||||||
setBlinkLoading(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CCard>
|
<CCard>
|
||||||
<CCardHeader>
|
<CCardHeader>
|
||||||
@@ -117,37 +46,39 @@ const DeviceActions = () => {
|
|||||||
<CCardBody>
|
<CCardBody>
|
||||||
<CRow>
|
<CRow>
|
||||||
<CCol>
|
<CCol>
|
||||||
<CButton block disabled={ rebootIsLoading } color="primary" onClick={ reboot }>
|
<CButton block onClick = { toggleRebootModal } color="primary">Reboot</CButton>
|
||||||
{ rebootIsLoading ? 'Loading...' : 'Reboot'} {' '}
|
|
||||||
<CSpinner hidden={ !rebootIsLoading } component="span" size="sm"/>
|
|
||||||
<CBadge hidden = { (rebootIsLoading || !hadRebootSuccess) } color="success" shape="rounded-pill">
|
|
||||||
Success
|
|
||||||
</CBadge>
|
|
||||||
<CBadge hidden = { (rebootIsLoading || !hadRebootFailure) }color="danger" shape="rounded-pill">
|
|
||||||
Request Failed
|
|
||||||
</CBadge>
|
|
||||||
</CButton>
|
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol>
|
<CCol>
|
||||||
<CButton block disabled={ blinkIsLoading } color="primary" onClick={ blink }>
|
<CButton block onClick = { toggleBlinkModal } color="primary">Blink</CButton>
|
||||||
{ blinkIsLoading ? 'Loading...' : 'Blink'} {' '}
|
|
||||||
<CSpinner hidden={ !blinkIsLoading } component="span" size="sm"/>
|
|
||||||
<CBadge hidden = { (blinkIsLoading || !hadBlinkSuccess) } color="success" shape="rounded-pill">
|
|
||||||
Success
|
|
||||||
</CBadge>
|
|
||||||
<CBadge hidden = { (blinkIsLoading || !hadBlinkFailure) }color="danger" shape="rounded-pill">
|
|
||||||
Request Failed
|
|
||||||
</CBadge>
|
|
||||||
</CButton>
|
|
||||||
</CCol>
|
</CCol>
|
||||||
</CRow>
|
</CRow>
|
||||||
<CRow style={{marginTop :'10px'}}>
|
<CRow style={{marginTop :'10px'}}>
|
||||||
<CCol>
|
<CCol>
|
||||||
<CButton block onClick = { toggleModal } color="primary">Firmware Upgrade</CButton>
|
<CButton block color="primary">Firmware Upgrade</CButton>
|
||||||
|
</CCol>
|
||||||
|
<CCol>
|
||||||
</CCol>
|
</CCol>
|
||||||
</CRow>
|
</CRow>
|
||||||
</CCardBody>
|
</CCardBody>
|
||||||
<CModal
|
<ActionModalWidget
|
||||||
|
show={showRebootModal}
|
||||||
|
toggleModal={toggleRebootModal}
|
||||||
|
title='Reboot Device'
|
||||||
|
directions='When would you like to reboot this device?'
|
||||||
|
actionLabel='reboot'
|
||||||
|
action='reboot'
|
||||||
|
/>
|
||||||
|
<ActionModalWidget
|
||||||
|
show={showBlinkModal}
|
||||||
|
toggleModal={toggleBlinkModal}
|
||||||
|
title='Blink LEDs of Device'
|
||||||
|
directions='When would you like make the LEDs of this device blink?'
|
||||||
|
actionLabel='blink'
|
||||||
|
action='leds'
|
||||||
|
extraParameters= {{ duration : 10, pattern : 'on' }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/*<CModal
|
||||||
show={showModal}
|
show={showModal}
|
||||||
onClose={toggleModal}
|
onClose={toggleModal}
|
||||||
>
|
>
|
||||||
@@ -178,7 +109,7 @@ const DeviceActions = () => {
|
|||||||
Cancel
|
Cancel
|
||||||
</CButton>
|
</CButton>
|
||||||
</CModalFooter>
|
</CModalFooter>
|
||||||
</CModal>
|
</CModal>*/}
|
||||||
</CCard>
|
</CCard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,3 +18,14 @@ export const cleanBytesString = (bytes, decimals = 2) => {
|
|||||||
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(k)));
|
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(k)));
|
||||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const convertDateToUtc = (date) => {
|
||||||
|
const utcDate = new Date(date.getTime() + date.getTimezoneOffset() * 60000);
|
||||||
|
return utcDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const convertDateFromUtc = (utcDate) => {
|
||||||
|
const dateObj = new Date();
|
||||||
|
const date = new Date(utcDate.getTime() - dateObj.getTimezoneOffset() * 60000);
|
||||||
|
return date;
|
||||||
|
}
|
||||||
169
src/widgets/ActionModalWidget.js
Normal file
169
src/widgets/ActionModalWidget.js
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
import {
|
||||||
|
CButton,
|
||||||
|
CModal,
|
||||||
|
CModalHeader,
|
||||||
|
CModalTitle,
|
||||||
|
CModalBody,
|
||||||
|
CModalFooter,
|
||||||
|
CSpinner,
|
||||||
|
CBadge,
|
||||||
|
CCol,
|
||||||
|
CRow
|
||||||
|
} from '@coreui/react';
|
||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { convertDateToUtc, convertDateFromUtc } from '../utils/helper'
|
||||||
|
import DatePicker from "react-widgets/DatePicker";
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import "react-widgets/styles.css";
|
||||||
|
import { getToken } from '../utils/authHelper';
|
||||||
|
import axiosInstance from '../utils/axiosInstance';
|
||||||
|
|
||||||
|
const ActionModalWidget = ({ show, toggleModal, title, directions, placeholder, handleClick, actionLabel, action, extraParameters }) => {
|
||||||
|
const [hadSuccess, setHadSuccess] = useState(false);
|
||||||
|
const [hadFailure, setHadFailure] = useState(false);
|
||||||
|
const [waiting, setWaiting] = useState(false);
|
||||||
|
const [chosenDate, setChosenDate] = useState(null);
|
||||||
|
const [responseBody, setResponseBody] = useState('');
|
||||||
|
const selectedDevice = useSelector(state => state.selectedDevice);
|
||||||
|
|
||||||
|
const formValidation = () => {
|
||||||
|
return (chosenDate !== null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const setDateToNow = () => {
|
||||||
|
const now = (new Date()).toISOString();
|
||||||
|
console.log('now to utc: ' + convertDateToUtc(new Date()));
|
||||||
|
setChosenDate(now);
|
||||||
|
}
|
||||||
|
|
||||||
|
const setDateToLate = () => {
|
||||||
|
const date = convertDateToUtc(new Date());
|
||||||
|
if (date.getHours() >= 3){
|
||||||
|
date.setDate(date.getDate() + 1);
|
||||||
|
}
|
||||||
|
date.setHours(3);
|
||||||
|
date.setMinutes(0);
|
||||||
|
|
||||||
|
setChosenDate(convertDateFromUtc(date).toISOString());
|
||||||
|
}
|
||||||
|
|
||||||
|
const setDate = (date) => {
|
||||||
|
if(date){
|
||||||
|
setChosenDate(convertDateFromUtc(date).toISOString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setHadSuccess(false);
|
||||||
|
setHadFailure(false);
|
||||||
|
setWaiting(false);
|
||||||
|
setChosenDate(false);
|
||||||
|
setResponseBody('');
|
||||||
|
},[show]);
|
||||||
|
|
||||||
|
const doAction = () => {
|
||||||
|
setHadFailure(false);
|
||||||
|
setHadSuccess(false);
|
||||||
|
setWaiting(true);
|
||||||
|
|
||||||
|
const token = getToken();
|
||||||
|
|
||||||
|
const headers = {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Authorization': `Bearer ${token}`,
|
||||||
|
'serialNumber': selectedDevice.serialNumber
|
||||||
|
};
|
||||||
|
|
||||||
|
const necessaryParameters = {
|
||||||
|
serialNumber : selectedDevice.serialNumber,
|
||||||
|
when: chosenDate
|
||||||
|
}
|
||||||
|
|
||||||
|
const parameters = {...necessaryParameters, ...extraParameters };
|
||||||
|
|
||||||
|
axiosInstance.post(`/device/${selectedDevice.serialNumber}/${action}`, parameters,{ headers: headers})
|
||||||
|
.then((response) => {
|
||||||
|
setResponseBody(JSON.stringify(response.data, null, 4));
|
||||||
|
setHadSuccess(true);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
setHadFailure(true);
|
||||||
|
console.log(error);
|
||||||
|
console.log(error.response);
|
||||||
|
})
|
||||||
|
.finally (() => {
|
||||||
|
setWaiting(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CModal
|
||||||
|
show={show}
|
||||||
|
onClose={toggleModal}
|
||||||
|
>
|
||||||
|
<CModalHeader closeButton>
|
||||||
|
<CModalTitle>{ title }</CModalTitle>
|
||||||
|
</CModalHeader>
|
||||||
|
<CModalBody>
|
||||||
|
<h6>{ directions }</h6>
|
||||||
|
<CRow style={{marginTop: '20px'}}>
|
||||||
|
<CCol>
|
||||||
|
<CButton block color="primary" onClick={ () => setDateToNow() } >Now</CButton>
|
||||||
|
</CCol>
|
||||||
|
<CCol>
|
||||||
|
<CButton block color="primary" onClick={ () => setDateToLate() }>Later tonight</CButton>
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
<CRow style={{marginTop: '20px'}}>
|
||||||
|
<CCol md="4" style={{marginTop: '7px'}}>
|
||||||
|
<p>Custom (UTC):</p>
|
||||||
|
</CCol>
|
||||||
|
<CCol xs="12" md="8">
|
||||||
|
<DatePicker
|
||||||
|
selected = { Date.parse(chosenDate) }
|
||||||
|
includeTime
|
||||||
|
selectTime
|
||||||
|
placeholder = 'Select custom date in UTC'
|
||||||
|
disabled = {waiting}
|
||||||
|
onChange = {date => setDate(date)}
|
||||||
|
min = { convertDateToUtc(new Date()) }
|
||||||
|
/>
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
|
||||||
|
<div style={{marginTop : '25px'}}>
|
||||||
|
<p>Device will { actionLabel } at (UTC): <b>{ chosenDate }</b></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div hidden={(!hadSuccess && !hadFailure)}>
|
||||||
|
<div><pre>{responseBody}</pre></div>
|
||||||
|
</div>
|
||||||
|
</CModalBody>
|
||||||
|
<CModalFooter>
|
||||||
|
<CButton
|
||||||
|
disabled={waiting}
|
||||||
|
color="primary"
|
||||||
|
onClick={event => formValidation() ? doAction() : null}
|
||||||
|
>
|
||||||
|
{ waiting ? 'Loading...' : 'Schedule'} {' '}
|
||||||
|
<CSpinner hidden={ !waiting } component="span" size="sm"/>
|
||||||
|
<CBadge hidden = { (waiting || !hadSuccess) } color="success" shape="rounded-pill">
|
||||||
|
Success
|
||||||
|
</CBadge>
|
||||||
|
<CBadge hidden = { (waiting || !hadFailure) }color="danger" shape="rounded-pill">
|
||||||
|
Request Failed
|
||||||
|
</CBadge>
|
||||||
|
</CButton>
|
||||||
|
<CButton
|
||||||
|
color="secondary"
|
||||||
|
onClick={ toggleModal }
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</CButton>
|
||||||
|
</CModalFooter>
|
||||||
|
</CModal>
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ActionModalWidget;
|
||||||
Reference in New Issue
Block a user