Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Login & Homepage #115

Open
wants to merge 32 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
7372776
Start homepage
hello-binit Oct 3, 2024
0a41569
Render homepage based on login state
hello-binit Oct 3, 2024
bbbbf8a
WIP: Robot selector
hello-binit Oct 3, 2024
3cdfee7
Fill out caller card in robot selector
hello-binit Oct 21, 2024
ace6937
Show occupied robots in selector
hello-binit Oct 21, 2024
e510be2
Try a no-paper design for Changelog elements
hello-binit Oct 22, 2024
65c77d8
Use AppBar for homepage title + logout button
hello-binit Oct 22, 2024
57642a0
Trigger logout with logout button
hello-binit Oct 22, 2024
93d56bb
Add login view
hello-binit Oct 22, 2024
19681ca
Add forgot password component
hello-binit Oct 22, 2024
6190a5d
Wire login details to login handler
hello-binit Oct 22, 2024
44ad934
Wire forgot password to login handler
hello-binit Oct 22, 2024
538e7c9
Local login starts authenticated by default
hello-binit Oct 22, 2024
c30e96e
Wire callable robots through login handler
hello-binit Oct 22, 2024
dc53068
Local server reports if robot is occupied
hello-binit Oct 23, 2024
bafc17a
Fix occupied logic
hello-binit Oct 23, 2024
97e88cd
Change title based on login state
hello-binit Oct 23, 2024
8acd5b3
Add page links to robot call buttons
hello-binit Oct 23, 2024
1eb74d2
WIP firebase login handler
hello-binit Oct 23, 2024
20fee26
Logout returns promise
hello-binit Oct 23, 2024
b64a3f1
Login returns promise
hello-binit Oct 23, 2024
e358cd3
Handle incorrect login credentials
hello-binit Oct 23, 2024
e0142ba
Firebase login/logout/passwd reset works
hello-binit Oct 24, 2024
94670df
Doesnt work
hello-binit Oct 24, 2024
c67cbe2
Fix for live update of callable robots
hello-binit Oct 24, 2024
64ac96c
Live update callable robots locally
hello-binit Oct 24, 2024
66ac196
Fix auth may be null
hello-binit Oct 24, 2024
bdc478f
Throw exception is uid null
hello-binit Oct 24, 2024
cdc8713
whitespace
hello-binit Oct 24, 2024
40dfa5e
Add production build npm option
hello-binit Oct 24, 2024
83a7f77
Run prettier
hello-binit Oct 24, 2024
4ba84f1
Run prettier
hello-binit Oct 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"dependencies": {
"@emotion/react": "^11.13.0",
"@emotion/styled": "^11.13.0",
"@mui/icons-material": "^5.16.6",
"@mui/material": "^5.16.6",
"@mui/icons-material": "^6.1.2",
"@mui/material": "^6.1.2",
"@types/createjs": "^0.0.29",
"@types/react": "^18.0.34",
"@types/react-dom": "^18.0.11",
Expand Down Expand Up @@ -43,7 +43,8 @@
"scripts": {
"firebase": "webpack --mode development --progress --env storage='firebase'",
"localstorage": "webpack --mode development --progress --env storage='localstorage'",
"styleguide": "styleguidist server"
"styleguide": "styleguidist server",
"build": "webpack --mode production --progress --env storage='firebase'"
},
"eslintConfig": {
"extends": [
Expand Down
28 changes: 28 additions & 0 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ io.on("connect_error", (err) => {
console.log(`connect_error due to ${err.message}`);
});

let protocol = undefined; // TODO(binit): ensure robot/operator protocol match
let status = "offline"; // ["online", "offline", "occupied"]
function updateRooms() {
io.emit("update_rooms", {
robot_id: {
name: process.env.HELLO_FLEET_ID,
protocol: protocol,
status: status,
},
});
}

io.on("connection", function (socket) {
console.log("new socket.io connection");
// console.log('socket.handshake = ');
Expand All @@ -68,10 +80,23 @@ io.on("connection", function (socket) {
) {
socket.join(room);
socket.emit("join", room, socket.id);
status = "online";
} else {
console.log("room full");
socket.emit("full", room);
status = "occupied";
}
updateRooms();
});

socket.on("list_rooms", () => {
if (
io.sockets.adapter.rooms.get("robot") &&
io.sockets.adapter.rooms.get("robot").size >= 2
) {
status = "occupied";
}
updateRooms();
});

socket.on("add operator to robot room", (callback) => {
Expand All @@ -85,10 +110,13 @@ io.on("connection", function (socket) {
console.log("could not connect because robot room is full");
callback({ success: false });
}
status = "occupied";
} else {
console.log("could not connect because robot is not available");
callback({ success: false });
status = "offline";
}
updateRooms();
});

socket.on("signalling", function (message) {
Expand Down
3 changes: 3 additions & 0 deletions src/pages/home/css/CallRobotSelector.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.rs-container {
overflow: auto;
}
3 changes: 3 additions & 0 deletions src/pages/home/css/Changelog.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.cv-container {
overflow: auto;
}
3 changes: 3 additions & 0 deletions src/pages/home/css/LoginView.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.lv-container {
padding: 20px;
}
3 changes: 3 additions & 0 deletions src/pages/home/css/SideBySideView.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.sbs-container {
padding: 20px;
}
24 changes: 24 additions & 0 deletions src/pages/home/css/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
"Helvetica Neue", sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: rgb(245, 245, 245);
}

html,
body {
height: 100%;
margin: 0;
}

code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}

#root {
margin: 0;
height: 100%;
}
10 changes: 10 additions & 0 deletions src/pages/home/html/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Home - Stretch Web Teleop</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
168 changes: 168 additions & 0 deletions src/pages/home/tsx/components/CallRobotSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import "home/css/CallRobotSelector.css";
import React, { useEffect, useState } from "react";
import Box from "@mui/material/Box";
import Grid from "@mui/material/Grid2";
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import CardActions from "@mui/material/CardActions";
import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography";
import CircleIcon from "@mui/icons-material/Circle";
import { green, red, yellow, grey } from "@mui/material/colors";
import { loginHandler } from "../index";

function get_indicator_text(status_str) {
switch (status_str) {
case "online":
return "Online";
case "offline":
return "Offline";
case "occupied":
return "Occupied";
default:
return "Unknown";
}
}

function get_indicator(status_str) {
let statusui;
switch (status_str) {
case "online":
statusui = {
color_name: "green",
color: green,
};
break;
case "offline":
statusui = {
color_name: "red",
color: red,
};
break;
case "occupied":
statusui = {
color_name: "yellow",
color: yellow,
};
break;
default:
statusui = {
color_name: "grey",
color: grey,
};
}
let indicator_css = {
fontSize: 12,
color: statusui["color"]["A400"],
animation: `glowing_${statusui["color_name"]} 3s linear infinite`,
};
indicator_css[`@keyframes glowing_${statusui["color_name"]}`] = {
"0%": {
color: statusui["color"]["A400"],
},
"50%": {
color: statusui["color"]["A200"],
},
"100%": {
color: statusui["color"]["A400"],
},
};
return <CircleIcon sx={indicator_css} />;
}

function get_action(status_str, robot_name) {
switch (status_str) {
case "online":
return (
<Button
href={`/operator/${robot_name}`}
variant="contained"
size="small"
>
Call Robot
</Button>
);
case "offline":
return (
<Button
href={`/operator/${robot_name}`}
variant="contained"
size="small"
disabled
>
Call Robot
</Button>
);
case "occupied":
return (
<Button
href={`/operator/${robot_name}`}
variant="contained"
size="small"
disabled
>
Call Robot
</Button>
);
default:
return (
<Button
href={`/operator/${robot_name}`}
variant="contained"
size="small"
disabled
>
Call Robot
</Button>
);
}
}

const CallRobotItem = (props: { name: String; status: String }) => {
return (
<Card sx={{ minWidth: 275 }}>
<CardContent>
<Typography variant="h5" component="div">
{props.name}
</Typography>
<Typography sx={{ color: "text.secondary", mb: 1.5 }}>
{get_indicator(props.status)}{" "}
{get_indicator_text(props.status)}
</Typography>
</CardContent>
<CardActions>{get_action(props.status, props.name)}</CardActions>
</Card>
);
};

export const CallRobotSelector = (props: { style?: React.CSSProperties }) => {
const [callableRobots, setCallableRobots] = useState({});

useEffect(() => {
loginHandler.listRooms(setCallableRobots);
}, [props]);

return (
<Box sx={{ flexGrow: 1 }}>
<h2>Robots:</h2>
<Grid
container
spacing={2}
className="rs-container"
style={props.style}
>
{Object.entries(callableRobots).map(([key, value], idx) => {
return (
<Grid key={idx} size={{ md: 12, lg: 6 }}>
<CallRobotItem
key={idx}
name={value["name"]}
status={value["status"]}
/>
</Grid>
);
})}
</Grid>
</Box>
);
};
Loading
Loading