mirror of
https://github.com/Telecominfraproject/wlan-cloud-ui.git
synced 2025-11-02 03:37:59 +00:00
Compare commits
28 Commits
hotfix/tes
...
feature/TW
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a49a0301e | ||
|
|
afc222bb4a | ||
|
|
c595424269 | ||
|
|
69fbceefff | ||
|
|
f9c66adf00 | ||
|
|
56c0329bdb | ||
|
|
06cb3feac3 | ||
|
|
a159705cae | ||
|
|
02c20ffd6e | ||
|
|
dc8374300e | ||
|
|
c001ce21ba | ||
|
|
04bbc5fbed | ||
|
|
902de8bcb0 | ||
|
|
6c6635017a | ||
|
|
8891b5b3f9 | ||
|
|
8d2e5bb8a5 | ||
|
|
f29f31558a | ||
|
|
6e0cf15616 | ||
|
|
49d5771fca | ||
|
|
3794869adb | ||
|
|
3d105340af | ||
|
|
c8ee2138ad | ||
|
|
2e9dd99f3a | ||
|
|
0d58a8bb6a | ||
|
|
19c0bb4393 | ||
|
|
2a521ce036 | ||
|
|
85e1ee16ee | ||
|
|
195518a137 |
@@ -24,7 +24,11 @@ RUN npm run build
|
||||
|
||||
# production environment
|
||||
FROM nginx:stable-alpine
|
||||
RUN apk add --no-cache jq
|
||||
COPY --from=build /app/dist /usr/share/nginx/html
|
||||
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
COPY docker_entrypoint.sh generate_config_js.sh /
|
||||
RUN chmod +x docker_entrypoint.sh generate_config_js.sh
|
||||
|
||||
EXPOSE 80
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
ENTRYPOINT ["/docker_entrypoint.sh"]
|
||||
1
app/config.js
Normal file
1
app/config.js
Normal file
@@ -0,0 +1 @@
|
||||
window.REACT_APP_API = undefined;
|
||||
@@ -31,6 +31,7 @@ const Alarms = () => {
|
||||
const { customerId } = useContext(UserContext);
|
||||
const { loading, error, data, refetch, fetchMore } = useQuery(GET_ALL_ALARMS, {
|
||||
variables: { customerId },
|
||||
errorPolicy: 'all',
|
||||
});
|
||||
|
||||
const handleOnReload = () => {
|
||||
@@ -73,9 +74,10 @@ const Alarms = () => {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
if (error && !data?.getAllAlarms?.items) {
|
||||
return <Alert message="Error" description="Failed to load alarms." type="error" showIcon />;
|
||||
}
|
||||
|
||||
return (
|
||||
<AlarmsPage
|
||||
data={data.getAllAlarms.items}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useContext, useMemo, useState } from 'react';
|
||||
import React, { useContext, useEffect, useMemo, useState, useRef } from 'react';
|
||||
import { Alert } from 'antd';
|
||||
import moment from 'moment';
|
||||
import { useQuery } from '@apollo/react-hooks';
|
||||
@@ -36,104 +36,164 @@ const USER_FRIENDLY_RADIOS = {
|
||||
is5GHz: '5GHz',
|
||||
};
|
||||
|
||||
const lineChartConfig = [
|
||||
{ key: 'inservicesAPs', title: 'Inservice APs (24 hours)' },
|
||||
{ key: 'clientDevices', title: 'Client Devices (24 hours)' },
|
||||
{
|
||||
key: 'traffic',
|
||||
title: 'Traffic (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 [toTime] = useState(
|
||||
moment()
|
||||
.valueOf()
|
||||
.toString()
|
||||
);
|
||||
const [fromTime] = useState(
|
||||
moment()
|
||||
.subtract(24, 'hours')
|
||||
.valueOf()
|
||||
.toString()
|
||||
);
|
||||
|
||||
const {
|
||||
loading: metricsLoading,
|
||||
error: metricsError,
|
||||
data: metricsData,
|
||||
// refetch: metricsRefetch,
|
||||
} = useQuery(FILTER_SYSTEM_EVENTS, {
|
||||
variables: {
|
||||
customerId,
|
||||
fromTime,
|
||||
toTime,
|
||||
equipmentIds: [0],
|
||||
dataTypes: ['StatusChangedEvent'],
|
||||
limit: 1000,
|
||||
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 formatLineChartData = (list = []) => {
|
||||
const lineChartData = {
|
||||
inservicesAPs: {
|
||||
title: 'Inservice APs (24 hours)',
|
||||
data: { key: 'Inservice APs', value: [] },
|
||||
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
|
||||
},
|
||||
clientDevices: { title: 'Client Devices (24 hours)' },
|
||||
traffic: {
|
||||
title: 'Traffic (24 hours)',
|
||||
formatter: trafficLabelFormatter,
|
||||
tooltipFormatter: trafficTooltipFormatter,
|
||||
data: {
|
||||
trafficBytesDownstream: { key: 'Down Stream', value: [] },
|
||||
trafficBytesUpstream: { key: 'Up Stream', value: [] },
|
||||
},
|
||||
},
|
||||
};
|
||||
const clientDevicesData = {};
|
||||
}
|
||||
);
|
||||
|
||||
list.forEach(
|
||||
({
|
||||
eventTimestamp,
|
||||
details: {
|
||||
payload: {
|
||||
const formatLineChartData = (list = []) => {
|
||||
if (list.length) {
|
||||
setLineChartData(prev => {
|
||||
const inservicesAPs = [];
|
||||
const clientDevices2dot4GHz = [];
|
||||
const clientDevices5GHz = [];
|
||||
const trafficBytesDownstreamData = [];
|
||||
const trafficBytesUpstreamData = [];
|
||||
|
||||
list.forEach(
|
||||
({
|
||||
eventTimestamp,
|
||||
details: {
|
||||
equipmentInServiceCount,
|
||||
associatedClientsCountPerRadio: radios,
|
||||
trafficBytesDownstream,
|
||||
trafficBytesUpstream,
|
||||
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]);
|
||||
}
|
||||
);
|
||||
|
||||
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],
|
||||
},
|
||||
},
|
||||
},
|
||||
}) => {
|
||||
lineChartData.inservicesAPs.data.value.push([eventTimestamp, equipmentInServiceCount]);
|
||||
Object.keys(radios).forEach(key => {
|
||||
if (!clientDevicesData[key]) {
|
||||
clientDevicesData[key] = {
|
||||
key: USER_FRIENDLY_RADIOS[key] || key,
|
||||
value: [],
|
||||
};
|
||||
}
|
||||
clientDevicesData[key].value.push([eventTimestamp, radios[key]]);
|
||||
});
|
||||
|
||||
lineChartData.traffic.data.trafficBytesDownstream.value.push([
|
||||
eventTimestamp,
|
||||
trafficBytesDownstream,
|
||||
]);
|
||||
lineChartData.traffic.data.trafficBytesUpstream.value.push([
|
||||
eventTimestamp,
|
||||
trafficBytesUpstream,
|
||||
]);
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
...lineChartData,
|
||||
clientDevices: { ...lineChartData.clientDevices, data: { ...clientDevicesData } },
|
||||
};
|
||||
traffic: {
|
||||
trafficBytesDownstream: {
|
||||
...prev.traffic.trafficBytesDownstream,
|
||||
value: [...prev.traffic.trafficBytesDownstream.value, ...trafficBytesDownstreamData],
|
||||
},
|
||||
trafficBytesUpstream: {
|
||||
...prev.traffic.trafficBytesUpstream,
|
||||
value: [...prev.traffic.trafficBytesUpstream.value, ...trafficBytesUpstreamData],
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const lineChartsData = useMemo(
|
||||
() => formatLineChartData(metricsData?.filterSystemEvents?.items),
|
||||
[metricsData]
|
||||
);
|
||||
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 || {};
|
||||
@@ -205,7 +265,8 @@ const Dashboard = () => {
|
||||
<DashboardPage
|
||||
statsCardDetails={statsArr}
|
||||
pieChartDetails={pieChartsData}
|
||||
lineChartDetails={lineChartsData}
|
||||
lineChartData={lineChartData}
|
||||
lineChartConfig={lineChartConfig}
|
||||
lineChartLoading={metricsLoading}
|
||||
lineChartError={metricsError}
|
||||
/>
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import React, { useEffect, useContext } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import moment from 'moment';
|
||||
import { useLazyQuery } from '@apollo/react-hooks';
|
||||
import { Alert } from 'antd';
|
||||
import { floor, padStart } from 'lodash';
|
||||
import { NetworkTable, Loading } from '@tip-wlan/wlan-cloud-ui-library';
|
||||
|
||||
import UserContext from 'contexts/UserContext';
|
||||
import { FILTER_EQUIPMENT } from 'graphql/queries';
|
||||
|
||||
import styles from './index.module.scss';
|
||||
|
||||
const renderTableCell = tabCell => {
|
||||
@@ -22,6 +25,13 @@ const renderTableCell = tabCell => {
|
||||
return tabCell;
|
||||
};
|
||||
|
||||
const durationToString = duration =>
|
||||
`${floor(duration.asDays())}d ${floor(duration.hours())}h ${padStart(
|
||||
duration.minutes(),
|
||||
2,
|
||||
0
|
||||
)}m ${padStart(duration.seconds(), 2, 0)}s`;
|
||||
|
||||
const accessPointsTableColumns = [
|
||||
{
|
||||
title: 'NAME',
|
||||
@@ -61,7 +71,7 @@ const accessPointsTableColumns = [
|
||||
{
|
||||
title: 'UP TIME',
|
||||
dataIndex: ['status', 'osPerformance', 'details', 'uptimeInSeconds'],
|
||||
render: renderTableCell,
|
||||
render: upTimeInSeconds => durationToString(moment.duration(upTimeInSeconds, 'seconds')),
|
||||
},
|
||||
{
|
||||
title: 'PROFILE',
|
||||
@@ -74,7 +84,7 @@ const accessPointsTableColumns = [
|
||||
render: renderTableCell,
|
||||
},
|
||||
{
|
||||
title: 'CAPACITY',
|
||||
title: 'OCCUPANCY',
|
||||
dataIndex: ['status', 'radioUtilization', 'details', 'capacityDetails'],
|
||||
render: renderTableCell,
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@ import UserContext from 'contexts/UserContext';
|
||||
import { GET_CLIENT_SESSION, FILTER_SERVICE_METRICS } from 'graphql/queries';
|
||||
|
||||
const toTime = moment();
|
||||
const fromTime = moment().subtract(1, 'hour');
|
||||
const fromTime = moment().subtract(4, 'hours');
|
||||
|
||||
const ClientDeviceDetails = () => {
|
||||
const { id } = useParams();
|
||||
@@ -33,7 +33,7 @@ const ClientDeviceDetails = () => {
|
||||
toTime: toTime.valueOf().toString(),
|
||||
clientMacs: [id],
|
||||
dataTypes: ['Client'],
|
||||
limit: 100,
|
||||
limit: 1000,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -73,7 +73,7 @@ const ClientDeviceDetails = () => {
|
||||
metricsData={
|
||||
metricsData && metricsData.filterServiceMetrics && metricsData.filterServiceMetrics.items
|
||||
}
|
||||
historyDate={toTime}
|
||||
historyDate={{ toTime, fromTime }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -77,9 +77,15 @@ const ProfileDetails = () => {
|
||||
const { loading, error, data } = useQuery(GET_PROFILE, {
|
||||
variables: { id },
|
||||
});
|
||||
|
||||
const { data: ssidProfiles } = useQuery(GET_ALL_PROFILES, {
|
||||
variables: { customerId, type: 'ssid' },
|
||||
});
|
||||
|
||||
const { data: radiusProfiles } = useQuery(GET_ALL_PROFILES, {
|
||||
variables: { customerId, type: 'radius' },
|
||||
});
|
||||
|
||||
const [updateProfile] = useMutation(UPDATE_PROFILE);
|
||||
const [deleteProfile] = useMutation(DELETE_PROFILE);
|
||||
|
||||
@@ -170,6 +176,7 @@ const ProfileDetails = () => {
|
||||
ssidProfiles={
|
||||
(ssidProfiles && ssidProfiles.getAllProfiles && ssidProfiles.getAllProfiles.items) || []
|
||||
}
|
||||
radiusProfiles={radiusProfiles?.getAllProfiles?.items}
|
||||
fileUpload={handleFileUpload}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -181,6 +181,7 @@ export const FILTER_SERVICE_METRICS = gql`
|
||||
rssi
|
||||
rxBytes
|
||||
txBytes
|
||||
detailsJSON
|
||||
}
|
||||
context {
|
||||
lastPage
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
<!-- Allow installing the app to the homescreen -->
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<script type="text/javascript" src="/config.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -18,9 +18,7 @@ import { getItem, setItem, removeItem } from 'utils/localStorage';
|
||||
import history from 'utils/history';
|
||||
|
||||
const API_URI =
|
||||
process.env.NODE_ENV === 'development'
|
||||
? 'http://localhost:4000/'
|
||||
: 'https://wlan-graphql.zone3.lab.connectus.ai/';
|
||||
process.env.NODE_ENV === 'development' ? 'http://localhost:4000/' : window.REACT_APP_API;
|
||||
const MOUNT_NODE = document.getElementById('root');
|
||||
|
||||
const cache = new InMemoryCache();
|
||||
|
||||
3
docker_entrypoint.sh
Normal file
3
docker_entrypoint.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh -eu
|
||||
./generate_config_js.sh >/usr/share/nginx/html/config.js
|
||||
nginx -g "daemon off;"
|
||||
10
generate_config_js.sh
Normal file
10
generate_config_js.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh -eu
|
||||
if [ -z "${API:-}" ]; then
|
||||
API_URL_JSON=undefined
|
||||
else
|
||||
API_URL_JSON=$(jq -n --arg api "$API" '$api')
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
window.REACT_APP_API = $API_URL_JSON;
|
||||
EOF
|
||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wlan-cloud-ui",
|
||||
"version": "0.2.3",
|
||||
"version": "0.2.7",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -1874,9 +1874,9 @@
|
||||
}
|
||||
},
|
||||
"@tip-wlan/wlan-cloud-ui-library": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://tip.jfrog.io/artifactory/api/npm/tip-wlan-cloud-npm-repo/@tip-wlan/wlan-cloud-ui-library/-/@tip-wlan/wlan-cloud-ui-library-0.2.3.tgz",
|
||||
"integrity": "sha1-m/aF8DLiaeGF8UDtECAabipk2P0="
|
||||
"version": "0.2.7",
|
||||
"resolved": "https://tip.jfrog.io/artifactory/api/npm/tip-wlan-cloud-npm-repo/@tip-wlan/wlan-cloud-ui-library/-/@tip-wlan/wlan-cloud-ui-library-0.2.7.tgz",
|
||||
"integrity": "sha1-GGCapOJxcgD36ml6ZU2j1AlzXio="
|
||||
},
|
||||
"@types/anymatch": {
|
||||
"version": "1.3.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wlan-cloud-ui",
|
||||
"version": "0.2.3",
|
||||
"version": "0.2.7",
|
||||
"author": "ConnectUs",
|
||||
"description": "React Portal",
|
||||
"engines": {
|
||||
@@ -20,7 +20,7 @@
|
||||
"@ant-design/icons": "^4.2.1",
|
||||
"@apollo/react-hoc": "^3.1.4",
|
||||
"@apollo/react-hooks": "^3.1.3",
|
||||
"@tip-wlan/wlan-cloud-ui-library": "^0.2.3",
|
||||
"@tip-wlan/wlan-cloud-ui-library": "^0.2.7",
|
||||
"antd": "^4.3.1",
|
||||
"apollo-cache-inmemory": "^1.6.6",
|
||||
"apollo-client": "^2.6.10",
|
||||
|
||||
Reference in New Issue
Block a user