feat(frontend): site survey

This commit is contained in:
leandrofars 2024-07-10 11:12:42 -03:00
parent 868a97f9d5
commit ad90ea6a4f
3 changed files with 316 additions and 168 deletions

View File

@ -18,14 +18,14 @@
"@mui/system": "5.11.9", "@mui/system": "5.11.9",
"@mui/x-date-pickers": "5.0.19", "@mui/x-date-pickers": "5.0.19",
"@react-google-maps/api": "^2.19.3", "@react-google-maps/api": "^2.19.3",
"apexcharts": "3.37.0", "apexcharts": "^3.37.0",
"date-fns": "2.29.3", "date-fns": "2.29.3",
"formik": "2.2.9", "formik": "2.2.9",
"next": "^14.2.4", "next": "^14.2.4",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"prop-types": "15.8.1", "prop-types": "15.8.1",
"react": "^18.3.1", "react": "^18.3.1",
"react-apexcharts": "1.4.0", "react-apexcharts": "^1.4.0",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"simple-peer": "^9.11.1", "simple-peer": "^9.11.1",
"simplebar-react": "^3.2.1", "simplebar-react": "^3.2.1",
@ -1480,6 +1480,11 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
} }
}, },
"node_modules/@yr/monotone-cubic-spline": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz",
"integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA=="
},
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.11.3", "version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
@ -1538,10 +1543,11 @@
} }
}, },
"node_modules/apexcharts": { "node_modules/apexcharts": {
"version": "3.37.0", "version": "3.50.0",
"resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.37.0.tgz", "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.50.0.tgz",
"integrity": "sha512-0mg1gDKUo3JG00Q//LK0jEXBS6OLjpuglqZ8ec9cqfA5oP8owopD9n5EhfARbWROb5o8GSPzFuohTJiCm2ecWw==", "integrity": "sha512-LJT1PNAm+NoIU3aogL2P+ViC0y/Cjik54FdzzGV54UNnGQLBoLe5ok3fxsJDTgyez45BGYT8gqNpYKqhdfy5sg==",
"dependencies": { "dependencies": {
"@yr/monotone-cubic-spline": "^1.0.3",
"svg.draggable.js": "^2.2.2", "svg.draggable.js": "^2.2.2",
"svg.easing.js": "^2.0.0", "svg.easing.js": "^2.0.0",
"svg.filter.js": "^2.0.2", "svg.filter.js": "^2.0.2",
@ -4722,14 +4728,14 @@
} }
}, },
"node_modules/react-apexcharts": { "node_modules/react-apexcharts": {
"version": "1.4.0", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.4.0.tgz", "resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.4.1.tgz",
"integrity": "sha512-DrcMV4aAMrUG+n6412yzyATWEyCDWlpPBBhVbpzBC4PDeuYU6iF84SmExbck+jx5MUm4U5PM3/T307Mc3kzc9Q==", "integrity": "sha512-G14nVaD64Bnbgy8tYxkjuXEUp/7h30Q0U33xc3AwtGFijJB9nHqOt1a6eG0WBn055RgRg+NwqbKGtqPxy15d0Q==",
"dependencies": { "dependencies": {
"prop-types": "^15.5.7" "prop-types": "^15.8.1"
}, },
"peerDependencies": { "peerDependencies": {
"apexcharts": "^3.18.0", "apexcharts": "^3.41.0",
"react": ">=0.13" "react": ">=0.13"
} }
}, },
@ -7102,6 +7108,11 @@
"eslint-visitor-keys": "^3.3.0" "eslint-visitor-keys": "^3.3.0"
} }
}, },
"@yr/monotone-cubic-spline": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz",
"integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA=="
},
"acorn": { "acorn": {
"version": "8.11.3", "version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
@ -7142,10 +7153,11 @@
} }
}, },
"apexcharts": { "apexcharts": {
"version": "3.37.0", "version": "3.50.0",
"resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.37.0.tgz", "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.50.0.tgz",
"integrity": "sha512-0mg1gDKUo3JG00Q//LK0jEXBS6OLjpuglqZ8ec9cqfA5oP8owopD9n5EhfARbWROb5o8GSPzFuohTJiCm2ecWw==", "integrity": "sha512-LJT1PNAm+NoIU3aogL2P+ViC0y/Cjik54FdzzGV54UNnGQLBoLe5ok3fxsJDTgyez45BGYT8gqNpYKqhdfy5sg==",
"requires": { "requires": {
"@yr/monotone-cubic-spline": "^1.0.3",
"svg.draggable.js": "^2.2.2", "svg.draggable.js": "^2.2.2",
"svg.easing.js": "^2.0.0", "svg.easing.js": "^2.0.0",
"svg.filter.js": "^2.0.2", "svg.filter.js": "^2.0.2",
@ -9444,11 +9456,11 @@
} }
}, },
"react-apexcharts": { "react-apexcharts": {
"version": "1.4.0", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.4.0.tgz", "resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.4.1.tgz",
"integrity": "sha512-DrcMV4aAMrUG+n6412yzyATWEyCDWlpPBBhVbpzBC4PDeuYU6iF84SmExbck+jx5MUm4U5PM3/T307Mc3kzc9Q==", "integrity": "sha512-G14nVaD64Bnbgy8tYxkjuXEUp/7h30Q0U33xc3AwtGFijJB9nHqOt1a6eG0WBn055RgRg+NwqbKGtqPxy15d0Q==",
"requires": { "requires": {
"prop-types": "^15.5.7" "prop-types": "^15.8.1"
} }
}, },
"react-dom": { "react-dom": {

View File

@ -24,14 +24,14 @@
"@mui/system": "5.11.9", "@mui/system": "5.11.9",
"@mui/x-date-pickers": "5.0.19", "@mui/x-date-pickers": "5.0.19",
"@react-google-maps/api": "^2.19.3", "@react-google-maps/api": "^2.19.3",
"apexcharts": "3.37.0", "apexcharts": "^3.37.0",
"date-fns": "2.29.3", "date-fns": "2.29.3",
"formik": "2.2.9", "formik": "2.2.9",
"next": "^14.2.4", "next": "^14.2.4",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"prop-types": "15.8.1", "prop-types": "15.8.1",
"react": "^18.3.1", "react": "^18.3.1",
"react-apexcharts": "1.4.0", "react-apexcharts": "^1.4.0",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"simple-peer": "^9.11.1", "simple-peer": "^9.11.1",
"simplebar-react": "^3.2.1", "simplebar-react": "^3.2.1",

View File

@ -1,6 +1,3 @@
import PropTypes from 'prop-types';
import ArrowPathIcon from '@heroicons/react/24/solid/ArrowPathIcon';
import ArrowRightIcon from '@heroicons/react/24/solid/ArrowRightIcon';
import { import {
Button, Button,
Card, Card,
@ -22,12 +19,11 @@ import {
TableHead, TableHead,
TableRow, TableRow,
TableContainer, TableContainer,
Paper, CircularProgress,
Container, ToggleButton,
CircularProgress ToggleButtonGroup
} from '@mui/material'; } from '@mui/material';
import { Scrollbar } from 'src/components/scrollbar'; import { useTheme } from '@mui/material/styles';
import { alpha, useTheme } from '@mui/material/styles';
import { Chart } from 'src/components/chart'; import { Chart } from 'src/components/chart';
import ChartBarSquareIcon from '@heroicons/react/24/outline/ChartBarSquareIcon'; import ChartBarSquareIcon from '@heroicons/react/24/outline/ChartBarSquareIcon';
import ListBulletIcon from '@heroicons/react/24/outline/ListBulletIcon'; import ListBulletIcon from '@heroicons/react/24/outline/ListBulletIcon';
@ -35,7 +31,103 @@ import { useRouter } from 'next/router';
import { Stack } from '@mui/system'; import { Stack } from '@mui/system';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
const useChartOptions = () => { export const SiteSurvey = (props) => {
// const getMaxChannel = () => {
// if (frequency == "2.4GHz") {
// return 13;
// } else {
// return 128;
// }
// }
// const geMinChannel = () => {
// if (frequency == "2.4GHz") {
// return 0;
// } else {
// return 36;
// }
// }
// const getChannelSpacing = () => {
// if (frequency == "2.4GHz") {
// return 1;
// } else {
// return 4;
// }
// }
// const getChannelAmount = () => {
// if (frequency == "2.4GHz") {
// return 13;
// } else {
// return 20;
// }
// }
const getCategories = () => {
}
const router = useRouter();
const [frequency, setFrequency] = useState("2.4GHz");
const [view, setView] = useState("chart");
const [content, setContent] = useState(null);
const getSeries = () => {
let series = []
content[frequency].map((network) => {
let data = []
if (frequency == "2.4GHz") {
if (Number(network.bandwidth) == 20) {
data.push({"x": Number(network.channel) -2, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +2, "y": -100})
}
if (Number(network.bandwidth) == 40) {
data.push({"x": Number(network.channel) -4, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +4, "y": -100})
}
}else {
if (Number(network.bandwidth) == 20) {
data.push({"x": Number(network.channel) -4, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +4, "y": -100})
}
if (Number(network.bandwidth) == 40) {
data.push({"x": Number(network.channel) -8, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +8, "y": -100})
}
if (Number(network.bandwidth) == 80) {
data.push({"x": Number(network.channel) -16, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +16, "y": -100})
}
if (Number(network.bandwidth) == 160) {
data.push({"x": Number(network.channel) -32, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +32, "y": -100})
}
}
let ssid = network.ssid
if ( ssid == "") {
ssid = " "
}
return series.push({
name: ssid,
data: data
})
})
return series;
}
const useChartOptions = () => {
const theme = useTheme(); const theme = useTheme();
return { return {
@ -44,100 +136,150 @@ const useChartOptions = () => {
stacked: false, stacked: false,
toolbar: { toolbar: {
show: true show: true
}
}, },
zoom: {
enabled: false
},
},
title: {
text: 'Site Survey Results',
},
// markers: {
// size: 5,
// hover: {
// size: 9
// }
// },
colors: [ colors: [
theme.palette.graphics.dark, theme.palette.graphics.dark,
theme.palette.warning.main,
theme.palette.graphics.darkest, theme.palette.graphics.darkest,
theme.palette.graphics.light,
theme.palette.graphics.main, theme.palette.graphics.main,
theme.palette.info.light,
theme.palette.graphics.lightest, theme.palette.graphics.lightest,
theme.palette.primary.main,
theme.palette.graphics.light,
theme.palette.error.light,
], ],
dataLabels: { dataLabels: {
enabled: false enabled: false
}, },
fill: {
opacity: 1,
type: 'solid'
},
grid: { grid: {
borderColor: theme.palette.divider, //borderColor: theme.palette.divider,
strokeDashArray: 2, strokeDashArray: 2,
xaxis: { xaxis: {
lines: { lines: {
show: false show: true
} }
}, },
yaxis: { yaxis: {
lines: { lines: {
show: true show: true
} },
} },
}, },
legend: { legend: {
show: true show: true,
showForSingleSeries: true,
}, },
plotOptions: { plotOptions: {
bar: { area: {
columnWidth: '40px' fillTo: 'end',
} }
}, },
stroke: { stroke: {
colors: ['transparent'],
show: true, show: true,
width: 2 curve: 'smooth',
lineCap: 'round',
}, },
theme: { theme: {
mode: theme.palette.mode mode: theme.palette.mode
}, },
xaxis: {
axisBorder: {
color: theme.palette.divider,
show: true
},
axisTicks: {
color: theme.palette.divider,
show: true
},
categories: [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec'
],
labels: {
offsetY: 5,
style: {
colors: theme.palette.text.secondary
}
}
},
yaxis: { yaxis: {
min: -100,
max: 0,
labels: { labels: {
formatter: (value) => (value > 0 ? `${value}K` : `${value}`), formatter: function (value) {
offsetX: -10, return value + ' dBm';
},
//offsetY: -10,
style: { style: {
colors: theme.palette.text.secondary //colors: theme.palette.text.secondary
} }
},
},
// annotations: {
// xaxis: [
// {
// x: 9,
// x2: 10,
// borderColor: '#0b54ff',
// label: {
// style: {
// color: 'black',
// },
// text: 'Channel 10',
// offsetX: 45,
// borderColor: 'transparent',
// style: {
// background: 'transparent',
// color: theme.palette.text.secondary,
// fontSize: '17px',
// },
// }
// }
// ]
// },
// annotations: {
// points: [{
// x: 9,
// y: -5,
// label: {
// borderColor: '#775DD0',
// offsetY: 0,
// style: {
// color: '#fff',
// background: '#775DD0',
// },
// rotate: -45,
// text: 'Bananas are good',
// }
// }]
// },
xaxis: {
// tickPlacement: 'on',
// tickAmount: getChannelAmount(),
tickPlacement: 'on',
labels: {
show: true,
style: {
//colors: theme.palette.text.secondary
},
trim: true,
},
// max: getMaxChannel(),
// min: geMinChannel(),
// stepSize: getChannelSpacing(),
//type: 'category',
//categories: [getCategories()],
type: 'numeric',
decimalsInFloat: 0,
},
tooltip: {
x: {
show: true,
formatter: (seriesName) => "Channel "+ seriesName,
},
followCursor: false,
intersect: false,
shared: true,
enabled: true,
onDatasetHover: {
highlightDataSeries: true,
} }
} }
}; };
}; };
export const SiteSurvey = (props) => {
const chartSeries = [{ name: 'This year', data: [18, 16, 5, 8, 3, 14, 14, 16, 17, 19, 18, 20] }, { name: 'Last year', data: [12, 11, 4, 6, 2, 9, 9, 10, 11, 12, 13, 13] }]
const router = useRouter();
const [content, setContent] = useState(null);
const [frequency, setFrequency] = useState("2.4GHz");
const chartOptions = useChartOptions(); const chartOptions = useChartOptions();
@ -181,23 +323,30 @@ export const SiteSurvey = (props) => {
<Grid spacing={1}> <Grid spacing={1}>
<Grid container> <Grid container>
<Card> <Card>
<Button <ToggleButtonGroup
color="inherit" value={view}
exclusive
onChange={(e, value) => {
setView(value)
}}
>
<ToggleButton
size="small" size="small"
disabled="true" value="chart"
> >
<SvgIcon> <SvgIcon>
<ChartBarSquareIcon /> <ChartBarSquareIcon />
</SvgIcon> </SvgIcon>
</Button> </ToggleButton>
<Button <ToggleButton
color="inherit"
size="small" size="small"
value="list"
> >
<SvgIcon> <SvgIcon>
<ListBulletIcon /> <ListBulletIcon />
</SvgIcon> </SvgIcon>
</Button> </ToggleButton>
</ToggleButtonGroup>
</Card> </Card>
</Grid> </Grid>
<Box display="flex" <Box display="flex"
@ -221,7 +370,7 @@ export const SiteSurvey = (props) => {
</RadioGroup> </RadioGroup>
</FormControl> </FormControl>
</Box> </Box>
<Card sx={{ height: '100%' }}> {view == "list" && <Card sx={{ height: '100%' }}>
<Box sx={{ minWidth: 800, }}> <Box sx={{ minWidth: 800, }}>
<TableContainer sx={{ maxHeight: 600 }}> <TableContainer sx={{ maxHeight: 600 }}>
<Table exportButton={true}> <Table exportButton={true}>
@ -273,31 +422,18 @@ export const SiteSurvey = (props) => {
</Table> </Table>
</TableContainer> </TableContainer>
</Box> </Box>
{/* <CardContent> </Card>}
{view == "chart" && <Card>
<CardContent>
<Chart <Chart
height={500} height={500}
options={chartOptions} options={chartOptions}
series={chartSeries} series={getSeries()}
type="bar" type="area"
width="100%" width="100%"
/> />
</CardContent> </CardContent>
<Divider /> </Card>}
<CardActions sx={{ justifyContent: 'center' }}>
<FormControl xs={2}>
<RadioGroup
aria-labelledby="demo-controlled-radio-buttons-group"
name="controlled-radio-buttons-group"
value={"2.4GHz"}
>
<Grid container>
<FormControlLabel value="2.4GHz" control={<Radio />} label="2.4GHz" />
<FormControlLabel value="5GHz" control={<Radio />} label="5GHz" />
</Grid>
</RadioGroup>
</FormControl>
</CardActions> */}
</Card>
</Grid>: <CircularProgress></CircularProgress>} </Grid>: <CircularProgress></CircularProgress>}
</Stack> </Stack>
); );