mirror of
https://github.com/optim-enterprises-bv/OptimCloud-gw-ui.git
synced 2025-10-30 17:57:46 +00:00
335 lines
9.1 KiB
JavaScript
335 lines
9.1 KiB
JavaScript
import React, { useState, useEffect, useCallback } from 'react';
|
|
import PropTypes from 'prop-types';
|
|
import { CSpinner } from '@coreui/react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { v4 as createUuid } from 'uuid';
|
|
import axiosInstance from 'utils/axiosInstance';
|
|
import { useAuth, useDevice } from 'ucentral-libs';
|
|
import {
|
|
capitalizeFirstLetter,
|
|
datesSameDay,
|
|
dateToUnix,
|
|
prettyDate,
|
|
unixToTime,
|
|
} from 'utils/helper';
|
|
import DeviceStatisticsChart from './DeviceStatisticsChart';
|
|
|
|
const StatisticsChartList = ({ setOptions, section, setStart, setEnd, time }) => {
|
|
const { t } = useTranslation();
|
|
const [loading, setLoading] = useState(false);
|
|
const { currentToken, endpoints } = useAuth();
|
|
const { deviceSerialNumber } = useDevice();
|
|
const [statOptions, setStatOptions] = useState({
|
|
interfaceList: [],
|
|
memory: [],
|
|
settings: {},
|
|
});
|
|
|
|
const transformIntoDataset = (data) => {
|
|
let sortedData = data.sort((a, b) => {
|
|
if (a.recorded > b.recorded) return 1;
|
|
if (b.recorded > a.recorded) return -1;
|
|
return 0;
|
|
});
|
|
|
|
const dataLength = sortedData.length;
|
|
if (dataLength > 1000 && dataLength < 3000) {
|
|
sortedData = sortedData.filter((dat, index) => index % 4 === 0);
|
|
} else if (dataLength >= 3000 && dataLength < 5000) {
|
|
sortedData = sortedData.filter((dat, index) => index % 8 === 0);
|
|
} else if (dataLength >= 5000 && dataLength < 7000) {
|
|
sortedData = sortedData.filter((dat, index) => index % 12 === 0);
|
|
} else if (dataLength > 7000) {
|
|
sortedData = sortedData.filter((dat, index) => index % 20 === 0);
|
|
}
|
|
|
|
// Looping through data to build our memory graph data
|
|
const memoryUsed = [
|
|
{
|
|
titleName: t('statistics.memory'),
|
|
name: 'Used',
|
|
backgroundColor: 'rgb(228,102,81,0.9)',
|
|
data: [],
|
|
fill: true,
|
|
},
|
|
{
|
|
titleName: t('statistics.memory'),
|
|
name: 'Buffered',
|
|
backgroundColor: 'rgb(228,102,81,0.9)',
|
|
data: [],
|
|
fill: true,
|
|
},
|
|
{
|
|
titleName: t('statistics.memory'),
|
|
name: 'Cached',
|
|
backgroundColor: 'rgb(228,102,81,0.9)',
|
|
data: [],
|
|
fill: true,
|
|
},
|
|
];
|
|
|
|
for (const log of sortedData) {
|
|
memoryUsed[0].data.push(
|
|
Math.floor((log.data.unit.memory.total - log.data.unit.memory.free) / 1024 / 1024),
|
|
);
|
|
memoryUsed[1].data.push(Math.floor(log.data.unit.memory.buffered / 1024 / 1024));
|
|
memoryUsed[2].data.push(Math.floor(log.data.unit.memory.cached / 1024 / 1024));
|
|
}
|
|
|
|
// This dictionary will have a key that is the interface name and a value of it's index in the final array
|
|
const interfaceTypes = {};
|
|
const interfaceList = [];
|
|
const categories = [];
|
|
let i = 0;
|
|
const areSameDay = datesSameDay(
|
|
new Date(sortedData[0].recorded * 1000),
|
|
new Date(sortedData[sortedData.length - 1].recorded * 1000),
|
|
);
|
|
|
|
// Just building the array for all the interfaces
|
|
for (const log of sortedData) {
|
|
categories.push(areSameDay ? unixToTime(log.recorded) : prettyDate(log.recorded));
|
|
for (const logInterface of log.data.interfaces) {
|
|
if (interfaceTypes[logInterface.name] === undefined) {
|
|
interfaceTypes[logInterface.name] = i;
|
|
interfaceList.push([
|
|
{
|
|
titleName: logInterface.name,
|
|
name: 'Tx',
|
|
backgroundColor: 'rgb(228,102,81,0.9)',
|
|
data: [],
|
|
fill: false,
|
|
},
|
|
{
|
|
titleName: logInterface.name,
|
|
name: 'Rx',
|
|
backgroundColor: 'rgb(0,216,255,0.9)',
|
|
data: [],
|
|
fill: false,
|
|
},
|
|
]);
|
|
i += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Looping through all the data
|
|
for (const log of sortedData) {
|
|
// Looping through the interfaces of the log
|
|
for (const inter of log.data.interfaces) {
|
|
interfaceList[interfaceTypes[inter.name]][0].data.push(
|
|
inter.counters?.tx_bytes ? Math.floor(inter.counters.tx_bytes / 1024) : 0,
|
|
);
|
|
interfaceList[interfaceTypes[inter.name]][1].data.push(
|
|
inter.counters?.rx_bytes ? Math.floor(inter.counters.rx_bytes / 1024) : 0,
|
|
);
|
|
}
|
|
}
|
|
|
|
const interfaceOptions = {
|
|
chart: {
|
|
id: 'chart',
|
|
},
|
|
stroke: {
|
|
curve: 'smooth',
|
|
},
|
|
xaxis: {
|
|
title: {
|
|
text: 'Time',
|
|
style: {
|
|
fontSize: '15px',
|
|
},
|
|
},
|
|
categories,
|
|
tickAmount: areSameDay ? 15 : 10,
|
|
},
|
|
yaxis: {
|
|
labels: {
|
|
minWidth: 40,
|
|
},
|
|
title: {
|
|
text: t('statistics.data'),
|
|
style: {
|
|
fontSize: '15px',
|
|
},
|
|
},
|
|
},
|
|
legend: {
|
|
position: 'top',
|
|
horizontalAlign: 'right',
|
|
float: true,
|
|
},
|
|
};
|
|
|
|
const memoryOptions = {
|
|
chart: {
|
|
id: 'chart',
|
|
},
|
|
stroke: {
|
|
curve: 'smooth',
|
|
},
|
|
xaxis: {
|
|
tickAmount: areSameDay ? 15 : 10,
|
|
title: {
|
|
text: 'Time',
|
|
style: {
|
|
fontSize: '15px',
|
|
},
|
|
},
|
|
categories,
|
|
},
|
|
yaxis: {
|
|
tickAmount: 5,
|
|
title: {
|
|
text: t('statistics.data_mb'),
|
|
style: {
|
|
fontSize: '15px',
|
|
},
|
|
},
|
|
},
|
|
legend: {
|
|
position: 'top',
|
|
horizontalAlign: 'right',
|
|
float: true,
|
|
},
|
|
};
|
|
|
|
const newOptions = {
|
|
interfaceList,
|
|
memory: [memoryUsed],
|
|
interfaceOptions,
|
|
memoryOptions,
|
|
start: new Date(sortedData[0].recorded * 1000).toISOString(),
|
|
end: new Date(sortedData[sortedData.length - 1].recorded * 1000).toISOString(),
|
|
};
|
|
|
|
if (statOptions !== newOptions) {
|
|
const sectionOptions = newOptions.interfaceList.map((opt) => ({
|
|
value: opt[0].titleName,
|
|
label: opt[0].titleName,
|
|
}));
|
|
setOptions([...sectionOptions, { value: 'memory', label: t('statistics.memory') }]);
|
|
setStatOptions({ ...newOptions });
|
|
if (sortedData.length > 0) {
|
|
setStart(new Date(sortedData[0].recorded * 1000));
|
|
setEnd(new Date(sortedData[sortedData.length - 1].recorded * 1000));
|
|
}
|
|
}
|
|
};
|
|
|
|
const getInterface = useCallback(() => {
|
|
if (statOptions.interfaceList.length === 0) return <p>N/A</p>;
|
|
|
|
const interfaceToShow = statOptions.interfaceList.find(
|
|
(inter) => inter[0].titleName === section,
|
|
);
|
|
|
|
if (interfaceToShow) {
|
|
const options = {
|
|
data: interfaceToShow,
|
|
options: {
|
|
...statOptions.interfaceOptions,
|
|
title: {
|
|
text: capitalizeFirstLetter(interfaceToShow[0].titleName),
|
|
align: 'left',
|
|
style: {
|
|
fontSize: '25px',
|
|
},
|
|
},
|
|
},
|
|
};
|
|
return (
|
|
<div key={createUuid()}>
|
|
<DeviceStatisticsChart chart={options} />
|
|
</div>
|
|
);
|
|
}
|
|
return <p>N/A</p>;
|
|
}, [statOptions, section]);
|
|
|
|
const getStatistics = () => {
|
|
setLoading(true);
|
|
|
|
const options = {
|
|
headers: {
|
|
Accept: 'application/json',
|
|
Authorization: `Bearer ${currentToken}`,
|
|
},
|
|
params: {},
|
|
};
|
|
|
|
let extraParams = '';
|
|
if (time.start !== null && time.end !== null) {
|
|
const utcStart = new Date(time.start).toISOString();
|
|
const utcEnd = new Date(time.end).toISOString();
|
|
options.params.startDate = dateToUnix(utcStart);
|
|
options.params.endDate = dateToUnix(utcEnd);
|
|
options.params.limit = 10000;
|
|
} else {
|
|
extraParams = '?newest=true&limit=50';
|
|
}
|
|
|
|
axiosInstance
|
|
.get(
|
|
`${endpoints.owgw}/api/v1/device/${deviceSerialNumber}/statistics${extraParams}`,
|
|
options,
|
|
)
|
|
.then((response) => {
|
|
transformIntoDataset(response.data.data);
|
|
})
|
|
.catch(() => {})
|
|
.finally(() => setLoading(false));
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (deviceSerialNumber) {
|
|
getStatistics();
|
|
}
|
|
}, [deviceSerialNumber, time.refreshId]);
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="text-center">
|
|
<CSpinner size="xl" />
|
|
</div>
|
|
);
|
|
}
|
|
return (
|
|
<div>
|
|
{section !== 'memory' && !loading && getInterface()}
|
|
{section === 'memory' &&
|
|
!loading &&
|
|
statOptions.memory.map((data) => {
|
|
const options = {
|
|
data,
|
|
options: {
|
|
...statOptions.memoryOptions,
|
|
title: {
|
|
text: capitalizeFirstLetter(data[0].titleName),
|
|
align: 'left',
|
|
style: {
|
|
fontSize: '25px',
|
|
},
|
|
},
|
|
},
|
|
};
|
|
return (
|
|
<div key={createUuid()}>
|
|
<DeviceStatisticsChart chart={options} section={section} />
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
StatisticsChartList.propTypes = {
|
|
setOptions: PropTypes.func.isRequired,
|
|
section: PropTypes.string.isRequired,
|
|
time: PropTypes.instanceOf(Object).isRequired,
|
|
setStart: PropTypes.func.isRequired,
|
|
setEnd: PropTypes.func.isRequired,
|
|
};
|
|
|
|
export default React.memo(StatisticsChartList);
|