mirror of
https://github.com/optim-enterprises-bv/OptimCloud-gw-ui.git
synced 2025-11-01 02:37:45 +00:00
245 lines
7.4 KiB
JavaScript
245 lines
7.4 KiB
JavaScript
/* eslint-disable-rule prefer-destructuring */
|
|
import React, { useState, useEffect } from 'react';
|
|
import {
|
|
CWidgetDropdown,
|
|
CButton,
|
|
CDataTable,
|
|
CCard,
|
|
CRow,
|
|
CCol,
|
|
CProgress,
|
|
CPopover,
|
|
} from '@coreui/react';
|
|
import CIcon from '@coreui/icons-react';
|
|
import { cilSync, cilTrash } from '@coreui/icons';
|
|
import { useTranslation } from 'react-i18next';
|
|
import DatePicker from 'react-widgets/DatePicker';
|
|
import { dateToUnix } from 'utils/helper';
|
|
import axiosInstance from 'utils/axiosInstance';
|
|
import eventBus from 'utils/eventBus';
|
|
import { LoadingButton, useAuth, useDevice, FormattedDate } from 'ucentral-libs';
|
|
import DeleteLogModal from 'components/DeleteLogModal';
|
|
|
|
const DeviceHealth = () => {
|
|
const { t } = useTranslation();
|
|
const { currentToken, endpoints } = useAuth();
|
|
const { deviceSerialNumber } = useDevice();
|
|
const [loading, setLoading] = useState(false);
|
|
const [healthChecks, setHealthChecks] = useState([]);
|
|
const [start, setStart] = useState('');
|
|
const [end, setEnd] = useState('');
|
|
const [logLimit, setLogLimit] = useState(25);
|
|
const [loadingMore, setLoadingMore] = useState(false);
|
|
const [showLoadingMore, setShowLoadingMore] = useState(true);
|
|
const [sanityLevel, setSanityLevel] = useState(null);
|
|
const [barColor, setBarColor] = useState('gradient-dark');
|
|
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
|
|
|
const toggleDeleteModal = () => {
|
|
setShowDeleteModal(!showDeleteModal);
|
|
};
|
|
|
|
const modifyStart = (value) => {
|
|
setStart(value);
|
|
};
|
|
|
|
const modifyEnd = (value) => {
|
|
setEnd(value);
|
|
};
|
|
|
|
const showMoreLogs = () => {
|
|
setLogLimit(logLimit + 50);
|
|
};
|
|
|
|
const getDeviceHealth = () => {
|
|
if (loading) return;
|
|
setLoadingMore(true);
|
|
setLoading(true);
|
|
|
|
const options = {
|
|
headers: {
|
|
Accept: 'application/json',
|
|
Authorization: `Bearer ${currentToken}`,
|
|
},
|
|
params: {
|
|
limit: logLimit,
|
|
},
|
|
};
|
|
|
|
let extraParams = '?newest=true';
|
|
if (start !== '' && end !== '') {
|
|
const utcStart = new Date(start).toISOString();
|
|
const utcEnd = new Date(end).toISOString();
|
|
options.params.startDate = dateToUnix(utcStart);
|
|
options.params.endDate = dateToUnix(utcEnd);
|
|
extraParams = '';
|
|
}
|
|
|
|
axiosInstance
|
|
.get(
|
|
`${endpoints.owgw}/api/v1/device/${encodeURIComponent(
|
|
deviceSerialNumber,
|
|
)}/healthchecks${extraParams}`,
|
|
options,
|
|
)
|
|
.then((response) => {
|
|
setHealthChecks(response.data.values);
|
|
})
|
|
.catch(() => {})
|
|
.finally(() => {
|
|
setLoading(false);
|
|
setLoadingMore(false);
|
|
});
|
|
};
|
|
|
|
const columns = [
|
|
{ key: 'recorded', label: t('common.recorded'), _style: { width: '15%' } },
|
|
{ key: 'UUID', label: t('common.config_id'), _style: { width: '10%' } },
|
|
{ key: 'sanity', label: t('health.sanity'), _style: { width: '5%' } },
|
|
{ key: 'checkDetails', label: t('common.details'), _style: { width: '65%' } },
|
|
];
|
|
|
|
useEffect(() => {
|
|
if (deviceSerialNumber) {
|
|
setLogLimit(25);
|
|
setLoadingMore(false);
|
|
setShowLoadingMore(true);
|
|
setStart('');
|
|
setEnd('');
|
|
getDeviceHealth();
|
|
}
|
|
}, [deviceSerialNumber]);
|
|
|
|
useEffect(() => {
|
|
if (logLimit !== 25) {
|
|
getDeviceHealth();
|
|
}
|
|
}, [logLimit]);
|
|
|
|
useEffect(() => {
|
|
if (healthChecks.length === 0 || (healthChecks.length > 0 && healthChecks.length < logLimit)) {
|
|
setShowLoadingMore(false);
|
|
} else {
|
|
setShowLoadingMore(true);
|
|
}
|
|
|
|
if (healthChecks && healthChecks.length > 0) {
|
|
const sortedHealthchecks = healthChecks.sort((a, b) => (a.recorded > b.recorded ? 1 : -1));
|
|
const tempSanityLevel = sortedHealthchecks[healthChecks.length - 1].sanity;
|
|
setSanityLevel(tempSanityLevel);
|
|
if (tempSanityLevel === 100) {
|
|
setBarColor('gradient-success');
|
|
} else if (tempSanityLevel >= 90) {
|
|
setBarColor('gradient-warning');
|
|
} else {
|
|
setBarColor('gradient-danger');
|
|
}
|
|
} else {
|
|
setBarColor('gradient-dark');
|
|
}
|
|
}, [healthChecks]);
|
|
|
|
useEffect(() => {
|
|
if (deviceSerialNumber && start !== '' && end !== '') {
|
|
getDeviceHealth();
|
|
} else if (deviceSerialNumber && start === '' && end === '') {
|
|
getDeviceHealth();
|
|
}
|
|
}, [start, end, deviceSerialNumber]);
|
|
|
|
useEffect(() => {
|
|
eventBus.on('deletedHealth', () => getDeviceHealth());
|
|
|
|
return () => {
|
|
eventBus.remove('deletedHealth');
|
|
};
|
|
}, []);
|
|
|
|
return (
|
|
<CWidgetDropdown
|
|
className="m-0"
|
|
header={t('health.title')}
|
|
text={sanityLevel ? `${sanityLevel}%` : t('common.unknown')}
|
|
value={sanityLevel ?? 100}
|
|
color={barColor}
|
|
inverse="true"
|
|
footerSlot={
|
|
<div className="pb-1 px-3">
|
|
<CProgress className="mb-3" color="white" value={sanityLevel ?? 0} />
|
|
<CRow className="mb-3">
|
|
<CCol>
|
|
{t('common.from')}
|
|
:
|
|
<DatePicker includeTime onChange={(date) => modifyStart(date)} />
|
|
</CCol>
|
|
<CCol>
|
|
{t('common.to')}
|
|
:
|
|
<DatePicker includeTime onChange={(date) => modifyEnd(date)} />
|
|
</CCol>
|
|
</CRow>
|
|
<CCard className="p-0">
|
|
<div className="overflow-auto" style={{ height: '200px' }}>
|
|
<CDataTable
|
|
addTableClasses="ignore-overflow table-sm"
|
|
border
|
|
items={healthChecks ?? []}
|
|
fields={columns}
|
|
className="text-white"
|
|
loading={loading}
|
|
sorterValue={{ column: 'recorded', desc: 'true' }}
|
|
scopedSlots={{
|
|
UUID: (item) => <td className="align-middle">{item.UUID}</td>,
|
|
recorded: (item) => (
|
|
<td className="align-middle">
|
|
<FormattedDate date={item.recorded} />
|
|
</td>
|
|
),
|
|
sanity: (item) => <td className="align-middle">{`${item.sanity}%`}</td>,
|
|
checkDetails: (item) => (
|
|
<td>
|
|
<pre className="my-0">{JSON.stringify(item.values)}</pre>
|
|
</td>
|
|
),
|
|
}}
|
|
/>
|
|
{showLoadingMore && (
|
|
<div className="mb-3">
|
|
<LoadingButton
|
|
label={t('common.view_more')}
|
|
isLoadingLabel={t('common.loading_more_ellipsis')}
|
|
isLoading={loadingMore}
|
|
action={showMoreLogs}
|
|
variant="outline"
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</CCard>
|
|
<DeleteLogModal
|
|
serialNumber={deviceSerialNumber}
|
|
object="healthchecks"
|
|
show={showDeleteModal}
|
|
toggle={toggleDeleteModal}
|
|
/>
|
|
</div>
|
|
}
|
|
>
|
|
<div className="text-right float-right">
|
|
<CPopover content={t('common.delete')}>
|
|
<CButton onClick={toggleDeleteModal} size="sm">
|
|
<CIcon name="cil-trash" content={cilTrash} className="text-white" size="2xl" />
|
|
</CButton>
|
|
</CPopover>
|
|
<CPopover content={t('common.refresh')}>
|
|
<CButton onClick={getDeviceHealth} size="sm">
|
|
<CIcon name="cil-sync" content={cilSync} className="text-white" size="2xl" />
|
|
</CButton>
|
|
</CPopover>
|
|
</div>
|
|
</CWidgetDropdown>
|
|
);
|
|
};
|
|
|
|
export default DeviceHealth;
|