mirror of
https://github.com/Telecominfraproject/wlan-cloud-ui.git
synced 2025-11-01 03:07:53 +00:00
281 lines
8.1 KiB
JavaScript
281 lines
8.1 KiB
JavaScript
import React, { useContext, useEffect, useMemo, useState, useRef } from 'react';
|
|
import { Alert } from 'antd';
|
|
import moment from 'moment';
|
|
import { useQuery } from '@apollo/client';
|
|
import { Dashboard as DashboardPage, Loading } from '@tip-wlan/wlan-cloud-ui-library';
|
|
import UserContext from 'contexts/UserContext';
|
|
import { FILTER_SYSTEM_EVENTS, GET_ALL_STATUS } from 'graphql/queries';
|
|
|
|
function formatBytes(bytes, decimals = 2) {
|
|
if (bytes === 0) return '0 Bytes';
|
|
|
|
const k = 1024;
|
|
const dm = decimals < 0 ? 0 : decimals;
|
|
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
|
|
const i = Math.floor(Math.log(Math.abs(bytes)) / Math.log(k));
|
|
|
|
// eslint-disable-next-line no-restricted-properties
|
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i] || ''}`;
|
|
}
|
|
|
|
function trafficLabelFormatter() {
|
|
return formatBytes(this.value);
|
|
}
|
|
|
|
function trafficTooltipFormatter() {
|
|
return `<span style="color:${this.color}">●</span> ${this.series.name}: <b>${formatBytes(
|
|
this.y
|
|
)}</b><br/>`;
|
|
}
|
|
|
|
const USER_FRIENDLY_RADIOS = {
|
|
is2dot4GHz: '2.4GHz',
|
|
is5GHzL: '5GHz (L)',
|
|
is5GHzU: '5GHz (U)',
|
|
is5GHz: '5GHz',
|
|
};
|
|
|
|
const lineChartConfig = [
|
|
{ key: 'inservicesAPs', title: 'Inservice APs (24 hours)' },
|
|
{ key: 'clientDevices', title: 'Client Devices (24 hours)' },
|
|
{
|
|
key: 'traffic',
|
|
title: 'Usage Information (24 hours)',
|
|
options: { formatter: trafficLabelFormatter, tooltipFormatter: trafficTooltipFormatter },
|
|
},
|
|
];
|
|
|
|
const Dashboard = () => {
|
|
const initialGraphTime = useRef({
|
|
toTime: moment()
|
|
.valueOf()
|
|
.toString(),
|
|
fromTime: moment()
|
|
.subtract(24, 'hours')
|
|
.valueOf()
|
|
.toString(),
|
|
});
|
|
const { customerId } = useContext(UserContext);
|
|
const { loading, error, data } = useQuery(GET_ALL_STATUS, {
|
|
variables: { customerId, statusDataTypes: ['CUSTOMER_DASHBOARD'] },
|
|
});
|
|
|
|
const [lineChartData, setLineChartData] = useState({
|
|
inservicesAPs: {
|
|
key: 'Inservice APs',
|
|
value: [],
|
|
},
|
|
clientDevices: {
|
|
is2dot4GHz: {
|
|
key: USER_FRIENDLY_RADIOS.is2dot4GHz,
|
|
value: [],
|
|
},
|
|
is5GHz: {
|
|
key: USER_FRIENDLY_RADIOS.is5GHz,
|
|
value: [],
|
|
},
|
|
},
|
|
traffic: {
|
|
trafficBytesDownstream: {
|
|
key: 'Down Stream',
|
|
value: [],
|
|
},
|
|
trafficBytesUpstream: {
|
|
key: 'Up Stream',
|
|
value: [],
|
|
},
|
|
},
|
|
});
|
|
|
|
const [totalUpstreamTraffic, setTotalUpstreamTraffic] = useState(0);
|
|
const [totalDownstreamTraffic, setTotalDownstreamTraffic] = useState(0);
|
|
|
|
const { loading: metricsLoading, error: metricsError, data: metricsData, fetchMore } = useQuery(
|
|
FILTER_SYSTEM_EVENTS,
|
|
{
|
|
variables: {
|
|
customerId,
|
|
fromTime: initialGraphTime.current.fromTime,
|
|
toTime: initialGraphTime.current.toTime,
|
|
equipmentIds: [0],
|
|
dataTypes: ['StatusChangedEvent'],
|
|
limit: 3000, // TODO: make get all in GraphQL
|
|
},
|
|
}
|
|
);
|
|
|
|
const formatLineChartData = (list = []) => {
|
|
if (list.length) {
|
|
setLineChartData(prev => {
|
|
const inservicesAPs = [];
|
|
const clientDevices2dot4GHz = [];
|
|
const clientDevices5GHz = [];
|
|
const trafficBytesDownstreamData = [];
|
|
const trafficBytesUpstreamData = [];
|
|
|
|
list.forEach(
|
|
({
|
|
eventTimestamp,
|
|
details: {
|
|
payload: {
|
|
details: {
|
|
equipmentInServiceCount,
|
|
associatedClientsCountPerRadio: radios,
|
|
trafficBytesDownstream,
|
|
trafficBytesUpstream,
|
|
},
|
|
},
|
|
},
|
|
}) => {
|
|
inservicesAPs.push([eventTimestamp, equipmentInServiceCount]);
|
|
|
|
let total5GHz = 0;
|
|
total5GHz += (radios?.is5GHz || 0) + (radios?.is5GHzL || 0) + (radios?.is5GHzU || 0); // combine all 5GHz radios
|
|
|
|
clientDevices2dot4GHz.push([eventTimestamp, radios.is2dot4GHz || 0]);
|
|
clientDevices5GHz.push([eventTimestamp, total5GHz]);
|
|
|
|
trafficBytesDownstreamData.push([eventTimestamp, trafficBytesDownstream]);
|
|
trafficBytesUpstreamData.push([eventTimestamp, trafficBytesUpstream]);
|
|
|
|
setTotalUpstreamTraffic(previous => previous + trafficBytesUpstream);
|
|
setTotalDownstreamTraffic(previous => previous + trafficBytesDownstream);
|
|
}
|
|
);
|
|
|
|
return {
|
|
inservicesAPs: {
|
|
...prev.inservicesAPs,
|
|
value: [...prev.inservicesAPs.value, ...inservicesAPs],
|
|
},
|
|
clientDevices: {
|
|
is2dot4GHz: {
|
|
...prev.clientDevices.is2dot4GHz,
|
|
value: [...prev.clientDevices.is2dot4GHz.value, ...clientDevices2dot4GHz],
|
|
},
|
|
is5GHz: {
|
|
...prev.clientDevices.is5GHz,
|
|
value: [...prev.clientDevices.is5GHz.value, ...clientDevices5GHz],
|
|
},
|
|
},
|
|
traffic: {
|
|
trafficBytesDownstream: {
|
|
...prev.traffic.trafficBytesDownstream,
|
|
value: [...prev.traffic.trafficBytesDownstream.value, ...trafficBytesDownstreamData],
|
|
},
|
|
trafficBytesUpstream: {
|
|
...prev.traffic.trafficBytesUpstream,
|
|
value: [...prev.traffic.trafficBytesUpstream.value, ...trafficBytesUpstreamData],
|
|
},
|
|
},
|
|
};
|
|
});
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
const interval = setInterval(() => {
|
|
const toTime = moment()
|
|
.valueOf()
|
|
.toString();
|
|
const fromTime = moment()
|
|
.subtract(5, 'minutes')
|
|
.valueOf()
|
|
.toString();
|
|
fetchMore({
|
|
variables: {
|
|
fromTime,
|
|
toTime,
|
|
},
|
|
updateQuery: (_, { fetchMoreResult }) => {
|
|
formatLineChartData(fetchMoreResult?.filterSystemEvents?.items);
|
|
},
|
|
});
|
|
}, 300000);
|
|
|
|
return () => clearInterval(interval);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
formatLineChartData(metricsData?.filterSystemEvents?.items);
|
|
}, [metricsData]);
|
|
|
|
const statsArr = useMemo(() => {
|
|
const status = data?.getAllStatus?.items[0]?.detailsJSON || {};
|
|
|
|
const {
|
|
associatedClientsCountPerRadio,
|
|
totalProvisionedEquipment,
|
|
equipmentInServiceCount,
|
|
equipmentWithClientsCount,
|
|
} = status;
|
|
|
|
const clientRadios = {};
|
|
let totalAssociated = 0;
|
|
if (associatedClientsCountPerRadio) {
|
|
Object.keys(associatedClientsCountPerRadio).forEach(i => {
|
|
if (i.includes('5GHz')) {
|
|
if (!clientRadios['5GHz']) {
|
|
clientRadios['5GHz'] = 0;
|
|
}
|
|
clientRadios['5GHz'] += associatedClientsCountPerRadio[i];
|
|
} else {
|
|
const key = USER_FRIENDLY_RADIOS[i] || i;
|
|
clientRadios[key] = associatedClientsCountPerRadio[i];
|
|
}
|
|
totalAssociated += associatedClientsCountPerRadio[i];
|
|
});
|
|
}
|
|
|
|
return [
|
|
{
|
|
title: 'Access Point',
|
|
'Total Provisioned': totalProvisionedEquipment,
|
|
'In Service': equipmentInServiceCount,
|
|
'With Clients': equipmentWithClientsCount,
|
|
},
|
|
{
|
|
title: 'Client Devices',
|
|
'Total Associated': totalAssociated,
|
|
...clientRadios,
|
|
},
|
|
{
|
|
title: 'Usage Information',
|
|
'Total Traffic (US)': formatBytes(totalUpstreamTraffic),
|
|
'Total Traffic (DS)': formatBytes(totalDownstreamTraffic),
|
|
},
|
|
];
|
|
}, [data]);
|
|
|
|
const pieChartsData = useMemo(() => {
|
|
const { clientCountPerOui, equipmentCountPerOui } = data?.getAllStatus?.items[0]?.details || {};
|
|
|
|
return [
|
|
{ title: 'AP Vendors', ...equipmentCountPerOui },
|
|
{ title: 'Client Vendors', ...clientCountPerOui },
|
|
];
|
|
}, [data]);
|
|
|
|
if (loading) {
|
|
return <Loading />;
|
|
}
|
|
|
|
if (error) {
|
|
return <Alert message="Error" description="Failed to load Dashboard" type="error" showIcon />;
|
|
}
|
|
|
|
return (
|
|
<DashboardPage
|
|
statsCardDetails={statsArr}
|
|
pieChartDetails={pieChartsData}
|
|
lineChartData={lineChartData}
|
|
lineChartConfig={lineChartConfig}
|
|
lineChartLoading={metricsLoading}
|
|
lineChartError={metricsError}
|
|
/>
|
|
);
|
|
};
|
|
|
|
export default Dashboard;
|