Skip to content

Commit

Permalink
Merge pull request #95 from LaumiH/feature/configurable_auto_reload
Browse files Browse the repository at this point in the history
feat: add configurable page auto-refresh to all pages (in Dashboard)
  • Loading branch information
ianchen0119 committed May 13, 2024
2 parents 420d9ba + 05e2a93 commit 29acb89
Show file tree
Hide file tree
Showing 16 changed files with 144 additions and 77 deletions.
103 changes: 97 additions & 6 deletions frontend/src/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext } from "react";
import React, { useContext, useState, useEffect } from "react";
import { styled, createTheme, ThemeProvider } from "@mui/material/styles";
import CssBaseline from "@mui/material/CssBaseline";
import MuiDrawer from "@mui/material/Drawer";
Expand All @@ -17,6 +17,7 @@ import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
import { MainListItems } from "./ListItems";
import { LoginContext } from "./LoginContext";
import SimpleListMenu from "./SimpleListMenu";
import { useNavigate } from "react-router-dom";

const drawerWidth = 300;

Expand Down Expand Up @@ -73,14 +74,83 @@ const mdTheme = createTheme();
export interface DashboardProps {
children: React.ReactNode;
title: string;
refreshAction: () => void;
}

function Dashboard(props: DashboardProps) {
const [open, setOpen] = React.useState(true);
const toggleDrawer = () => {
setOpen(!open);
};
const { user } = useContext(LoginContext);
const { user, setUser } = useContext(LoginContext);
const navigation = useNavigate();

const [time, setTime] = useState<Date>(new Date());
const [refreshInterval, setRefreshInterval] = useState(0);
const [refreshString, setRefreshString] = useState("manual");

// execute every time the refreshInterval changes to set the interval correctly
// update the time value every x ms, which triggers refresh (see below)
useEffect(() => {
if (refreshInterval === 0) {
console.log("refreshInterval is 0");
return;
}
const interval = setInterval(() => setTime(new Date()), refreshInterval);
return () => {
console.log("clear refreshInterval");
clearInterval(interval);
};
}, [refreshInterval]);

// refresh every time the 'time' value changes
useEffect(() => {
console.log("reload page at", time.toISOString());
props.refreshAction();
}, [time]);

const handleUserNameClick = (event: React.MouseEvent<HTMLElement>, index: number) => {
switch (index) {
case 0:
navigation("/password");
break;
case 1:
setUser(null);
navigation("/login");
break;
default:
break;
}
};

const refreshStrings = ["manual", "1s", "5s", "10s", "30s"];

const handleRefreshClick = (event: React.MouseEvent<HTMLElement>, index: number) => {
switch (index) {
case 0: // manual
setRefreshInterval(0);
setRefreshString(refreshStrings.at(index)!);
break;
case 1: // 1s
setRefreshInterval(1000);
setRefreshString(refreshStrings.at(index)!);
break;
case 2: // 5s
setRefreshInterval(5000);
setRefreshString(refreshStrings.at(index)!);
break;
case 3: // 10s
setRefreshInterval(10000);
setRefreshString(refreshStrings.at(index)!);
break;
case 4: // 30s
setRefreshInterval(30000);
setRefreshString(refreshStrings.at(index)!);
break;
default:
break;
}
};

return (
<ThemeProvider theme={mdTheme}>
Expand All @@ -104,10 +174,31 @@ function Dashboard(props: DashboardProps) {
>
<MenuIcon />
</IconButton>
<Typography component="h1" variant="h6" color="inherit" noWrap sx={{ flexGrow: 1 }}>
{props.title}
</Typography>
<SimpleListMenu title={user?.username} />
<Box sx={{ display: "flex", alignItems: "center", flexGrow: 1 }}>
<Typography component="h1" variant="h6" color="inherit" noWrap>
{props.title}
</Typography>
<Divider
orientation="vertical"
flexItem
sx={{
//height: "100%",
//alignSelf: "center",
mx: 2,
borderColor: "white",
}}
/>
<SimpleListMenu
title={`Refresh: ${refreshString}`}
options={refreshStrings}
handleMenuItemClick={handleRefreshClick}
/>
</Box>
<SimpleListMenu
title={user?.username}
options={["Change Password", "Logout"]}
handleMenuItemClick={handleUserNameClick}
/>
</Toolbar>
</AppBar>
<Drawer variant="permanent" open={open}>
Expand Down
48 changes: 11 additions & 37 deletions frontend/src/SimpleListMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,24 @@
import React, { useContext } from "react";
import { useNavigate } from "react-router-dom";
import React, { useState } from "react";
import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem";
import ListItemText from "@mui/material/ListItemText";
import MenuItem from "@mui/material/MenuItem";
import Menu from "@mui/material/Menu";

import { LoginContext } from "./LoginContext";

const options = ["Change Password", "Logout"];

export interface SimpleListMenuProps {
title: string | undefined;
options: string[];
handleMenuItemClick: (event: React.MouseEvent<HTMLElement>, index: number) => void;
}

export default function SimpleListMenu(props: SimpleListMenuProps) {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const [selectedIndex, setSelectedIndex] = React.useState(1);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selectedIndex, setSelectedIndex] = useState(0);
const open = Boolean(anchorEl);
const handleClickListItem = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};

const navigation = useNavigate();
const { setUser } = useContext(LoginContext);

function onChangePassword() {
navigation("/password");
}

function onLogout() {
setUser(null);
navigation("/login");
}

const handleMenuItemClick = (event: React.MouseEvent<HTMLElement>, index: number) => {
setSelectedIndex(index);
setAnchorEl(null);
switch (index) {
case 0:
onChangePassword();
break;
case 1:
onLogout();
break;
default:
break;
}
};

const handleClose = () => {
setAnchorEl(null);
};
Expand Down Expand Up @@ -78,11 +48,15 @@ export default function SimpleListMenu(props: SimpleListMenuProps) {
role: "listbox",
}}
>
{options.map((option, index) => (
{props.options.map((option, index) => (
<MenuItem
key={option}
selected={index === selectedIndex}
onClick={(event) => handleMenuItemClick(event, index)}
onClick={(event) => {
setSelectedIndex(index);
setAnchorEl(null);
props.handleMenuItemClick(event, index);
}}
>
{option}
</MenuItem>
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/pages/AnalysisList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default function AnalysisList() {
const [data, setData] = useState<UeContext[]>([]);
const [limit, setLimit] = useState(50);
const [page, setPage] = useState(0);
const [refresh, setRefresh] = useState<boolean>(false);

useEffect(() => {
axios
Expand All @@ -29,9 +30,9 @@ export default function AnalysisList() {
setData(res.data);
})
.catch((e) => {
console.log(e);
console.log(e.message);
});
}, [limit, page]);
}, [refresh, limit, page]);

const handlePageChange = (
_event: React.MouseEvent<HTMLButtonElement> | null,
Expand Down Expand Up @@ -103,7 +104,7 @@ export default function AnalysisList() {
);

return (
<Dashboard title="Analysis">
<Dashboard title="Analysis" refreshAction={() => setRefresh(!refresh)}>
<br />
{data == null || data.length === 0 ? <div>No App Data</div> : tableView}
</Dashboard>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/ChangePassword.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export default function ChangePassword() {
};

return (
<Dashboard title="Change Password">
<Dashboard title="Change Password" refreshAction={() => {}}>
<Table>
<TableBody>
<TableRow>
Expand Down
23 changes: 10 additions & 13 deletions frontend/src/pages/Charging/ChargingTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { Button, Grid } from "@mui/material";

export default function ChargingTable() {
const [expand, setExpand] = useState(true);
const [currentTime, setCurrentTime] = useState<Date>(new Date());
const [refresh, setRefresh] = useState<boolean>(false);
const [updateTime, setUpdateTime] = useState<Date>(new Date());

const [onlineChargingData, setOnlineChargingData] = useState<ChargingData[]>([]);
const [offlineChargingData, setOfflineChargingData] = useState<ChargingData[]>([]);
Expand Down Expand Up @@ -47,47 +48,43 @@ export default function ChargingTable() {
fetchChargingData("Online", setOnlineChargingData);
fetchChargingData("Offline", setOfflineChargingData);
fetchChargingRecord();
setCurrentTime(new Date());
setUpdateTime(new Date());
};

useEffect(() => {
onRefresh();
const id = setInterval(() => {
onRefresh();
}, 10000);
return () => clearInterval(id);
}, []);
}, [refresh]);

const onExpand = () => {
setExpand(!expand);
};

return (
<Dashboard title="UE CHARGING">
<Dashboard title="UE CHARGING" refreshAction={() => onRefresh()}>
<Grid container spacing="2">
<Grid item>
<Button
color="secondary"
variant="contained"
onClick={() => onRefresh()}
onClick={() => onExpand()}
sx={{ m: 2, backgroundColor: "blue", "&:hover": { backgroundColor: "blue" } }}
>
Refresh
{expand ? "Fold" : "Expand"}
</Button>
</Grid>
<Grid item>
<Button
color="secondary"
variant="contained"
onClick={() => onExpand()}
onClick={() => onRefresh()}
sx={{ m: 2, backgroundColor: "blue", "&:hover": { backgroundColor: "blue" } }}
>
{expand ? "Fold" : "Expand"}
Refresh
</Button>
</Grid>
<Grid item>
<Button color="success" variant="contained" sx={{ m: 2 }} disabled>
Last update: {currentTime.toISOString().slice(0, 19).replace("T", " ")}
Last update: {updateTime.toISOString().slice(0, 19).replace("T", " ")}
</Button>
</Grid>
</Grid>
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/pages/StatusList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
export default function StatusList() {
const navigation = useNavigate();
const [data, setData] = useState<UeContext[]>([]);
const [refresh, setRefresh] = useState<boolean>(false);
const [limit, setLimit] = useState(50);
const [page, setPage] = useState(0);

Expand All @@ -33,9 +34,9 @@ export default function StatusList() {
}
})
.catch((e) => {
console.log(e);
console.log(e.message);
});
}, [limit, page]);
}, [refresh, limit, page]);

const handlePageChange = (
_event: React.MouseEvent<HTMLButtonElement> | null,
Expand Down Expand Up @@ -109,7 +110,7 @@ export default function StatusList() {
);

return (
<Dashboard title="Registered UEs">
<Dashboard title="Registered UEs" refreshAction={() => setRefresh(!refresh)}>
<br />
{data == null || data.length === 0 ? <div>No App Data</div> : tableView}
</Dashboard>
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/pages/StatusRead.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Card, Table, TableBody, TableCell, TableRow } from "@mui/material";
export default function StatusRead() {
const location = useLocation();
const ueContext = location.state as UeContext;
const [refresh, setRefresh] = useState<boolean>(false);

const { id } = useParams<{
id: string;
Expand All @@ -28,10 +29,10 @@ export default function StatusRead() {
const pdus: PduSessionInfo[] = res.map((item) => item.data);
setData(pdus);
});
}, [id]);
}, [id, refresh]);

return (
<Dashboard title="Registered UEs">
<Dashboard title="Registered UEs" refreshAction={() => setRefresh(!refresh)}>
<h3>AMF Information [SUPI:{ueContext.Supi}]</h3>
<Card variant="outlined">
<Table>
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/pages/SubscriberCreate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ export default function SubscriberCreate() {
if (!isNewSubscriber) {
useEffect(() => {
axios.get("/api/subscriber/" + id + "/" + plmn).then((res) => {
console.log('loaded existing subscriber', res.data);
setData(res.data);
});
}, [id]);
Expand Down Expand Up @@ -1577,7 +1578,7 @@ export default function SubscriberCreate() {
};

return (
<Dashboard title="Subscription">
<Dashboard title="Subscription" refreshAction={() => {}}>
<Card variant="outlined">
<Table>
<TableBody id="Subscriber Data Number">
Expand Down
Loading

0 comments on commit 29acb89

Please sign in to comment.