mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentral-ui-libs.git
synced 2025-11-02 03:37:56 +00:00
General UI fixes, Settings page, WifiAnalysisTable
This commit is contained in:
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ucentral-libs",
|
||||
"version": "0.8.19",
|
||||
"version": "0.8.22",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ucentral-libs",
|
||||
"version": "0.8.19",
|
||||
"version": "0.8.22",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.14.6",
|
||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ucentral-libs",
|
||||
"version": "0.8.19",
|
||||
"version": "0.8.22",
|
||||
"main": "dist/index.js",
|
||||
"source": "src/index.js",
|
||||
"engines": {
|
||||
|
||||
32
src/components/ApiStatusCard/index.js
Normal file
32
src/components/ApiStatusCard/index.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { CCard, CCardBody, CCardHeader, CRow, CCol } from '@coreui/react';
|
||||
|
||||
const ApiStatusCard = ({ t, info }) => (
|
||||
<CCard>
|
||||
<CCardHeader>{info.title}</CCardHeader>
|
||||
<CCardBody>
|
||||
<CRow>
|
||||
<CCol sm="4">
|
||||
<div block="true">{t('common.endpoint')}:</div>
|
||||
<div block="true">{t('common.start')}:</div>
|
||||
<div block="true">{t('status.uptime')}:</div>
|
||||
<div block="true">{t('footer.version')}:</div>
|
||||
</CCol>
|
||||
<CCol>
|
||||
<div block="true">{info.endpoint}</div>
|
||||
<div block="true">{info.start}</div>
|
||||
<div block="true">{info.uptime}</div>
|
||||
<div block="true">{info.version}</div>
|
||||
</CCol>
|
||||
</CRow>
|
||||
</CCardBody>
|
||||
</CCard>
|
||||
);
|
||||
|
||||
ApiStatusCard.propTypes = {
|
||||
t: PropTypes.func.isRequired,
|
||||
info: PropTypes.instanceOf(Object).isRequired,
|
||||
};
|
||||
|
||||
export default React.memo(ApiStatusCard);
|
||||
@@ -118,7 +118,7 @@ const EditMyProfile = ({
|
||||
</CLabel>
|
||||
<CCol sm="4">
|
||||
<CRow>
|
||||
<CCol sm="2" className="pt-2">
|
||||
<CCol sm="3" className="pt-2">
|
||||
{t('common.current')}
|
||||
<div className="pt-5">Preview</div>
|
||||
</CCol>
|
||||
@@ -128,7 +128,7 @@ const EditMyProfile = ({
|
||||
<Avatar src={newAvatar} fallback={user.email.value} />
|
||||
</div>
|
||||
</CCol>
|
||||
<CCol sm="4" className="pt-2">
|
||||
<CCol className="pt-2">
|
||||
<div className="mt-1 mb-4">
|
||||
<LoadingButton
|
||||
label={t('user.delete_avatar')}
|
||||
@@ -165,7 +165,7 @@ const EditMyProfile = ({
|
||||
</CFormGroup>
|
||||
<CRow>
|
||||
<CCol />
|
||||
<CCol xs={1} className="mt-2 text-right">
|
||||
<CCol xs={2} className="mt-2 text-right">
|
||||
<CLink
|
||||
className="c-subheader-nav-link"
|
||||
aria-current="page"
|
||||
|
||||
41
src/components/RadioAnalysisTable/index.js
Normal file
41
src/components/RadioAnalysisTable/index.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { CDataTable } from '@coreui/react';
|
||||
|
||||
const RadioAnalysisTable = ({ data, loading }) => {
|
||||
const columns = [
|
||||
{ key: 'radio', label: 'R', _style: { width: '5%' } },
|
||||
{ key: 'channel', label: 'Ch', _style: { width: '5%' } },
|
||||
{ key: 'channelWidth', label: 'C Width', _style: { width: '7%' }, sorter: false },
|
||||
{ key: 'noise', label: 'Noise', _style: { width: '4%' }, sorter: false },
|
||||
{ key: 'txPower', label: 'Tx Power', _style: { width: '9%' }, sorter: false },
|
||||
{ key: 'activeMs', label: 'Active MS', _style: { width: '23%' }, sorter: false },
|
||||
{ key: 'busyMs', label: 'Busy MS', _style: { width: '23%' }, sorter: false },
|
||||
{ key: 'receiveMs', label: 'Receive MS', _style: { width: '23%' }, sorter: false },
|
||||
];
|
||||
|
||||
const centerIfEmpty = (value) => (
|
||||
<td className={!value || value === '' || value === '-' ? 'text-center' : ''}>{value}</td>
|
||||
);
|
||||
|
||||
return (
|
||||
<CDataTable
|
||||
fields={columns}
|
||||
items={data}
|
||||
hover
|
||||
border
|
||||
loading={loading}
|
||||
sorter
|
||||
sorterValue={{ column: 'radio', asc: true }}
|
||||
scopedSlots={{
|
||||
noise: (item) => centerIfEmpty(item.noise),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
RadioAnalysisTable.propTypes = {
|
||||
data: PropTypes.instanceOf(Object).isRequired,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
};
|
||||
export default RadioAnalysisTable;
|
||||
229
src/components/RadioAnalysisTable/radioindex.json
Normal file
229
src/components/RadioAnalysisTable/radioindex.json
Normal file
@@ -0,0 +1,229 @@
|
||||
{
|
||||
"UUID": 1626408268,
|
||||
"data": {
|
||||
"interfaces": [
|
||||
{
|
||||
"counters": {
|
||||
"collisions": 0,
|
||||
"multicast": 2234,
|
||||
"rx_bytes": 258222,
|
||||
"rx_dropped": 0,
|
||||
"rx_errors": 0,
|
||||
"rx_packets": 2574,
|
||||
"tx_bytes": 1254,
|
||||
"tx_dropped": 0,
|
||||
"tx_errors": 0,
|
||||
"tx_packets": 1
|
||||
},
|
||||
"location": null,
|
||||
"name": "up_none",
|
||||
"uptime": 387758
|
||||
},
|
||||
{
|
||||
"clients": [
|
||||
{
|
||||
"ipv6_addresses": [
|
||||
"fe80:0:0:0:1e98:c1ff:fe4f:1add"
|
||||
],
|
||||
"mac": "1c:98:c1:4f:1a:dd",
|
||||
"ports": [
|
||||
"eth1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ipv6_addresses": [
|
||||
"fe80:0:0:0:1050:3814:a6a0:fcd8"
|
||||
],
|
||||
"mac": "46:e6:b2:59:9d:6b",
|
||||
"ports": [
|
||||
"eth1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ipv6_addresses": [
|
||||
"fe80:0:0:0:1849:6d1f:1bde:c932"
|
||||
],
|
||||
"mac": "6e:45:97:3d:ad:fc",
|
||||
"ports": [
|
||||
"eth1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ipv6_addresses": [
|
||||
"fe80:0:0:0:1879:8133:b53a:e191"
|
||||
],
|
||||
"mac": "78:4f:43:5f:37:e0",
|
||||
"ports": [
|
||||
"eth1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ipv4_addresses": [
|
||||
"10.0.0.1"
|
||||
],
|
||||
"ipv6_addresses": [
|
||||
"fe80:0:0:0:9a9d:5dff:fea3:f4bd",
|
||||
"fe80:0:0:0:226:86ff:fee8:5c16"
|
||||
],
|
||||
"mac": "98:9d:5d:a3:f4:bd",
|
||||
"ports": [
|
||||
"eth1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ipv6_addresses": [
|
||||
"fe80:0:0:0:a677:33ff:febb:acb2"
|
||||
],
|
||||
"mac": "a4:77:33:bb:ac:b2",
|
||||
"ports": [
|
||||
"eth1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ipv6_addresses": [
|
||||
"fe80:0:0:0:141e:c84:e2ac:7416"
|
||||
],
|
||||
"mac": "ca:1c:85:a9:ed:24",
|
||||
"ports": [
|
||||
"eth1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ipv6_addresses": [
|
||||
"fe80:0:0:0:f882:1877:a036:b28d"
|
||||
],
|
||||
"mac": "dc:41:a9:f0:1d:0b",
|
||||
"ports": [
|
||||
"eth1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ipv6_addresses": [
|
||||
"fe80:0:0:0:105b:f1b8:883b:11d8"
|
||||
],
|
||||
"mac": "f2:6c:fa:68:95:05",
|
||||
"ports": [
|
||||
"eth1"
|
||||
]
|
||||
}
|
||||
],
|
||||
"counters": {
|
||||
"collisions": 0,
|
||||
"multicast": 2234,
|
||||
"rx_bytes": 258222,
|
||||
"rx_dropped": 0,
|
||||
"rx_errors": 0,
|
||||
"rx_packets": 2574,
|
||||
"tx_bytes": 1254,
|
||||
"tx_dropped": 0,
|
||||
"tx_errors": 0,
|
||||
"tx_packets": 1
|
||||
},
|
||||
"dns_servers": [
|
||||
"24.201.245.77",
|
||||
"24.200.0.1",
|
||||
"24.53.0.2"
|
||||
],
|
||||
"ipv4": {
|
||||
"addresses": [
|
||||
"10.0.0.99/24"
|
||||
],
|
||||
"leasetime": 172800
|
||||
},
|
||||
"location": "/interfaces/0",
|
||||
"name": "up0v0",
|
||||
"ssids": [
|
||||
{
|
||||
"mode": "ap",
|
||||
"radio": {
|
||||
"$ref": "#/radios/0"
|
||||
},
|
||||
"ssid": "OpenWifi"
|
||||
},
|
||||
{
|
||||
"mode": "ap",
|
||||
"radio": {
|
||||
"$ref": "#/radios/2"
|
||||
},
|
||||
"ssid": "OpenWifi"
|
||||
}
|
||||
],
|
||||
"uptime": 387753
|
||||
},
|
||||
{
|
||||
"counters": {
|
||||
"collisions": 0,
|
||||
"multicast": 0,
|
||||
"rx_bytes": 0,
|
||||
"rx_dropped": 0,
|
||||
"rx_errors": 0,
|
||||
"rx_packets": 0,
|
||||
"tx_bytes": 1058,
|
||||
"tx_dropped": 0,
|
||||
"tx_errors": 0,
|
||||
"tx_packets": 5
|
||||
},
|
||||
"ipv4": {
|
||||
"addresses": [
|
||||
"192.168.1.1/24"
|
||||
]
|
||||
},
|
||||
"location": "/interfaces/1",
|
||||
"name": "down1v0",
|
||||
"ssids": [
|
||||
{
|
||||
"mode": "ap",
|
||||
"radio": {
|
||||
"$ref": "#/radios/0"
|
||||
},
|
||||
"ssid": "OpenWifi"
|
||||
},
|
||||
{
|
||||
"mode": "ap",
|
||||
"radio": {
|
||||
"$ref": "#/radios/2"
|
||||
},
|
||||
"ssid": "OpenWifi"
|
||||
}
|
||||
],
|
||||
"uptime": 387761
|
||||
}
|
||||
],
|
||||
"radios": [
|
||||
{
|
||||
"active_ms": 387751448,
|
||||
"busy_ms": 2637879,
|
||||
"channel": 100,
|
||||
"channel_width": "80",
|
||||
"noise": 4294967193,
|
||||
"receive_ms": 485,
|
||||
"transmit_ms": 2634150,
|
||||
"tx_power": 24
|
||||
},
|
||||
{
|
||||
"active_ms": 387751962,
|
||||
"busy_ms": 4379945,
|
||||
"channel": 36,
|
||||
"channel_width": "80",
|
||||
"noise": 4294967192,
|
||||
"receive_ms": 1119,
|
||||
"transmit_ms": 2642485,
|
||||
"tx_power": 23
|
||||
}
|
||||
],
|
||||
"unit": {
|
||||
"load": [
|
||||
7680,
|
||||
3136,
|
||||
576
|
||||
],
|
||||
"localtime": 1627043604,
|
||||
"memory": {
|
||||
"free": 100302848,
|
||||
"total": 254529536
|
||||
},
|
||||
"uptime": 387785
|
||||
}
|
||||
},
|
||||
"recorded": 1627043604
|
||||
}
|
||||
@@ -77,32 +77,36 @@ const UserListTable = ({
|
||||
<CCardHeader>
|
||||
<CRow>
|
||||
<CCol />
|
||||
<CCol xs={1}>
|
||||
<div className="text-right">
|
||||
<CSelect
|
||||
custom
|
||||
defaultValue={usersPerPage}
|
||||
onChange={(e) => setUsersPerPage(e.target.value)}
|
||||
disabled={loading}
|
||||
>
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
</CSelect>
|
||||
</div>
|
||||
</CCol>
|
||||
<CCol xs={1}>
|
||||
<div className="text-right">
|
||||
<CButton
|
||||
color="primary"
|
||||
variant="outline"
|
||||
shape="square"
|
||||
onClick={toggleCreate}
|
||||
block
|
||||
>
|
||||
{t('user.create')}
|
||||
</CButton>
|
||||
</div>
|
||||
<CCol xs={3}>
|
||||
<CRow>
|
||||
<CCol xs={6}>
|
||||
<div className="text-right">
|
||||
<CSelect
|
||||
custom
|
||||
defaultValue={usersPerPage}
|
||||
onChange={(e) => setUsersPerPage(e.target.value)}
|
||||
disabled={loading}
|
||||
>
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
</CSelect>
|
||||
</div>
|
||||
</CCol>
|
||||
<CCol xs={6}>
|
||||
<div className="text-right">
|
||||
<CButton
|
||||
color="primary"
|
||||
variant="outline"
|
||||
shape="square"
|
||||
onClick={toggleCreate}
|
||||
block
|
||||
>
|
||||
{t('user.create')}
|
||||
</CButton>
|
||||
</div>
|
||||
</CCol>
|
||||
</CRow>
|
||||
</CCol>
|
||||
</CRow>
|
||||
</CCardHeader>
|
||||
|
||||
@@ -1,51 +1,73 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { CCard, CCardBody, CCardHeader, CCol, CDataTable, CRow } from '@coreui/react';
|
||||
import { CButton, CDataTable, CPopover } from '@coreui/react';
|
||||
|
||||
const WifiAnalysisTable = ({ t, data, loading, range, updateSelectedStats }) => {
|
||||
const WifiAnalysisTable = ({ t, data, loading }) => {
|
||||
const columns = [
|
||||
{ key: 'radio', label: 'R', _style: { width: '2%' } },
|
||||
{ key: 'channel', label: 'Ch', _style: { width: '3%' } },
|
||||
{ key: 'channelWidth', label: 'ChW', _style: { width: '2%' } },
|
||||
{ key: 'mode', label: t('wifi_analysis.mode'), _style: { width: '5%' } },
|
||||
{ key: 'txPower', label: 'TX Power', _style: { width: '3%' } },
|
||||
{ key: 'ssid', label: 'SSID', _style: { width: '10%' } },
|
||||
{ key: 'rssi', label: 'RSSI', _style: { width: '5%' } },
|
||||
{ key: 'rxRate', label: 'RxBitrate', _style: { width: '7%' } },
|
||||
{ key: 'rxBytes', label: 'RxBytes', _style: { width: '7%' } },
|
||||
{ key: 'rxMcs', label: 'Rx MCS', _style: { width: '4%' } },
|
||||
{ key: 'rxNss', label: 'Rx NSS', _style: { width: '4%' } },
|
||||
{ key: 'txRate', label: 'TxRate', _style: { width: '7%' } },
|
||||
{ key: 'txBytes', label: 'TxBytes', _style: { width: '7%' } },
|
||||
{ key: 'ipV4', label: 'IpV4', _style: { width: '17%' } },
|
||||
{ key: 'ipV6', label: 'IpV6', _style: { width: '17%' } },
|
||||
{ key: 'radio', label: 'R', _style: { width: '5%' } },
|
||||
{ key: 'bssid', label: 'BSSID', _style: { width: '14%' } },
|
||||
{ key: 'mode', label: t('wifi_analysis.mode'), _style: { width: '9%' }, sorter: false },
|
||||
{ key: 'ssid', label: 'SSID', _style: { width: '14%' } },
|
||||
{ key: 'rssi', label: 'RSSI', _style: { width: '5%' }, sorter: false },
|
||||
{ key: 'rxRate', label: 'Rx Rate', _style: { width: '7%' }, sorter: false },
|
||||
{ key: 'rxBytes', label: 'Rx Bytes', _style: { width: '7%' }, sorter: false },
|
||||
{ key: 'rxMcs', label: 'Rx MCS', _style: { width: '7%' }, sorter: false },
|
||||
{ key: 'rxNss', label: 'Rx NSS', _style: { width: '7%' }, sorter: false },
|
||||
{ key: 'txRate', label: 'Tx Rate', _style: { width: '7%' }, sorter: false },
|
||||
{ key: 'txBytes', label: 'Tx Bytes', _style: { width: '7%' }, sorter: false },
|
||||
{ key: 'ips', label: 'Ip Addr.', _style: { width: '7%' }, sorter: false },
|
||||
];
|
||||
|
||||
const centerIfEmpty = (value) => (
|
||||
<td className={!value || value === '' || value === '-' ? 'text-center' : ''}>{value}</td>
|
||||
);
|
||||
|
||||
const displayIp = (v4, v6) => {
|
||||
const count = v4.length + v6.length;
|
||||
|
||||
const content4 = v4.map((ip) => <li>{ip}</li>);
|
||||
const content6 = v6.map((ip) => <li>{ip}</li>);
|
||||
|
||||
const content = (
|
||||
<div>
|
||||
IpV4
|
||||
<ul>{content4}</ul>
|
||||
IpV6
|
||||
<ul>{content6}</ul>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<td className="text-center">
|
||||
{count > 0 ? (
|
||||
<CPopover header="Ipv4 - Ipv6 Addresses" content={content} trigger="click" interactive>
|
||||
<CButton color="primary" size="sm">
|
||||
{count}
|
||||
</CButton>
|
||||
</CPopover>
|
||||
) : (
|
||||
<p>{count}</p>
|
||||
)}
|
||||
</td>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<CCard>
|
||||
<CCardHeader>
|
||||
<CRow>
|
||||
<CCol className="text-center">
|
||||
<input
|
||||
type="range"
|
||||
style={{ width: '80%' }}
|
||||
className="form-range"
|
||||
min="0"
|
||||
max={range}
|
||||
step="1"
|
||||
onChange={(e) => updateSelectedStats(e.target.value)}
|
||||
defaultValue={range}
|
||||
/>
|
||||
<h5>
|
||||
{t('common.timestamp')}: {data[0]?.timeStamp}
|
||||
</h5>
|
||||
</CCol>
|
||||
</CRow>
|
||||
</CCardHeader>
|
||||
<CCardBody>
|
||||
<CDataTable fields={columns} items={data} hover border loading={loading} />
|
||||
</CCardBody>
|
||||
</CCard>
|
||||
<CDataTable
|
||||
fields={columns}
|
||||
items={data}
|
||||
hover
|
||||
border
|
||||
loading={loading}
|
||||
sorter
|
||||
sorterValue={{ column: 'radio', asc: true }}
|
||||
scopedSlots={{
|
||||
radio: (item) => <td className="text-center">{item.radio.radio}</td>,
|
||||
rxMcs: (item) => centerIfEmpty(item.rxMcs),
|
||||
rxNss: (item) => centerIfEmpty(item.rxNss),
|
||||
ips: (item) => displayIp(item.ipV4, item.ipV6),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -53,7 +75,5 @@ WifiAnalysisTable.propTypes = {
|
||||
t: PropTypes.func.isRequired,
|
||||
data: PropTypes.instanceOf(Object).isRequired,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
range: PropTypes.number.isRequired,
|
||||
updateSelectedStats: PropTypes.func.isRequired,
|
||||
};
|
||||
export default WifiAnalysisTable;
|
||||
|
||||
@@ -15,6 +15,8 @@ export { default as EditUserForm } from './components/EditUserForm';
|
||||
export { default as EditMyProfile } from './components/EditMyProfile';
|
||||
export { default as Avatar } from './components/Avatar';
|
||||
export { default as WifiAnalysisTable } from './components/WifiAnalysisTable';
|
||||
export { default as RadioAnalysisTable } from './components/RadioAnalysisTable';
|
||||
export { default as ApiStatusCard } from './components/ApiStatusCard';
|
||||
|
||||
// Pages
|
||||
export { default as LoginPage } from './components/LoginPage';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.sidebarImgFull {
|
||||
height: 100px;
|
||||
width: 230px;
|
||||
height: 75px;
|
||||
width: 175;
|
||||
}
|
||||
|
||||
.sidebarImgMinimized {
|
||||
|
||||
Reference in New Issue
Block a user