diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..0a02bcef --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +{ + "tabWidth": 4 +} diff --git a/package.json b/package.json index d88a880a..e675d876 100644 --- a/package.json +++ b/package.json @@ -1,77 +1,77 @@ { - "name": "stretch_web_teleop", - "version": "0.1.0", - "private": true, - "dependencies": { - "@types/createjs": "^0.0.29", - "@types/react": "^18.0.34", - "@types/react-dom": "^18.0.11", - "@types/roslib": "^1.3.0", - "browser": "^0.2.6", - "buffer": "^6.0.3", - "createjs-module": "^0.8.3", - "css-loader": "^6.7.3", - "dotenv": "^16.0.3", - "eslint-config-react-app": "^7.0.1", - "express": "^4.18.2", - "file-loader": "^6.2.0", - "firebase": "^9.22.1", - "html-webpack-plugin": "^4.5.2", - "jpeg-js": "^0.4.4", - "latest-createjs": "^1.0.24", - "nodejs": "^0.0.0", - "nodemon": "^3.0.1", - "playwright": "^1.33.0", - "pm2": "^5.3.0", - "process": "^0.11.10", - "react": "^18.2.0", - "react-device-detect": "^2.2.3", - "react-dom": "^18.2.0", - "react-native-keyboard-aware-scrollview": "^2.1.0", - "react-native-web": "^0.19.7", - "react-path-tooltip": "^1.0.25", - "roslib": "github:hello-vinitha/roslibjs#ros2actionclient", - "socket.io": "^4.6.1", - "socket.io-client": "^4.6.1", - "style-loader": "^3.3.2", - "three": "^0.157.0" - }, - "scripts": { - "firebase": "webpack --mode development --progress --env storage='firebase'", - "localstorage": "webpack --mode development --progress --env storage='localstorage'", - "styleguide": "styleguidist server" - }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - }, - "devDependencies": { - "@babel/plugin-transform-runtime": "^7.21.4", - "@babel/preset-env": "^7.22.6", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.21.4", - "@types/node": "^20.6.0", - "@types/three": "^0.157.0", - "babel-loader": "^9.1.2", - "babel-polyfill": "^6.26.0", - "react-docgen-typescript": "^2.2.2", - "react-styleguidist": "^13.1.1", - "typescript": "^5.2.2", - "webpack": "^5.88.2", - "webpack-cli": "^5.0.2" - } + "name": "stretch_web_teleop", + "version": "0.1.0", + "private": true, + "dependencies": { + "@types/createjs": "^0.0.29", + "@types/react": "^18.0.34", + "@types/react-dom": "^18.0.11", + "@types/roslib": "^1.3.0", + "browser": "^0.2.6", + "buffer": "^6.0.3", + "createjs-module": "^0.8.3", + "css-loader": "^6.7.3", + "dotenv": "^16.0.3", + "eslint-config-react-app": "^7.0.1", + "express": "^4.18.2", + "file-loader": "^6.2.0", + "firebase": "^9.22.1", + "html-webpack-plugin": "^4.5.2", + "jpeg-js": "^0.4.4", + "latest-createjs": "^1.0.24", + "nodejs": "^0.0.0", + "nodemon": "^3.0.1", + "playwright": "^1.33.0", + "pm2": "^5.3.0", + "process": "^0.11.10", + "react": "^18.2.0", + "react-device-detect": "^2.2.3", + "react-dom": "^18.2.0", + "react-native-keyboard-aware-scrollview": "^2.1.0", + "react-native-web": "^0.19.7", + "react-path-tooltip": "^1.0.25", + "roslib": "github:hello-vinitha/roslibjs#ros2actionclient", + "socket.io": "^4.6.1", + "socket.io-client": "^4.6.1", + "style-loader": "^3.3.2", + "three": "^0.157.0" + }, + "scripts": { + "firebase": "webpack --mode development --progress --env storage='firebase'", + "localstorage": "webpack --mode development --progress --env storage='localstorage'", + "styleguide": "styleguidist server" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "devDependencies": { + "@babel/plugin-transform-runtime": "^7.21.4", + "@babel/preset-env": "^7.22.6", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.4", + "@types/node": "^20.6.0", + "@types/three": "^0.157.0", + "babel-loader": "^9.1.2", + "babel-polyfill": "^6.26.0", + "react-docgen-typescript": "^2.2.2", + "react-styleguidist": "^13.1.1", + "typescript": "^5.2.2", + "webpack": "^5.88.2", + "webpack-cli": "^5.0.2" + } } diff --git a/server.js b/server.js index f825c677..9fccbe47 100644 --- a/server.js +++ b/server.js @@ -2,8 +2,8 @@ var fs = require("fs"); require("dotenv").config(); var options = { - key: fs.readFileSync(`certificates/${process.env.keyfile}`), - cert: fs.readFileSync(`certificates/${process.env.certfile}`), + key: fs.readFileSync(`certificates/${process.env.keyfile}`), + cert: fs.readFileSync(`certificates/${process.env.certfile}`), }; // const http = require('http'); @@ -25,20 +25,20 @@ var app = express(); app.all("*", ensureSecure); // at top of routing calls function ensureSecure(req, res, next) { - if (!req.secure) { - // handle port numbers if you need non defaults - console.log("redirecting insecure request"); - return res.redirect("https://" + req.hostname + req.url); - // res.redirect(`https://${req.hostname}${process.env.NGROK_URL}`); - } + if (!req.secure) { + // handle port numbers if you need non defaults + console.log("redirecting insecure request"); + return res.redirect("https://" + req.hostname + req.url); + // res.redirect(`https://${req.hostname}${process.env.NGROK_URL}`); + } - return next(); + return next(); } var server = require("http").Server(app); var secure_server = require("https").Server(options, app); const io = socket(secure_server, { - allowEIO3: true, + allowEIO3: true, }); app.enable("trust proxy"); app.set("port", 443); @@ -51,63 +51,65 @@ app.use("/", express.static(path.join(__dirname, "dist"))); app.listen(process.env.port); io.on("connect_error", (err) => { - console.log(`connect_error due to ${err.message}`); + console.log(`connect_error due to ${err.message}`); }); io.on("connection", function (socket) { - console.log("new socket.io connection"); - // console.log('socket.handshake = '); - // console.log(socket.handshake); + console.log("new socket.io connection"); + // console.log('socket.handshake = '); + // console.log(socket.handshake); - socket.on("join", function (room) { - console.log("Received request to join room " + room); - // A room can have atmost two clients - if ( - !io.sockets.adapter.rooms.get(room) || - io.sockets.adapter.rooms.get(room).size < 2 - ) { - socket.join(room); - socket.emit("join", room, socket.id); - } else { - console.log("room full"); - socket.emit("full", room); - } - }); + socket.on("join", function (room) { + console.log("Received request to join room " + room); + // A room can have atmost two clients + if ( + !io.sockets.adapter.rooms.get(room) || + io.sockets.adapter.rooms.get(room).size < 2 + ) { + socket.join(room); + socket.emit("join", room, socket.id); + } else { + console.log("room full"); + socket.emit("full", room); + } + }); - socket.on("add operator to robot room", (callback) => { - // The robot room is only available if another operator is not connected to it - if (io.sockets.adapter.rooms.get("robot")) { - if (io.sockets.adapter.rooms.get("robot").size < 2) { - socket.join("robot"); - socket.in("robot").emit("joined", "robot"); - callback({ success: true }); - } else { - console.log("could not connect because robot room is full"); - callback({ success: false }); - } - } else { - console.log("could not connect because robot is not available"); - callback({ success: false }); - } - }); + socket.on("add operator to robot room", (callback) => { + // The robot room is only available if another operator is not connected to it + if (io.sockets.adapter.rooms.get("robot")) { + if (io.sockets.adapter.rooms.get("robot").size < 2) { + socket.join("robot"); + socket.in("robot").emit("joined", "robot"); + callback({ success: true }); + } else { + console.log("could not connect because robot room is full"); + callback({ success: false }); + } + } else { + console.log("could not connect because robot is not available"); + callback({ success: false }); + } + }); - socket.on("signalling", function (message) { - if (io.sockets.adapter.rooms.get("robot")) { - socket.to("robot").emit("signalling", message); - } else { - console.log( - "robot_operator_room is none, so there is nobody to send the WebRTC message to", - ); - } - }); + socket.on("signalling", function (message) { + if (io.sockets.adapter.rooms.get("robot")) { + socket.to("robot").emit("signalling", message); + } else { + console.log( + "robot_operator_room is none, so there is nobody to send the WebRTC message to", + ); + } + }); - socket.on("bye", (role) => { - console.log(role, socket.rooms); - if (socket.rooms.has("robot")) { - socket.to("robot").emit("bye"); - console.log("Attempting to have the " + role + " leave the robot room."); - console.log(""); - socket.leave("robot"); - } - }); + socket.on("bye", (role) => { + console.log(role, socket.rooms); + if (socket.rooms.has("robot")) { + socket.to("robot").emit("bye"); + console.log( + "Attempting to have the " + role + " leave the robot room.", + ); + console.log(""); + socket.leave("robot"); + } + }); }); diff --git a/src/pages/operator/css/Alert.css b/src/pages/operator/css/Alert.css index 1ec72aa2..61eacd5f 100644 --- a/src/pages/operator/css/Alert.css +++ b/src/pages/operator/css/Alert.css @@ -1,65 +1,65 @@ /* The alert message box */ .alert { - position: relative; - padding: 2rem 1rem; - /* margin-bottom: 1rem; */ - border: 1px solid transparent; - border-radius: 0.25rem; - height: 5.5rem; - text-align: center; + position: relative; + padding: 2rem 1rem; + /* margin-bottom: 1rem; */ + border: 1px solid transparent; + border-radius: 0.25rem; + height: 5.5rem; + text-align: center; } .error { - color: #842029; - background-color: #f8d7da; - border-color: #f5c2c7; + color: #842029; + background-color: #f8d7da; + border-color: #f5c2c7; } .success { - color: #0f4f51; - background-color: #d1e4e7; - border-color: #badbcc; + color: #0f4f51; + background-color: #d1e4e7; + border-color: #badbcc; } .warning { - color: #664d03; - background-color: #fff3cd; - border-color: #ffecb5; + color: #664d03; + background-color: #fff3cd; + border-color: #ffecb5; } .primary { - color: #084298; - background-color: #cfe2ff; - border-color: #b6d4fe; + color: #084298; + background-color: #cfe2ff; + border-color: #b6d4fe; } .info { - color: #41464b; - background-color: #e2e3e5; - border-color: #d3d6d8; + color: #41464b; + background-color: #e2e3e5; + border-color: #d3d6d8; } .secondary { - color: #055160; - background-color: #cff4fc; - border-color: #b6effb; + color: #055160; + background-color: #cff4fc; + border-color: #b6effb; } /* The close button */ .closebtn { - margin-left: 15px; - /* color: white; */ - font-weight: bold; - float: right; - font-size: 3rem; - line-height: 0.75rem; - cursor: pointer; - transition: 0.3s; + margin-left: 15px; + /* color: white; */ + font-weight: bold; + float: right; + font-size: 3rem; + line-height: 0.75rem; + cursor: pointer; + transition: 0.3s; } /* When moving the mouse over the close button */ .closebtn:hover { - color: black; + color: black; } .hide { - display: none; + display: none; } diff --git a/src/pages/operator/css/AudioControl.css b/src/pages/operator/css/AudioControl.css index 21d2be09..b001a321 100644 --- a/src/pages/operator/css/AudioControl.css +++ b/src/pages/operator/css/AudioControl.css @@ -1,15 +1,15 @@ .audioControlContainer { - display: flex; - flex-direction: column; - align-items: center; - text-align: center; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; } .audioControl { - display: none; + display: none; } .audioControlButton { - border-radius: 50%; - aspect-ratio: 1; + border-radius: 50%; + aspect-ratio: 1; } diff --git a/src/pages/operator/css/BatteryGuage.css b/src/pages/operator/css/BatteryGuage.css index 623dff3d..c6985969 100644 --- a/src/pages/operator/css/BatteryGuage.css +++ b/src/pages/operator/css/BatteryGuage.css @@ -1,59 +1,59 @@ .bar { - width: 100%; - height: 15px; - background-color: #436fb7; - display: flex; - margin-top: 3px; + width: 100%; + height: 15px; + background-color: #436fb7; + display: flex; + margin-top: 3px; } .barsContainer { - width: 50px; - height: 100px; - display: flex; - flex-direction: column-reverse; - align-items: center; + width: 50px; + height: 100px; + display: flex; + flex-direction: column-reverse; + align-items: center; } .batteryGauge { - height: 100px; - /* position: absolute; */ - width: 100%; - padding: 0px 10px 10px 10px; + height: 100px; + /* position: absolute; */ + width: 100%; + padding: 0px 10px 10px 10px; } .green { - filter: invert(17%) sepia(15%) saturate(6070%) hue-rotate(89deg) - brightness(75%) contrast(108%); + filter: invert(17%) sepia(15%) saturate(6070%) hue-rotate(89deg) + brightness(75%) contrast(108%); } .yellow-green { - filter: brightness(70%) saturate(100%) invert(0%) sepia(28%) saturate(4155%) - hue-rotate(56deg) contrast(119%); + filter: brightness(70%) saturate(100%) invert(0%) sepia(28%) saturate(4155%) + hue-rotate(56deg) contrast(119%); } .yellow { - filter: brightness(90%) saturate(100%) invert(0%) sepia(28%) saturate(4155%) - hue-rotate(6deg) contrast(119%); + filter: brightness(90%) saturate(100%) invert(0%) sepia(28%) saturate(4155%) + hue-rotate(6deg) contrast(119%); } .orange { - filter: brightness(70%) saturate(100%) invert(10%) sepia(28%) saturate(4155%) - hue-rotate(6deg) contrast(119%); + filter: brightness(70%) saturate(100%) invert(10%) sepia(28%) + saturate(4155%) hue-rotate(6deg) contrast(119%); } .orange-red { - filter: brightness(50%) saturate(100%) invert(10%) sepia(28%) saturate(4155%) - hue-rotate(6deg) contrast(119%); + filter: brightness(50%) saturate(100%) invert(10%) sepia(28%) + saturate(4155%) hue-rotate(6deg) contrast(119%); } .red { - filter: brightness(30%) saturate(100%) invert(10%) sepia(28%) saturate(4155%) - hue-rotate(346deg) contrast(119%); + filter: brightness(30%) saturate(100%) invert(10%) sepia(28%) + saturate(4155%) hue-rotate(346deg) contrast(119%); } .batteryGaugeContainer { - align-items: center; - display: flex; - flex-direction: column; - max-height: 90%; + align-items: center; + display: flex; + flex-direction: column; + max-height: 90%; } diff --git a/src/pages/operator/css/ButtonGrid.css b/src/pages/operator/css/ButtonGrid.css index 97742c87..e5e70e30 100644 --- a/src/pages/operator/css/ButtonGrid.css +++ b/src/pages/operator/css/ButtonGrid.css @@ -1,58 +1,58 @@ .button-grid { - flex: 2; - display: grid; - grid-template-columns: repeat(6, 1fr); - grid-template-rows: repeat(4, auto 1fr); - grid-template-areas: - "header0 header0 header0 header0 header0 header0" - ". b0 b1 b2 b3 ." - "header1 header1 header1 header1 header1 header1" - ". b4 b5 b6 b7 ." - "header2 header2 header2 header2 header2 header2" - "b8 b9 b10 b11 b12 b13" - "header3 header3 header3 header3 header3 header3" - ". . b14 b15 . ."; - - padding: 0.4rem; - position: relative; - z-index: 1; - border-radius: var(--radius); + flex: 2; + display: grid; + grid-template-columns: repeat(6, 1fr); + grid-template-rows: repeat(4, auto 1fr); + grid-template-areas: + "header0 header0 header0 header0 header0 header0" + ". b0 b1 b2 b3 ." + "header1 header1 header1 header1 header1 header1" + ". b4 b5 b6 b7 ." + "header2 header2 header2 header2 header2 header2" + "b8 b9 b10 b11 b12 b13" + "header3 header3 header3 header3 header3 header3" + ". . b14 b15 . ."; + + padding: 0.4rem; + position: relative; + z-index: 1; + border-radius: var(--radius); } .button-grid::after { - border-radius: var(--radius); + border-radius: var(--radius); } .button-grid p { - text-align: center; - margin: 1.5rem 0 0.5rem 0; + text-align: center; + margin: 1.5rem 0 0.5rem 0; } .button-grid p:first-of-type { - text-align: center; - margin-top: 0.5rem; + text-align: center; + margin-top: 0.5rem; } .button-grid button { - width: 90%; - height: 4rem; - justify-self: center; - align-self: center; + width: 90%; + height: 4rem; + justify-self: center; + align-self: center; } .button-grid button.active { - background-color: var(--btn-turquoise); + background-color: var(--btn-turquoise); } .button-grid button.collision { - background-color: orange; + background-color: orange; } .button-grid button.limit { - background-color: red; + background-color: red; } .button-grid-bkg-color { - grid-column: 1 / 7; - height: 5rem; + grid-column: 1 / 7; + height: 5rem; } diff --git a/src/pages/operator/css/ButtonPad.css b/src/pages/operator/css/ButtonPad.css index 3829a6f0..a2cd6874 100644 --- a/src/pages/operator/css/ButtonPad.css +++ b/src/pages/operator/css/ButtonPad.css @@ -1,117 +1,117 @@ /* Stand-alone button pad *****************************************************/ .button-pads { - /* Shared style */ - stroke-linecap: round; - stroke-linejoin: round; - cursor: pointer; - - /* Style for standalone version (not overlay */ - fill-opacity: 100%; - stroke-width: 6px; - stroke: var(--background-color); - fill: hsl(0, 0%, 31%); - flex: 1 1 0; - padding: 0.4rem; - max-height: 100%; - /* max-width: fit-content; */ - touch-action: none; - user-select: none; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + /* Shared style */ + stroke-linecap: round; + stroke-linejoin: round; + cursor: pointer; + + /* Style for standalone version (not overlay */ + fill-opacity: 100%; + stroke-width: 6px; + stroke: var(--background-color); + fill: hsl(0, 0%, 31%); + flex: 1 1 0; + padding: 0.4rem; + max-height: 100%; + /* max-width: fit-content; */ + touch-action: none; + user-select: none; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } .button-pads svg { - height: 100%; - width: 100%; + height: 100%; + width: 100%; } /* Overlay ********************************************************************/ .button-pads.overlay { - stroke-width: 3px; - fill: hsl(200, 50%, 60%); - fill-opacity: 0; - stroke: hsl(200, 0%, 60%); + stroke-width: 3px; + fill: hsl(200, 50%, 60%); + fill-opacity: 0; + stroke: hsl(200, 0%, 60%); - width: 100%; - height: 100%; - padding: 0; - margin: 0; + width: 100%; + height: 100%; + padding: 0; + margin: 0; } /* Settings for the buttons on the button pad *********************************/ /*When hovering over a child element of an svg*/ .button-pads path:hover { - fill-opacity: 30%; + fill-opacity: 30%; } @media (hover: none) { - .button-pads path.inactive:hover + image { - filter: none !important; - } + .button-pads path.inactive:hover + image { + filter: none !important; + } } .button-pads image { - pointer-events: none; + pointer-events: none; } .button-pads path.inactive:hover + image { - filter: brightness(50%) sepia(100%) saturate(10000%) hue-rotate(194deg); + filter: brightness(50%) sepia(100%) saturate(10000%) hue-rotate(194deg); } .button-pads path.active { - fill-opacity: 60%; - fill: var(--btn-turquoise); + fill-opacity: 60%; + fill: var(--btn-turquoise); } .button-pads path.collision { - fill: orange; - fill-opacity: 40%; + fill: orange; + fill-opacity: 40%; } .button-pads path.limit { - fill: red; - fill-opacity: 40%; + fill: red; + fill-opacity: 40%; } /* Disable hover actions */ .button-pads.customizing path { - pointer-events: none; + pointer-events: none; } .button-pads.selected { - opacity: 100%; - stroke: var(--selected-color); - opacity: 100%; - border: 1px solid var(--selected-color); - stroke-width: 5px; + opacity: 100%; + stroke: var(--selected-color); + opacity: 100%; + border: 1px solid var(--selected-color); + stroke-width: 5px; } .button-pad { - font-size: x-large; - flex: 1 1 0; - display: grid; - text-align: center; - max-height: 100%; - justify-items: center; + font-size: x-large; + flex: 1 1 0; + display: grid; + text-align: center; + max-height: 100%; + justify-items: center; } @media (max-width: 1300px) { - .title { - font-size: smaller; - margin: 0.5rem; - } + .title { + font-size: smaller; + margin: 0.5rem; + } } @media screen and (orientation: portrait) { - .button-pad { - width: 100%; - } + .button-pad { + width: 100%; + } } @media (max-width: 500px) { - .button-pads { - filter: drop-shadow(6px 7px 2px rgb(0 0 0 / 0.4)); - } + .button-pads { + filter: drop-shadow(6px 7px 2px rgb(0 0 0 / 0.4)); + } } diff --git a/src/pages/operator/css/CameraView.css b/src/pages/operator/css/CameraView.css index 822a5caa..df5f30f2 100644 --- a/src/pages/operator/css/CameraView.css +++ b/src/pages/operator/css/CameraView.css @@ -1,135 +1,135 @@ .video-container { - position: relative; - flex: 1 1 0; - display: grid; - justify-items: center; - padding: 0.4rem; - height: 100%; - grid-template-columns: auto; - grid-template-rows: 1fr auto minmax(15rem, 2fr); - object-fit: cover; - justify-content: center; - /* align-items: center; + position: relative; + flex: 1 1 0; + display: grid; + justify-items: center; + padding: 0.4rem; + height: 100%; + grid-template-columns: auto; + grid-template-rows: 1fr auto minmax(15rem, 2fr); + object-fit: cover; + justify-content: center; + /* align-items: center; flex-direction: column; */ } /* Overlays the button pad on top of the camera view*/ .video-overlay-container { - z-index: 1; - position: absolute; - width: 100%; - height: 100%; - box-sizing: border-box; - top: 0; - left: 0; + z-index: 1; + position: absolute; + width: 100%; + height: 100%; + box-sizing: border-box; + top: 0; + left: 0; } .video-overlay-container.realsense, .video-overlay-container.overhead { - z-index: 2; - position: absolute; - width: calc(100% - 102px); - height: calc(100% - 102px); - box-sizing: border-box; - top: 0; - left: 0; - left: 51px; - top: 51px; - display: flex; - align-items: center; + z-index: 2; + position: absolute; + width: calc(100% - 102px); + height: calc(100% - 102px); + box-sizing: border-box; + top: 0; + left: 0; + left: 51px; + top: 51px; + display: flex; + align-items: center; } /* The style for the plus icon overlay for click-to-pregrasp */ .realsense.material-icons { - color: rgba(255, 0, 0, 0.6); - position: absolute; - transform: translate(-50%, -50%); + color: rgba(255, 0, 0, 0.6); + position: absolute; + transform: translate(-50%, -50%); } .video-overlay-container.overhead.predictiveDisplay { - z-index: 2; - position: absolute; - width: 100%; - height: 100%; - box-sizing: border-box; - top: 0; - left: 0; - display: flex; - align-items: center; + z-index: 2; + position: absolute; + width: 100%; + height: 100%; + box-sizing: border-box; + top: 0; + left: 0; + display: flex; + align-items: center; } .video-overlay-container::after { - grid-row: 2/2; - grid-column: 1/1; + grid-row: 2/2; + grid-column: 1/1; } .video-area { - position: relative; - grid-row: 2/2; - width: 100%; - max-height: 100%; - max-width: fit-content; /* 100% */ - object-fit: cover; - display: inline-block; + position: relative; + grid-row: 2/2; + width: 100%; + max-height: 100%; + max-width: fit-content; /* 100% */ + object-fit: cover; + display: inline-block; } .video-canvas { - display: inline-block; - width: 100%; - height: auto; - object-fit: cover; + display: inline-block; + width: 100%; + height: auto; + object-fit: cover; } .video-canvas.constrainedHeight { - display: inline-block; - /* width: auto; */ - height: 100%; - object-fit: cover; + display: inline-block; + /* width: auto; */ + height: 100%; + object-fit: cover; } /* Don't display selected highlight on video canvas element */ .video-canvas.customizing::after { - content: none; + content: none; } .video-canvas.customizing { - filter: brightness(0.6); + filter: brightness(0.6); } .video-canvas.customizing.selected { - filter: none; + filter: none; } /* Under video buttons ********************************************************/ .under-video-area { - grid-row: 3; - grid-column: 1; - /* background: blue; */ - /* display: grid; */ - /* flex-wrap: wrap; */ - align-content: flex-start; - padding-top: 0.5rem; - width: 100%; - object-fit: cover; - /* justify-content: center; */ - align-items: center; - overflow-y: auto; - overflow-x: hidden; + grid-row: 3; + grid-column: 1; + /* background: blue; */ + /* display: grid; */ + /* flex-wrap: wrap; */ + align-content: flex-start; + padding-top: 0.5rem; + width: 100%; + object-fit: cover; + /* justify-content: center; */ + align-items: center; + overflow-y: auto; + overflow-x: hidden; } .under-video-area button { - /* height: 30%; */ - margin: 0.2rem 0rem 0.2rem 0rem; - /* flex: 1 0 auto; */ - align-items: center; - width: 99%; + /* height: 30%; */ + margin: 0.2rem 0rem 0.2rem 0rem; + /* flex: 1 0 auto; */ + align-items: center; + width: 99%; } /* Realsense pan-tilt controls ************************************************/ .realsense-pan-tilt-grid { - width: 100%; - /* max-width: fit-content; + width: 100%; + /* max-width: fit-content; height: auto; grid-row: 2/2; grid-column: 1/1; @@ -142,124 +142,124 @@ } .realsense-pan-tilt-grid.constrainedHeight { - height: 100%; - /* width: auto; */ - /* grid-template-columns: var(--pan-tilt-button-size) min-content var(--pan-tilt-button-size); + height: 100%; + /* width: auto; */ + /* grid-template-columns: var(--pan-tilt-button-size) min-content var(--pan-tilt-button-size); grid-template-rows: var(--pan-tilt-button-size) fit-content var(--pan-tilt-button-size); */ - justify-content: center; - object-fit: cover; - z-index: 2; - position: absolute; - display: block; + justify-content: center; + object-fit: cover; + z-index: 2; + position: absolute; + display: block; } .realsense-pan-tilt-grid button { - padding: 0px; + padding: 0px; } .realsense-pan-tilt-grid button .material-icons { - margin: 0; - font-size: xxx-large; - background-color: whitesmoke; - opacity: 40%; - border-radius: 60px; + margin: 0; + font-size: xxx-large; + background-color: whitesmoke; + opacity: 40%; + border-radius: 60px; } .realsense-pan-tilt-grid .up { - border-radius: var(--btn-brdr-radius) var(--btn-brdr-radius) 0 0; - z-index: 2; - width: 100%; - position: absolute; - background: transparent; - box-shadow: none; + border-radius: var(--btn-brdr-radius) var(--btn-brdr-radius) 0 0; + z-index: 2; + width: 100%; + position: absolute; + background: transparent; + box-shadow: none; } .realsense-pan-tilt-grid .down { - border-radius: 0 0 var(--btn-brdr-radius) var(--btn-brdr-radius); - z-index: 2; - width: 100%; - bottom: 0; - left: 0; - position: absolute; - background: transparent; - box-shadow: none; + border-radius: 0 0 var(--btn-brdr-radius) var(--btn-brdr-radius); + z-index: 2; + width: 100%; + bottom: 0; + left: 0; + position: absolute; + background: transparent; + box-shadow: none; } .realsense-pan-tilt-grid .left { - border-radius: var(--btn-brdr-radius) 0 0 var(--btn-brdr-radius); - z-index: 2; - height: 100%; - position: absolute; - background: transparent; - box-shadow: none; + border-radius: var(--btn-brdr-radius) 0 0 var(--btn-brdr-radius); + z-index: 2; + height: 100%; + position: absolute; + background: transparent; + box-shadow: none; } .realsense-pan-tilt-grid .right { - border-radius: 0 var(--btn-brdr-radius) var(--btn-brdr-radius) 0; - z-index: 2; - position: absolute; - right: 0; - height: 100%; - background: transparent; - box-shadow: none; + border-radius: 0 var(--btn-brdr-radius) var(--btn-brdr-radius) 0; + z-index: 2; + position: absolute; + right: 0; + height: 100%; + background: transparent; + box-shadow: none; } /* Context menu popup *********************************************************/ .video-context-menu { - list-style-type: none; - position: absolute; - background-color: var(--background-color); - /* border: var(--btn-brdr); */ - margin: 0; - padding: 0; - white-space: nowrap; - - --padding: 1rem; - - padding-top: var(--padding); - grid-row: 2/2; - z-index: 4; + list-style-type: none; + position: absolute; + background-color: var(--background-color); + /* border: var(--btn-brdr); */ + margin: 0; + padding: 0; + white-space: nowrap; + + --padding: 1rem; + + padding-top: var(--padding); + grid-row: 2/2; + z-index: 4; } .video-context-menu li { - padding: var(--padding); - cursor: pointer; - background-color: inherit; + padding: var(--padding); + cursor: pointer; + background-color: inherit; } .video-context-menu li:hover { - filter: brightness(90%); + filter: brightness(90%); } .video-context-menu::before { - content: attr(aria-label); - font-weight: bold; - padding: var(--padding); + content: attr(aria-label); + font-weight: bold; + padding: var(--padding); } .title { - font-size: x-large; - align-self: flex-end; - text-align: center; - margin: 10px; + font-size: x-large; + align-self: flex-end; + text-align: center; + margin: 10px; } @media screen and (orientation: portrait) and (max-device-width: 900px) { - .video-container { - grid-template-rows: 1fr auto minmax(3rem, 2fr); - } + .video-container { + grid-template-rows: 1fr auto minmax(3rem, 2fr); + } } @media screen and (orientation: landscape) and (max-device-width: 900px) { - .video-container { - grid-template-rows: auto; - } + .video-container { + grid-template-rows: auto; + } - .realsense-pan-tilt-grid button .material-icons { - font-size: larger; - } + .realsense-pan-tilt-grid button .material-icons { + font-size: larger; + } - .title { - font-size: smaller; - } + .title { + font-size: smaller; + } } diff --git a/src/pages/operator/css/CustomizeButton.css b/src/pages/operator/css/CustomizeButton.css index 3b83b732..09be3cdb 100644 --- a/src/pages/operator/css/CustomizeButton.css +++ b/src/pages/operator/css/CustomizeButton.css @@ -1,16 +1,16 @@ #customize-button { - display: flex; - align-items: center; - justify-content: center; - width: var(--header-btn-width); + display: flex; + align-items: center; + justify-content: center; + width: var(--header-btn-width); } #customize-button span { - margin-right: 2rem; + margin-right: 2rem; } @media (max-width: 900px) { - #customize-button { - width: var(--btn-header-width-med); - } + #customize-button { + width: var(--btn-header-width-med); + } } diff --git a/src/pages/operator/css/DropZone.css b/src/pages/operator/css/DropZone.css index 30dbcbee..b47d72bf 100644 --- a/src/pages/operator/css/DropZone.css +++ b/src/pages/operator/css/DropZone.css @@ -1,60 +1,60 @@ .drop-zone { - background-color: hsl(0, 0%, 90%); - border: 0.2rem dashed gray; - border-radius: 10px; - opacity: 100%; - flex: 0 0 2rem; - margin: 1rem 0.5rem; - cursor: pointer; - text-align: center; - transition-property: opacity, flex, width; - transition-duration: 0.4s; - transition-timing-function: ease-out; + background-color: hsl(0, 0%, 90%); + border: 0.2rem dashed gray; + border-radius: 10px; + opacity: 100%; + flex: 0 0 2rem; + margin: 1rem 0.5rem; + cursor: pointer; + text-align: center; + transition-property: opacity, flex, width; + transition-duration: 0.4s; + transition-timing-function: ease-out; } .drop-zone.standard { - height: 90%; + height: 90%; } /* Drop zone in layout or tab content*/ .drop-zone.standard, .drop-zone.overlay { - display: flex; - align-items: center; - justify-content: center; - width: -webkit-fill-available; + display: flex; + align-items: center; + justify-content: center; + width: -webkit-fill-available; } /* Dropzone is a tab in a tabs component header */ .drop-zone.material-icons.tab { - margin: 0; - width: 5rem; - padding-top: 10px; + margin: 0; + width: 5rem; + padding-top: 10px; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - /* border-bottom: none; */ + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + /* border-bottom: none; */ } /* Dropzone is an overlay in a video stream*/ .drop-zone.overlay { - margin: 0; - width: 100%; - height: 100%; - opacity: 60%; - flex-grow: 1; + margin: 0; + width: 100%; + height: 100%; + opacity: 60%; + flex-grow: 1; } .drop-zone[hidden] { - flex: 0; - width: 0; - opacity: 0; - margin: 0; - padding: 0; - border: none; - visibility: hidden; + flex: 0; + width: 0; + opacity: 0; + margin: 0; + padding: 0; + border: none; + visibility: hidden; } .drop-zone:hover { - background-color: hsl(0, 0%, 50%); + background-color: hsl(0, 0%, 50%); } diff --git a/src/pages/operator/css/LayoutArea.css b/src/pages/operator/css/LayoutArea.css index 6f68b847..da8debc9 100644 --- a/src/pages/operator/css/LayoutArea.css +++ b/src/pages/operator/css/LayoutArea.css @@ -1,38 +1,38 @@ #layout-area { - /* padding: var(--screen-padding); + /* padding: var(--screen-padding); flex: 1 1 0; */ - padding: var(--screen-padding); - flex-direction: column; - height: auto; + padding: var(--screen-padding); + flex-direction: column; + height: auto; } /* Remove margin for elements at edges of the layout area */ #layout-area > *:first-of-type { - margin-left: 0; + margin-left: 0; } #layout-area > *:last-of-type { - margin-right: 0; + margin-right: 0; } #layout-area, .tabs-content { - display: flex; - justify-content: space-evenly; - align-items: center; + display: flex; + justify-content: space-evenly; + align-items: center; } @media screen and (orientation: portrait) and (max-device-width: 900px) { - #layout-area, - .tabs-content { - flex-direction: column; - padding: 1rem; - grid-gap: 0.3rem; - } + #layout-area, + .tabs-content { + flex-direction: column; + padding: 1rem; + grid-gap: 0.3rem; + } } @media screen and (orientation: landscape) and (max-device-width: 900px) { - #layout-area, - .tabs-content { - overflow: scroll; - } + #layout-area, + .tabs-content { + overflow: scroll; + } } diff --git a/src/pages/operator/css/Map.css b/src/pages/operator/css/Map.css index dbf816d5..b778c8d6 100644 --- a/src/pages/operator/css/Map.css +++ b/src/pages/operator/css/Map.css @@ -1,153 +1,153 @@ .map-container, .mobile-map-container { - position: relative; - /* flex: 1 1 0; */ - display: grid; - justify-items: center; - padding: 0.4rem; - max-height: 100%; - grid-template-columns: auto; - /* grid-template-rows: 1fr auto minmax(9rem, 1fr); */ - object-fit: cover; - justify-content: center; - /* align-items: center; + position: relative; + /* flex: 1 1 0; */ + display: grid; + justify-items: center; + padding: 0.4rem; + max-height: 100%; + grid-template-columns: auto; + /* grid-template-rows: 1fr auto minmax(9rem, 1fr); */ + object-fit: cover; + justify-content: center; + /* align-items: center; flex-direction: column; */ - z-index: 1; + z-index: 1; } .map-container { - flex: 1 1 0; - /* display: flex; + flex: 1 1 0; + /* display: flex; flex-direction: column; */ - /* overflow: hidden; */ + /* overflow: hidden; */ } .map-title { - font-size: x-large; - text-align: center; - margin: 10px; + font-size: x-large; + text-align: center; + margin: 10px; } .map { - align-self: center; - width: auto; - height: 100%; - z-index: 1; + align-self: center; + width: auto; + height: 100%; + z-index: 1; } .map.constrainedHeight { - width: auto; - height: 100%; + width: auto; + height: 100%; } .mapCanvas { - max-width: 100%; - max-height: 100%; + max-width: 100%; + max-height: 100%; } .dropdown em { - color: #6a6a6a; - margin-right: 1rem; + color: #6a6a6a; + margin-right: 1rem; } .mobile { - padding: var(--btn-padding); - /* font-size: 30px; */ - flex: auto; + padding: var(--btn-padding); + /* font-size: 30px; */ + flex: auto; } .mobile-map-save-btn { - width: 54%; - border-radius: 13px; - border: 5px solid whitesmoke; - padding: 10px; - margin: 0.5rem; - vertical-align: middle; - display: flex; - justify-content: space-evenly; - align-items: center; + width: 54%; + border-radius: 13px; + border: 5px solid whitesmoke; + padding: 10px; + margin: 0.5rem; + vertical-align: middle; + display: flex; + justify-content: space-evenly; + align-items: center; } .map-save-btn { - width: 100%; - border-radius: 13px; - padding: 8px; - vertical-align: middle; - display: flex; - justify-content: center; - align-items: center; - margin-bottom: 0.5rem; - text-align: center; + width: 100%; + border-radius: 13px; + padding: 8px; + vertical-align: middle; + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 0.5rem; + text-align: center; } .mobile-map-play-btn { - width: 32%; - border-radius: 13px; - border: 5px solid whitesmoke; - padding: 10px; - margin: 0.5rem; - text-align: center; - background: #06c7e1; - vertical-align: middle; - display: flex; - justify-content: space-evenly; - align-items: center; + width: 32%; + border-radius: 13px; + border: 5px solid whitesmoke; + padding: 10px; + margin: 0.5rem; + text-align: center; + background: #06c7e1; + vertical-align: middle; + display: flex; + justify-content: space-evenly; + align-items: center; } .map-play-btn { - width: 100%; - border-radius: 13px; - padding: 8px; - text-align: center; - background: var(--selected-color); - vertical-align: middle; - display: flex; - align-items: center; - margin-top: 0.5rem; - justify-content: center; - margin-bottom: 0.5rem; + width: 100%; + border-radius: 13px; + padding: 8px; + text-align: center; + background: var(--selected-color); + vertical-align: middle; + display: flex; + align-items: center; + margin-top: 0.5rem; + justify-content: center; + margin-bottom: 0.5rem; } .mobile-map-cancel-btn { - width: 32%; - border-radius: 13px; - border: 5px solid whitesmoke; - padding: 10px; - margin: 0.5rem; - text-align: center; - background: #cd0b0b; - vertical-align: middle; - display: flex; - justify-content: space-evenly; - align-items: center; - color: white; + width: 32%; + border-radius: 13px; + border: 5px solid whitesmoke; + padding: 10px; + margin: 0.5rem; + text-align: center; + background: #cd0b0b; + vertical-align: middle; + display: flex; + justify-content: space-evenly; + align-items: center; + color: white; } .map-cancel-btn { - width: 100%; - border-radius: 13px; - padding: 8px; - text-align: center; - vertical-align: middle; - display: flex; - align-items: center; - margin-top: 0.5rem; - justify-content: center; - margin-bottom: 0.5rem; - background: #cd0b0b; - display: flex; - color: white; + width: 100%; + border-radius: 13px; + padding: 8px; + text-align: center; + vertical-align: middle; + display: flex; + align-items: center; + margin-top: 0.5rem; + justify-content: center; + margin-bottom: 0.5rem; + background: #cd0b0b; + display: flex; + color: white; } .map-fn-btns { - display: grid; - font-size: 18px; - margin-top: 1rem; - margin-bottom: 0.5rem; - width: 100%; + display: grid; + font-size: 18px; + margin-top: 1rem; + margin-bottom: 0.5rem; + width: 100%; } .map-fn-btns-mobile { - display: flex; - /* font-size: 45px; */ + display: flex; + /* font-size: 45px; */ } diff --git a/src/pages/operator/css/MobileOperator.css b/src/pages/operator/css/MobileOperator.css index 0cd8efe8..0b288691 100644 --- a/src/pages/operator/css/MobileOperator.css +++ b/src/pages/operator/css/MobileOperator.css @@ -1,224 +1,224 @@ #mobile-operator { - height: 100%; - touch-action: none; - /* display: grid; */ - grid-template-rows: auto auto 1fr; - grid-template-columns: 1fr auto; - background-color: #7f7f7f; + height: 100%; + touch-action: none; + /* display: grid; */ + grid-template-rows: auto auto 1fr; + grid-template-columns: 1fr auto; + background-color: #7f7f7f; } .switch-camera { - z-index: 5; - position: absolute; - border-radius: 0px; - opacity: 0.5; - font-size: 2rem; - padding: 0; - float: right; - text-align: right; - margin-left: 85%; - color: black; + z-index: 5; + position: absolute; + border-radius: 0px; + opacity: 0.5; + font-size: 2rem; + padding: 0; + float: right; + text-align: right; + margin-left: 85%; + color: black; } .switch-camera .material-icons { - color: black; + color: black; } .record { - z-index: 5; - position: absolute; - border-radius: 0px; - opacity: 0.65; - /* font-size: 50px; */ - text-align: right; - display: flex; - padding: 0.5rem; - align-items: center; - color: black; + z-index: 5; + position: absolute; + border-radius: 0px; + opacity: 0.65; + /* font-size: 50px; */ + text-align: right; + display: flex; + padding: 0.5rem; + align-items: center; + color: black; } .depth-sensing { - float: right; - z-index: 5; - position: absolute; - border-radius: 0px; - opacity: 0.5; - /* font-size: 50px; */ - text-align: right; - display: flex; - align-items: center; - /* width: 20rem; */ - /* margin-top: 85%; */ - /* margin-left: 68%; */ - background: whitesmoke; + float: right; + z-index: 5; + position: absolute; + border-radius: 0px; + opacity: 0.5; + /* font-size: 50px; */ + text-align: right; + display: flex; + align-items: center; + /* width: 20rem; */ + /* margin-top: 85%; */ + /* margin-left: 68%; */ + background: whitesmoke; } .pill { - border-radius: 1.5rem; + border-radius: 1.5rem; } .active-color { - color: white; - background-color: #084298; + color: white; + background-color: #084298; } #mobile-operator-body { - display: flex; - flex-direction: column; - height: 100%; - /* flex: 1 1 0; + display: flex; + flex-direction: column; + height: 100%; + /* flex: 1 1 0; grid-column: 1/1; */ - /* grid-row: 3; */ + /* grid-row: 3; */ } .mobile-alert { - position: absolute; - width: 100%; - z-index: 6; + position: absolute; + width: 100%; + z-index: 6; } /** https://stackoverflow.com/a/40989121 **/ .loader { - position: absolute; - top: calc(50% - 5em); - left: calc(50% - 5em); - width: 11em; - height: 11em; - border: 1.1em solid rgba(0, 0, 0, 0.2); - border-left: 1.1em solid #000000; - border-radius: 50%; - animation: load 1s infinite linear; + position: absolute; + top: calc(50% - 5em); + left: calc(50% - 5em); + width: 11em; + height: 11em; + border: 1.1em solid rgba(0, 0, 0, 0.2); + border-left: 1.1em solid #000000; + border-radius: 50%; + animation: load 1s infinite linear; } .loading-text { - position: absolute; - top: calc(50% - 1em); - left: calc(50% - 2em); - font-size: large; - z-index: 4; + position: absolute; + top: calc(50% - 1em); + left: calc(50% - 2em); + font-size: large; + z-index: 4; } .control-modes { - touch-action: none; - font-size: 3.5rem; - justify-content: center; - display: flex; - padding-top: 20px; - gap: 15px; - padding-bottom: 50px; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + touch-action: none; + font-size: 3.5rem; + justify-content: center; + display: flex; + padding-top: 20px; + gap: 15px; + padding-bottom: 50px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } @keyframes load { - 0% { - transform: rotate(0deg); - } + 0% { + transform: rotate(0deg); + } - 100% { - transform: rotate(360deg); - } + 100% { + transform: rotate(360deg); + } } @media (max-width: 900px) { - #operator-header .dropdown { - width: var(--header-btn-width-med); - } + #operator-header .dropdown { + width: var(--header-btn-width-med); + } - #operator-header > *, - #operator-header button { - height: 3rem; - } + #operator-header > *, + #operator-header button { + height: 3rem; + } - .operator-voice, - .operator-pose-library, - .operator-pose-recorder, - .operator-aruco-markers { - width: 30rem; - height: 5rem; - } + .operator-voice, + .operator-pose-library, + .operator-pose-recorder, + .operator-aruco-markers { + width: 30rem; + height: 5rem; + } } .slider { - height: 15px; - touch-action: none; - pointer-events: all; + height: 15px; + touch-action: none; + pointer-events: all; } .slider-container { - display: flex; - align-items: baseline; - justify-content: space-around; - padding-top: 16px; + display: flex; + align-items: baseline; + justify-content: space-around; + padding-top: 16px; } .slider { - -webkit-appearance: none; - width: 70%; - /* height: 30px; */ - border-radius: 19px; - background: #d3d3d3; - outline: none; - opacity: 0.7; - -webkit-transition: 0.2s; - transition: opacity 0.2s; + -webkit-appearance: none; + width: 70%; + /* height: 30px; */ + border-radius: 19px; + background: #d3d3d3; + outline: none; + opacity: 0.7; + -webkit-transition: 0.2s; + transition: opacity 0.2s; } .slider::-webkit-slider-thumb { - -webkit-appearance: none; - appearance: none; - width: 25px; - height: 25px; - border-radius: 50%; - background: #4caf50; - cursor: pointer; + -webkit-appearance: none; + appearance: none; + width: 25px; + height: 25px; + border-radius: 50%; + background: #4caf50; + cursor: pointer; } .label { - font-size: 20px; - padding-bottom: 10px; + font-size: 20px; + padding-bottom: 10px; } .map, .controls { - display: contents; + display: contents; } .map.hideMap, .controls.hideControls { - display: none; + display: none; } .record-circle { - width: 20px; - height: 20px; - background-color: #bd1919; - border-radius: 50%; - margin: 0.5rem; + width: 20px; + height: 20px; + background-color: #bd1919; + border-radius: 50%; + margin: 0.5rem; } /** https://codepen.io/vram1980/pen/oNvWdO */ .recording { - border: 3px solid #bd1919; - -webkit-border-radius: 30px; - height: 30px; - width: 30px; - position: absolute; - left: 11px; - top: 11px; - -webkit-animation: pulsate 1s ease-out; - -webkit-animation-iteration-count: infinite; - opacity: 0; + border: 3px solid #bd1919; + -webkit-border-radius: 30px; + height: 30px; + width: 30px; + position: absolute; + left: 11px; + top: 11px; + -webkit-animation: pulsate 1s ease-out; + -webkit-animation-iteration-count: infinite; + opacity: 0; } @-webkit-keyframes pulsate { - 0% { - -webkit-transform: scale(0.1, 0.1); - opacity: 0; - } - 50% { - opacity: 1; - } - 100% { - -webkit-transform: scale(1.2, 1.2); - opacity: 0; - } + 0% { + -webkit-transform: scale(0.1, 0.1); + opacity: 0; + } + 50% { + opacity: 1; + } + 100% { + -webkit-transform: scale(1.2, 1.2); + opacity: 0; + } } diff --git a/src/pages/operator/css/MovementRecorder.css b/src/pages/operator/css/MovementRecorder.css index 4073246a..0d9d8cdc 100644 --- a/src/pages/operator/css/MovementRecorder.css +++ b/src/pages/operator/css/MovementRecorder.css @@ -1,8 +1,8 @@ #movement-recorder-container { - display: flex; - gap: 15px; - align-items: center; - justify-content: center; + display: flex; + gap: 15px; + align-items: center; + justify-content: center; } /* The below buttons' CSS likely gets overridden by the TextToSpeech CSS @@ -11,49 +11,49 @@ * one of the components. */ .play-btn { - background-color: var(--selected-color); - display: flex; + background-color: var(--selected-color); + display: flex; } .save-btn { - background-color: var(--btn-turquoise); - display: flex; + background-color: var(--btn-turquoise); + display: flex; } .delete-btn { - background-color: var(--btn-red); - display: flex; + background-color: var(--btn-red); + display: flex; } @media (max-width: 1300px) { - #movement-recorder-container { - font-size: smaller; - } + #movement-recorder-container { + font-size: smaller; + } } .mobile-movement-save-btn { - border-radius: 13px; - border: 5px solid whitesmoke; - font-size: 25px; - padding: 10px; - margin: 1rem; - text-align: center; - background: #06c7e1; - vertical-align: middle; - display: flex; - justify-content: center; + border-radius: 13px; + border: 5px solid whitesmoke; + font-size: 25px; + padding: 10px; + margin: 1rem; + text-align: center; + background: #06c7e1; + vertical-align: middle; + display: flex; + justify-content: center; } .mobile-movement-play-btn { - /* width: 97%; */ - border-radius: 13px; - border: 5px solid whitesmoke; - font-size: 20px; - padding: 10px; - margin: 0.5rem; - text-align: center; - background: #06c7e1; - vertical-align: middle; - display: flex; - justify-content: center; + /* width: 97%; */ + border-radius: 13px; + border: 5px solid whitesmoke; + font-size: 20px; + padding: 10px; + margin: 0.5rem; + text-align: center; + background: #06c7e1; + vertical-align: middle; + display: flex; + justify-content: center; } diff --git a/src/pages/operator/css/Operator.css b/src/pages/operator/css/Operator.css index 3222a7e0..0b7a550f 100644 --- a/src/pages/operator/css/Operator.css +++ b/src/pages/operator/css/Operator.css @@ -1,79 +1,79 @@ #operator { - height: 100%; - display: grid; - grid-template-rows: auto auto 1fr; - grid-template-columns: 1fr auto; + height: 100%; + display: grid; + grid-template-rows: auto auto 1fr; + grid-template-columns: 1fr auto; - --screen-padding: 1rem; + --screen-padding: 1rem; } #operator-header { - background-color: var(--gray-bg); - width: 100%; - box-sizing: border-box; - padding: var(--screen-padding); - display: flex; - align-items: center; - justify-content: space-between; - grid-row: 1; - grid-column: 1/3; - --header-btn-width: 11rem; - --header-btn-width-med: 7rem; + background-color: var(--gray-bg); + width: 100%; + box-sizing: border-box; + padding: var(--screen-padding); + display: flex; + align-items: center; + justify-content: space-between; + grid-row: 1; + grid-column: 1/3; + --header-btn-width: 11rem; + --header-btn-width-med: 7rem; } .operator-collision-alerts { - width: 100%; - /* padding: 0.5rem 1rem 0 1rem; */ - position: absolute; + width: 100%; + /* padding: 0.5rem 1rem 0 1rem; */ + position: absolute; } .operator-alert { - font-size: 1.5rem; + font-size: 1.5rem; } .operator-collision-alerts .operator-alert { - animation: fade-out 1s; + animation: fade-out 1s; } .operator-collision-alerts .operator-alert.fadeOut { - display: none; - animation: fade-out 2s; - opacity: 0; + display: none; + animation: fade-out 2s; + opacity: 0; } .operator-collision-alerts .operator-alert.fadeIn { - display: block; - animation: fade-in 0.5s; + display: block; + animation: fade-in 0.5s; } @keyframes fade-in { - from { - opacity: 0; - } + from { + opacity: 0; + } - to { - opacity: 1; - } + to { + opacity: 1; + } } @keyframes fade-out { - from { - opacity: 1; - } + from { + opacity: 1; + } - to { - opacity: 0; - } + to { + opacity: 0; + } } /* Make all the components in the header fill the available height */ #operator-header > *, #operator-header button { - height: 100%; + height: 100%; } #operator-header .dropdown { - width: var(--header-btn-width); + width: var(--header-btn-width); } .operator-voice, @@ -81,34 +81,34 @@ .operator-pose-recorder, .operator-text-to-speech, .operator-aruco-markers { - background-color: whitesmoke; - box-shadow: var(--shadow); - height: 6rem; - width: 50rem; - display: inline-grid; - align-items: center; - justify-content: center; - /* justify-self: center; */ - align-self: center; - border-radius: 200px; - /* margin-top: 10px; */ - /* grid-row: 2/2; + background-color: whitesmoke; + box-shadow: var(--shadow); + height: 6rem; + width: 50rem; + display: inline-grid; + align-items: center; + justify-content: center; + /* justify-self: center; */ + align-self: center; + border-radius: 200px; + /* margin-top: 10px; */ + /* grid-row: 2/2; grid-column: 1/1; */ - transition: all 0.2s ease-out; - font-size: large; + transition: all 0.2s ease-out; + font-size: large; } .operator-pose-library.hideLabels, .operator-pose-recorder.hideLabels { - width: 32rem; + width: 32rem; } .operator-aruco-markers.hideLabels { - width: 43rem; + width: 43rem; } .operator-aruco-markers { - width: 66rem; + width: 66rem; } .operator-voice[hidden], @@ -116,82 +116,82 @@ .operator-pose-recorder[hidden], .operator-text-to-speech[hidden], .operator-aruco-markers[hidden] { - display: none; + display: none; } #operator-global-controls { - display: flex; - flex-wrap: wrap; - row-gap: 10px; - column-gap: 10px; - justify-content: center; + display: flex; + flex-wrap: wrap; + row-gap: 10px; + column-gap: 10px; + justify-content: center; } #operator-body { - display: flex; - justify-content: center; - flex-flow: row; - flex: 1 1 0; - grid-column: 1/1; - grid-row: 3; + display: flex; + justify-content: center; + flex-flow: row; + flex: 1 1 0; + grid-column: 1/1; + grid-row: 3; } /** https://stackoverflow.com/a/40989121 **/ .loader { - position: absolute; - top: calc(50% - 5em); - left: calc(50% - 5em); - width: 11em; - height: 11em; - border: 1.1em solid rgba(0, 0, 0, 0.2); - border-left: 1.1em solid #000000; - border-radius: 50%; - animation: load 1s infinite linear; - background-color: white; - z-index: 4; + position: absolute; + top: calc(50% - 5em); + left: calc(50% - 5em); + width: 11em; + height: 11em; + border: 1.1em solid rgba(0, 0, 0, 0.2); + border-left: 1.1em solid #000000; + border-radius: 50%; + animation: load 1s infinite linear; + background-color: white; + z-index: 4; } .loading-text { - position: absolute; - top: calc(50% - 1em); - left: calc(50% - 2em); - font-size: large; - z-index: 4; + position: absolute; + top: calc(50% - 1em); + left: calc(50% - 2em); + font-size: large; + z-index: 4; } .reconnecting-text { - position: absolute; - top: calc(50% - 1em); - left: calc(50% - 3em); - font-size: large; - z-index: 5; + position: absolute; + top: calc(50% - 1em); + left: calc(50% - 3em); + font-size: large; + z-index: 5; } @keyframes load { - 0% { - transform: rotate(0deg); - } + 0% { + transform: rotate(0deg); + } - 100% { - transform: rotate(360deg); - } + 100% { + transform: rotate(360deg); + } } @media (max-width: 900px) { - #operator-header .dropdown { - width: var(--header-btn-width-med); - } - - #operator-header > *, - #operator-header button { - height: 3rem; - } - - .operator-voice, - .operator-pose-library, - .operator-pose-recorder, - .operator-aruco-markers { - width: 30rem; - height: 5rem; - } + #operator-header .dropdown { + width: var(--header-btn-width-med); + } + + #operator-header > *, + #operator-header button { + height: 3rem; + } + + .operator-voice, + .operator-pose-library, + .operator-pose-recorder, + .operator-aruco-markers { + width: 30rem; + height: 5rem; + } } diff --git a/src/pages/operator/css/Panel.css b/src/pages/operator/css/Panel.css index 531af9c4..ca9c6030 100644 --- a/src/pages/operator/css/Panel.css +++ b/src/pages/operator/css/Panel.css @@ -1,83 +1,83 @@ .tabs-component { - height: 100%; - display: flex; - flex-direction: column; - flex: 1 1 0; - /* margin: 0 0.5rem; */ - margin-top: 0.5rem; /* new */ - width: 100%; /* new */ - box-shadow: var(--shadow); - position: relative; + height: 100%; + display: flex; + flex-direction: column; + flex: 1 1 0; + /* margin: 0 0.5rem; */ + margin-top: 0.5rem; /* new */ + width: 100%; /* new */ + box-shadow: var(--shadow); + position: relative; - --radius: 0.3rem; - border-radius: var(--radius) var(--radius) 0px 0px; + --radius: 0.3rem; + border-radius: var(--radius) var(--radius) 0px 0px; } .tabs-component.customizing.selected::after { - background-color: var(--selected-color); + background-color: var(--selected-color); } .tabs-content { - border: 3px solid var(--btn-blue); - flex: 1 1 0; - background-color: var(--background-color); + border: 3px solid var(--btn-blue); + flex: 1 1 0; + background-color: var(--background-color); } /* Header *********************************************************************/ .tabs-header { - display: flex; - flex-wrap: wrap; - overflow: hidden; - border-radius: var(--radius) var(--radius) 0px 0px; + display: flex; + flex-wrap: wrap; + overflow: hidden; + border-radius: var(--radius) var(--radius) 0px 0px; } /* Apply to all the tabs in the header */ .tabs-header > * { - flex: 1 0 auto; - background-color: var(--tab-inactive); - border-radius: var(--radius) var(--radius) 0px 0px; + flex: 1 0 auto; + background-color: var(--tab-inactive); + border-radius: var(--radius) var(--radius) 0px 0px; } /* Format tabs with icons */ .tabs-header > .material-icons { - vertical-align: bottom; - padding-top: 3px; - padding-bottom: 3px; + vertical-align: bottom; + padding-top: 3px; + padding-bottom: 3px; } .tab-button { - border: none; - font-size: 1.5rem; - z-index: 0; + border: none; + font-size: 1.5rem; + z-index: 0; } .tab-button.active { - background-color: var(--btn-blue); - color: var(--font-white); - /* z-index: 2; */ - box-shadow: 0px 2px 2px 2px rgb(112 112 112 / 47%); + background-color: var(--btn-blue); + color: var(--font-white); + /* z-index: 2; */ + box-shadow: 0px 2px 2px 2px rgb(112 112 112 / 47%); } .tab-button.selected { - box-shadow: 0 0 0.2rem 0.2rem var(--selected-color); + box-shadow: 0 0 0.2rem 0.2rem var(--selected-color); } .add-tab:hover { - background-color: var(--btn-turquoise); - color: white; + background-color: var(--btn-turquoise); + color: white; } /* Popup for adding a new tab *************************************************/ @media (max-width: 900px) { - .tab-button { - font-size: medium; - } + .tab-button { + font-size: medium; + } } @media screen and (orientation: portrait) and (max-device-width: 900px) { - .tabs-component { - width: 100%; - } + .tabs-component { + width: 100%; + } } diff --git a/src/pages/operator/css/PoseLibrary.css b/src/pages/operator/css/PoseLibrary.css index 7c9251d4..011439cd 100644 --- a/src/pages/operator/css/PoseLibrary.css +++ b/src/pages/operator/css/PoseLibrary.css @@ -1,27 +1,27 @@ #pose-library-container { - display: flex; - gap: 15px; - align-items: center; - justify-content: center; + display: flex; + gap: 15px; + align-items: center; + justify-content: center; } .play-btn { - background-color: var(--selected-color); - display: flex; + background-color: var(--selected-color); + display: flex; } .save-btn { - background-color: var(--btn-turquoise); - display: flex; + background-color: var(--btn-turquoise); + display: flex; } .delete-btn { - background-color: var(--btn-red); - display: flex; + background-color: var(--btn-red); + display: flex; } @media (max-width: 1300px) { - #pose-library-container { - font-size: smaller; - } + #pose-library-container { + font-size: smaller; + } } diff --git a/src/pages/operator/css/PredictiveDisplay.css b/src/pages/operator/css/PredictiveDisplay.css index 1fbd5735..54c745fc 100644 --- a/src/pages/operator/css/PredictiveDisplay.css +++ b/src/pages/operator/css/PredictiveDisplay.css @@ -1,21 +1,21 @@ .predictive-display { - width: 100%; - height: 100%; - stroke: gray; - cursor: crosshair; - fill: none; + width: 100%; + height: 100%; + stroke: gray; + cursor: crosshair; + fill: none; } .predictive-display.customizing { - cursor: default; + cursor: default; } .predictive-display path { - stroke-width: 8; - stroke: var(--path-blue); - stroke-linecap: round; + stroke-width: 8; + stroke: var(--path-blue); + stroke-linecap: round; } .predictive-display.moving path { - stroke: red; + stroke: red; } diff --git a/src/pages/operator/css/RadioGroup.css b/src/pages/operator/css/RadioGroup.css index 14425df5..37bb132c 100644 --- a/src/pages/operator/css/RadioGroup.css +++ b/src/pages/operator/css/RadioGroup.css @@ -1,69 +1,69 @@ .radio-btn-mobile { - font-size: 20px; - border-radius: 13px; - background-color: whitesmoke; - margin: 0.5rem; - border: 3px solid whitesmoke; - filter: drop-shadow(6px 7px 2px rgb(0 0 0 / 0.4)); + font-size: 20px; + border-radius: 13px; + background-color: whitesmoke; + margin: 0.5rem; + border: 3px solid whitesmoke; + filter: drop-shadow(6px 7px 2px rgb(0 0 0 / 0.4)); } .radio-btn { - font-size: 20px; - border-radius: 4px; - background-color: whitesmoke; - padding: 5px; - margin: 0.5rem; - filter: drop-shadow(4px 2px 2px rgb(0 0 0 / 0.4)); + font-size: 20px; + border-radius: 4px; + background-color: whitesmoke; + padding: 5px; + margin: 0.5rem; + filter: drop-shadow(4px 2px 2px rgb(0 0 0 / 0.4)); } .radio { - height: 1rem; - width: 1rem; - margin-right: 2rem; + height: 1rem; + width: 1rem; + margin-right: 2rem; } .radio-mobile { - height: 1.25rem; - width: 1.25rem; - margin-right: 1.5rem; + height: 1.25rem; + width: 1.25rem; + margin-right: 1.5rem; } .radio-group { - overflow-y: auto; - width: 100%; - max-height: 18vh; + overflow-y: auto; + width: 100%; + max-height: 18vh; } .radio-group-mobile { - overflow-y: scroll; + overflow-y: scroll; } .modify { - float: right; - font-size: 25px; + float: right; + font-size: 25px; } .radio-icon { - padding-right: 2rem; + padding-right: 2rem; } .add-btn { - width: 97%; - border-radius: 13px; - border: 5px solid whitesmoke; - font-size: 45px; - padding: 20px; - margin: 1rem; - text-align: center; + width: 97%; + border-radius: 13px; + border: 5px solid whitesmoke; + font-size: 45px; + padding: 20px; + margin: 1rem; + text-align: center; } .start-btn { - width: 97%; - border-radius: 13px; - border: 5px solid whitesmoke; - font-size: 45px; - padding: 20px; - margin: 1rem; - text-align: center; - background: #06c7e1; + width: 97%; + border-radius: 13px; + border: 5px solid whitesmoke; + font-size: 45px; + padding: 20px; + margin: 1rem; + text-align: center; + background: #06c7e1; } diff --git a/src/pages/operator/css/RunStopButton.css b/src/pages/operator/css/RunStopButton.css index 38ffd19f..de3aea0d 100644 --- a/src/pages/operator/css/RunStopButton.css +++ b/src/pages/operator/css/RunStopButton.css @@ -1,23 +1,23 @@ .run-stop-button { - max-width: 110px; - width: 100%; + max-width: 110px; + width: 100%; } .enabled { - animation: blinker 1s linear infinite; - filter: brightness(30%) saturate(100%) invert(10%) sepia(28%) saturate(4155%) - hue-rotate(0deg) contrast(119%); + animation: blinker 1s linear infinite; + filter: brightness(30%) saturate(100%) invert(10%) sepia(28%) + saturate(4155%) hue-rotate(0deg) contrast(119%); } @keyframes blinker { - 50% { - opacity: 0; - } + 50% { + opacity: 0; + } } .runStopContainer { - display: flex; - flex-direction: column; - align-items: center; - text-align: center; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; } diff --git a/src/pages/operator/css/Sidebar.css b/src/pages/operator/css/Sidebar.css index cf3437fc..bdde80f4 100644 --- a/src/pages/operator/css/Sidebar.css +++ b/src/pages/operator/css/Sidebar.css @@ -1,196 +1,196 @@ #sidebar { - width: 20rem; - grid-row: 2/4; - grid-column: 2; - height: 100%; - background-color: var(--gray-bg); - display: grid; - grid-template-rows: 5rem auto 7rem; - transition: width 0.5s ease-out; - /* Darken the gray background color from index.css */ - --header-bg: color-mix(in srgb, var(--gray-bg) 90%, black); - white-space: nowrap; + width: 20rem; + grid-row: 2/4; + grid-column: 2; + height: 100%; + background-color: var(--gray-bg); + display: grid; + grid-template-rows: 5rem auto 7rem; + transition: width 0.5s ease-out; + /* Darken the gray background color from index.css */ + --header-bg: color-mix(in srgb, var(--gray-bg) 90%, black); + white-space: nowrap; } #sidebar[hidden] { - width: 0; + width: 0; } #sidebar p { - margin-top: 0; - margin-bottom: 1rem; + margin-top: 0; + margin-bottom: 1rem; } #sidebar-header { - background-color: var(--header-bg); - padding: 1rem; - display: flex; - align-items: center; - font-size: 18px; + background-color: var(--header-bg); + padding: 1rem; + display: flex; + align-items: center; + font-size: 18px; } #sidebar-body { - padding: 1rem; - box-shadow: inset 0 0 3px 0px var(--shadow-color); + padding: 1rem; + box-shadow: inset 0 0 3px 0px var(--shadow-color); - display: flex; - flex-direction: column; - justify-content: space-between; + display: flex; + flex-direction: column; + justify-content: space-between; } /* Footer *********************************************************************/ #sidebar-footer { - background-color: var(--header-bg); + background-color: var(--header-bg); } #delete-button { - font-size: 3rem; - padding: 1rem; - /* Center it */ - display: block; - width: 90%; - margin: 0.8rem auto; + font-size: 3rem; + padding: 1rem; + /* Center it */ + display: block; + width: 90%; + margin: 0.8rem auto; } /* Options ********************************************************************/ #sidebar-options > button { - height: 5rem; - width: 100%; + height: 5rem; + width: 100%; } .toggle-button-div { - padding-bottom: 10px; + padding-bottom: 10px; } .toggle-button { - display: inline-block; - margin-right: 1rem; - width: 7rem; - height: 5rem; - border-radius: var(--btn-brdr-radius); + display: inline-block; + margin-right: 1rem; + width: 7rem; + height: 5rem; + border-radius: var(--btn-brdr-radius); } .toggle-button.on { - background-color: var(--btn-lightgreen); + background-color: var(--btn-lightgreen); } /* Component Provider *********************************************************/ #sidebar-component-provider { - margin-bottom: 2rem; - flex: 1; - display: grid; - grid-template-rows: auto 1fr; + margin-bottom: 2rem; + flex: 1; + display: grid; + grid-template-rows: auto 1fr; } #components-set { - overflow-y: scroll; - height: 100%; + overflow-y: scroll; + height: 100%; } .provider-tab { - border-radius: var(--btn-brdr-radius); - box-shadow: var(--shadow); - margin-right: 0.5rem; + border-radius: var(--btn-brdr-radius); + box-shadow: var(--shadow); + margin-right: 0.5rem; } #sidebar-component-provider button { - width: 100%; - text-align: left; - padding: var(--btn-padding); - display: flex; - align-items: center; - height: 3rem; - box-shadow: none; + width: 100%; + text-align: left; + padding: var(--btn-padding); + display: flex; + align-items: center; + height: 3rem; + box-shadow: none; } .provider-tab .active { - background-color: var(--selected-color); + background-color: var(--selected-color); } .provider-tab button span { - width: 2rem; - transition: transform 0.2s linear; + width: 2rem; + transition: transform 0.2s linear; } .provider-tab button.expanded { - filter: brightness(95%); - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; + filter: brightness(95%); + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; } .provider-tab button.expanded span { - transform: scaleY(-1); + transform: scaleY(-1); } .provider-tab button.id-button { - padding-left: 3rem; + padding-left: 3rem; } .id-button { - transition: height 0.2s ease-out; - border-radius: 0; + transition: height 0.2s ease-out; + border-radius: 0; } .id-button:last-of-type { - border-bottom-left-radius: var(--btn-brdr-radius); - border-bottom-right-radius: var(--btn-brdr-radius); + border-bottom-left-radius: var(--btn-brdr-radius); + border-bottom-right-radius: var(--btn-brdr-radius); } /* Global settings area *******************************************************/ #global-settings > button { - display: block; + display: block; } #global-settings button { - height: 3rem; + height: 3rem; } #global-settings > * { - width: 100%; + width: 100%; } #global-settings > *, .provider-tab { - margin-bottom: 0.4rem; + margin-bottom: 0.4rem; } #load-layout-modal .dropdown p { - margin: 0; + margin: 0; } #load-layout-modal .dropdown em { - color: #6a6a6a; - margin-right: 1rem; + color: #6a6a6a; + margin-right: 1rem; } #load-layout-modal .dropdown { - width: 90%; + width: 90%; } .select-selected { - background-color: dodgerblue; + background-color: dodgerblue; } .global-label { - display: inline-flex; - inline-size: 164px; - text-wrap: wrap; + display: inline-flex; + inline-size: 164px; + text-wrap: wrap; } @media (max-width: 900px) { - #sidebar { - grid-template-rows: auto; - } - - #delete-button { - font-size: x-large; - padding: 0.1rem; - } - - #sidebar-body { - display: block; - overflow: scroll; - } + #sidebar { + grid-template-rows: auto; + } + + #delete-button { + font-size: x-large; + padding: 0.1rem; + } + + #sidebar-body { + display: block; + overflow: scroll; + } } diff --git a/src/pages/operator/css/SimpleCameraView.css b/src/pages/operator/css/SimpleCameraView.css index 951a748a..71de3809 100644 --- a/src/pages/operator/css/SimpleCameraView.css +++ b/src/pages/operator/css/SimpleCameraView.css @@ -1,46 +1,46 @@ .simple-video-container { - position: relative; - /* flex: 1 1 0; */ - /* display: grid; */ - justify-items: center; - /* padding: 0.4rem; */ - /* height: 100%; */ - /* grid-template-columns: auto; */ - /* grid-template-rows: 1fr auto minmax(9rem, 1fr); */ - object-fit: cover; - justify-content: center; - /* align-items: center; + position: relative; + /* flex: 1 1 0; */ + /* display: grid; */ + justify-items: center; + /* padding: 0.4rem; */ + /* height: 100%; */ + /* grid-template-columns: auto; */ + /* grid-template-rows: 1fr auto minmax(9rem, 1fr); */ + object-fit: cover; + justify-content: center; + /* align-items: center; flex-direction: column; */ - text-align: -webkit-center; + text-align: -webkit-center; } .simple-video-area { - position: relative; - grid-row: 2/2; - width: 100%; - max-height: 100%; - max-width: 100%; - object-fit: cover; - display: inline-block; - text-align: center; + position: relative; + grid-row: 2/2; + width: 100%; + max-height: 100%; + max-width: 100%; + object-fit: cover; + display: inline-block; + text-align: center; } .simple-video-canvas { - display: inline-block; - width: 100%; - height: auto; - object-fit: cover; + display: inline-block; + width: 100%; + height: auto; + object-fit: cover; } .simple-video-canvas.constrainedHeight { - display: inline-block; - /* width: auto; + display: inline-block; + /* width: auto; height: 100%; */ - object-fit: cover; + object-fit: cover; } .simple-realsense { - /* margin-top: -75%; */ + /* margin-top: -75%; */ } /* @media screen and (max-height: 800px) { @@ -49,88 +49,88 @@ } } */ .icon { - border-radius: 60px; - background-color: aliceblue; - font-size: 100px; - opacity: 0.5; - color: black; + border-radius: 60px; + background-color: aliceblue; + font-size: 100px; + opacity: 0.5; + color: black; } .simple-overlay { - font-size: 50px; - position: absolute; - z-index: 4; - /* margin-top: 75%; */ - background-color: transparent; - touch-action: none; - box-shadow: none; + font-size: 50px; + position: absolute; + z-index: 4; + /* margin-top: 75%; */ + background-color: transparent; + touch-action: none; + box-shadow: none; } .btn-left { - width: 20%; - height: 100%; + width: 20%; + height: 100%; } .btn-right { - width: 20%; - height: 100%; - margin-left: 80%; + width: 20%; + height: 100%; + margin-left: 80%; } .btn-up { - width: 100%; + width: 100%; } .btn-down { - width: 100%; - display: flex; - justify-content: center; + width: 100%; + display: flex; + justify-content: center; } /* Context menu popup *********************************************************/ .video-context-menu { - list-style-type: none; - position: absolute; - background-color: var(--background-color); - /* border: var(--btn-brdr); */ - margin: 0; - padding: 0; - white-space: nowrap; + list-style-type: none; + position: absolute; + background-color: var(--background-color); + /* border: var(--btn-brdr); */ + margin: 0; + padding: 0; + white-space: nowrap; - --padding: 1rem; + --padding: 1rem; - padding-top: var(--padding); - grid-row: 2/2; + padding-top: var(--padding); + grid-row: 2/2; } .video-context-menu li { - padding: var(--padding); - cursor: pointer; - background-color: inherit; + padding: var(--padding); + cursor: pointer; + background-color: inherit; } .video-context-menu li:hover { - filter: brightness(90%); + filter: brightness(90%); } .video-context-menu::before { - content: attr(aria-label); - font-weight: bold; - padding: var(--padding); + content: attr(aria-label); + font-weight: bold; + padding: var(--padding); } .title { - font-size: x-large; - align-self: flex-end; - text-align: center; + font-size: x-large; + align-self: flex-end; + text-align: center; } @media screen and (orientation: landscape) and (max-device-width: 900px) { - .realsense-pan-tilt-grid button .material-icons { - font-size: larger; - } + .realsense-pan-tilt-grid button .material-icons { + font-size: larger; + } - .title { - font-size: smaller; - } + .title { + font-size: smaller; + } } diff --git a/src/pages/operator/css/SpeedControl.css b/src/pages/operator/css/SpeedControl.css index 289f945e..5537fd56 100644 --- a/src/pages/operator/css/SpeedControl.css +++ b/src/pages/operator/css/SpeedControl.css @@ -1,19 +1,19 @@ #velocity-control-container button:first-of-type { - border-radius: var(--btn-brdr-radius) 0 0 var(--btn-brdr-radius); + border-radius: var(--btn-brdr-radius) 0 0 var(--btn-brdr-radius); } #velocity-control-container button:last-of-type { - border-radius: 0 var(--btn-brdr-radius) var(--btn-brdr-radius) 0; + border-radius: 0 var(--btn-brdr-radius) var(--btn-brdr-radius) 0; } #velocity-control-container button { - border-radius: 0; - /* Make buttons wider than default */ - width: 8rem; + border-radius: 0; + /* Make buttons wider than default */ + width: 8rem; } @media (max-width: 1000px) { - #velocity-control-container button { - width: auto; - } + #velocity-control-container button { + width: auto; + } } diff --git a/src/pages/operator/css/TabGroup.css b/src/pages/operator/css/TabGroup.css index 7dcd07eb..a3bbf2ad 100644 --- a/src/pages/operator/css/TabGroup.css +++ b/src/pages/operator/css/TabGroup.css @@ -1,75 +1,75 @@ .tab { - font-size: 20px; - /* padding-top: 10px; */ - cursor: pointer; - outline: 0; - display: flex; - border-bottom: 5px solid black; - justify-content: space-evenly; - background-color: transparent; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + font-size: 20px; + /* padding-top: 10px; */ + cursor: pointer; + outline: 0; + display: flex; + border-bottom: 5px solid black; + justify-content: space-evenly; + background-color: transparent; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } .pill-tab { - /* font-size: 45px; */ - cursor: pointer; - outline: 0; - display: flex; - justify-content: space-between; - background-color: transparent; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - width: 80%; - height: auto; - background: #052a33; - margin: 1rem auto 1rem; - color: #e8f0f2; - border-radius: 10rem; - list-style: none; + /* font-size: 45px; */ + cursor: pointer; + outline: 0; + display: flex; + justify-content: space-between; + background-color: transparent; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + width: 80%; + height: auto; + background: #052a33; + margin: 1rem auto 1rem; + color: #e8f0f2; + border-radius: 10rem; + list-style: none; } .tab-btn { - background-color: transparent; - border-bottom: none; - color: white; - font-weight: 500; + background-color: transparent; + border-bottom: none; + color: white; + font-weight: 500; } li.pill-tab-btn { - background-color: transparent; - border-bottom: none; - padding: 0.5rem; - padding-left: 2rem; - padding-right: 2rem; + background-color: transparent; + border-bottom: none; + padding: 0.5rem; + padding-left: 2rem; + padding-right: 2rem; } li.pill-tab-btn:first-child { - border-bottom-left-radius: 5rem; - border-top-left-radius: 5rem; + border-bottom-left-radius: 5rem; + border-top-left-radius: 5rem; } li.pill-tab-btn:last-child { - border-bottom-right-radius: 5rem; - border-top-right-radius: 5rem; + border-bottom-right-radius: 5rem; + border-top-right-radius: 5rem; } .tab-btn.active { - border-bottom: 5px solid #06c7e1; + border-bottom: 5px solid #06c7e1; } .pill-tab-btn.active { - background: #39a2db; + background: #39a2db; } .tab-content { - display: flex; - flex-direction: column; - height: 100%; - width: 100%; - flex: 1 1 0; - /* padding-bottom: 10px; */ - justify-content: space-between; + display: flex; + flex-direction: column; + height: 100%; + width: 100%; + flex: 1 1 0; + /* padding-bottom: 10px; */ + justify-content: space-between; } .tab-group { - display: contents; + display: contents; } diff --git a/src/pages/operator/css/TextToSpeech.css b/src/pages/operator/css/TextToSpeech.css index f7bbbcae..f32da0f0 100644 --- a/src/pages/operator/css/TextToSpeech.css +++ b/src/pages/operator/css/TextToSpeech.css @@ -1,60 +1,60 @@ #text-to-speech-container { - display: flex; - gap: 15px; - align-items: center; - justify-content: center; + display: flex; + gap: 15px; + align-items: center; + justify-content: center; } .play-btn { - background-color: var(--selected-color); - display: flex; + background-color: var(--selected-color); + display: flex; } .save-btn { - background-color: var(--btn-turquoise); - display: flex; + background-color: var(--btn-turquoise); + display: flex; } .stop-btn { - background-color: #cd0b0b; - color: white; - display: flex; + background-color: #cd0b0b; + color: white; + display: flex; } .delete-btn { - background-color: var(--btn-red); - display: flex; + background-color: var(--btn-red); + display: flex; } @media (max-width: 1300px) { - #text-to-speech-container { - font-size: smaller; - } + #text-to-speech-container { + font-size: smaller; + } } .mobile-text-save-btn { - border-radius: 13px; - border: 5px solid whitesmoke; - font-size: 25px; - padding: 10px; - margin: 1rem; - text-align: center; - background: #06c7e1; - vertical-align: middle; - display: flex; - justify-content: center; + border-radius: 13px; + border: 5px solid whitesmoke; + font-size: 25px; + padding: 10px; + margin: 1rem; + text-align: center; + background: #06c7e1; + vertical-align: middle; + display: flex; + justify-content: center; } .mobile-text-play-btn { - /* width: 97%; */ - border-radius: 13px; - border: 5px solid whitesmoke; - font-size: 20px; - padding: 10px; - margin: 0.5rem; - text-align: center; - background: #06c7e1; - vertical-align: middle; - display: flex; - justify-content: center; + /* width: 97%; */ + border-radius: 13px; + border: 5px solid whitesmoke; + font-size: 20px; + padding: 10px; + margin: 0.5rem; + text-align: center; + background: #06c7e1; + vertical-align: middle; + display: flex; + justify-content: center; } diff --git a/src/pages/operator/css/Tooltip.css b/src/pages/operator/css/Tooltip.css index 0c5323e5..c681f0f5 100644 --- a/src/pages/operator/css/Tooltip.css +++ b/src/pages/operator/css/Tooltip.css @@ -1,105 +1,105 @@ .tooltip-trigger .tooltip-top::after { - content: " "; - position: absolute; - top: 100%; - left: 50%; - margin-left: -5px; - border-width: 5px; - border-style: solid; - border-color: black transparent transparent transparent; + content: " "; + position: absolute; + top: 100%; + left: 50%; + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: black transparent transparent transparent; } .tooltip-trigger .tooltip-bottom::after { - content: " "; - position: absolute; - bottom: 100%; - left: 50%; - margin-left: -5px; - border-width: 5px; - border-style: solid; - border-color: transparent transparent black transparent; + content: " "; + position: absolute; + bottom: 100%; + left: 50%; + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: transparent transparent black transparent; } .tooltip-trigger .tooltip { - display: none; - opacity: 0; + display: none; + opacity: 0; } .tooltip-trigger:hover .tooltip { - display: block; - opacity: 1; - animation: fade-in 0.5s; + display: block; + opacity: 1; + animation: fade-in 0.5s; } @keyframes fade-in { - from { - opacity: 0; - } + from { + opacity: 0; + } - to { - opacity: 1; - } + to { + opacity: 1; + } } .tooltip-trigger { - position: relative; - display: inline; + position: relative; + display: inline; } .tooltip-trigger .tooltip { - width: fit-content; - min-width: 100%; - left: 50%; - transform: translateX(-50%); - background-color: black; - color: #fff; - text-align: center; - border-radius: 6px; - padding: 5px; - opacity: 0; - transition: opacity 1s; - position: absolute; - z-index: 1; + width: fit-content; + min-width: 100%; + left: 50%; + transform: translateX(-50%); + background-color: black; + color: #fff; + text-align: center; + border-radius: 6px; + padding: 5px; + opacity: 0; + transition: opacity 1s; + position: absolute; + z-index: 1; } .tooltip-right { - top: -5px; - left: 105%; + top: -5px; + left: 105%; } .tooltip-left { - top: -5px; - right: 105%; + top: -5px; + right: 105%; } .tooltip-top { - bottom: 105%; - left: 0%; + bottom: 105%; + left: 0%; } .tooltip-bottom { - top: 105%; - left: 0%; + top: 105%; + left: 0%; } .tooltip-trigger .tooltip-right::after { - content: " "; - position: absolute; - top: 50%; - right: 100%; - margin-top: -5px; - border-width: 5px; - border-style: solid; - border-color: transparent black transparent transparent; + content: " "; + position: absolute; + top: 50%; + right: 100%; + margin-top: -5px; + border-width: 5px; + border-style: solid; + border-color: transparent black transparent transparent; } .tooltip-trigger .tooltip-left::after { - content: " "; - position: absolute; - top: 50%; - left: 100%; - margin-top: -5px; - border-width: 5px; - border-style: solid; - border-color: transparent transparent transparent black; + content: " "; + position: absolute; + top: 50%; + left: 100%; + margin-top: -5px; + border-width: 5px; + border-style: solid; + border-color: transparent transparent transparent black; } diff --git a/src/pages/operator/css/VirtualJoystick.css b/src/pages/operator/css/VirtualJoystick.css index c1b3ffb4..fe430d90 100644 --- a/src/pages/operator/css/VirtualJoystick.css +++ b/src/pages/operator/css/VirtualJoystick.css @@ -1,44 +1,44 @@ .virtual-joystick { - flex: 1; - border-radius: var(--btn-brdr-radius); - /* border: 2px solid var(--btn-blue); */ - margin: 0.4rem; - position: relative; - z-index: 1; - max-height: 100%; + flex: 1; + border-radius: var(--btn-brdr-radius); + /* border: 2px solid var(--btn-blue); */ + margin: 0.4rem; + position: relative; + z-index: 1; + max-height: 100%; - display: grid; - justify-items: center; + display: grid; + justify-items: center; } .virtual-joystick svg { - max-height: 100%; - max-width: fit-content; + max-height: 100%; + max-width: fit-content; } .virtual-joystick:not(.customizing) { - cursor: crosshair; + cursor: crosshair; } .virtual-joystick::after { - border-radius: var(--btn-brdr-radius); + border-radius: var(--btn-brdr-radius); } .virtual-joystick path { - fill: none; - stroke-width: 1; - stroke: lightgray; + fill: none; + stroke-width: 1; + stroke: lightgray; } .virtual-joystick .joystick { - fill: darkgray; + fill: darkgray; } .virtual-joystick .outer-circle { - /* fill: lightgray; */ - fill: #312e2e; + /* fill: lightgray; */ + fill: #312e2e; } .virtual-joystick.active .joystick { - fill: var(--btn-turquoise); + fill: var(--btn-turquoise); } diff --git a/src/pages/operator/css/basic_components.css b/src/pages/operator/css/basic_components.css index df24a91d..b706c500 100644 --- a/src/pages/operator/css/basic_components.css +++ b/src/pages/operator/css/basic_components.css @@ -1,380 +1,380 @@ /* Popup modal ****************************************************************/ .popup-modal { - position: fixed; - border-radius: var(--btn-brdr-radius); - background-color: var(--background-color); - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - padding: 1rem; - z-index: 10; - height: 50%; - width: 50%; - display: flex; - flex-direction: column; - /* align-items: center; */ - justify-content: space-between; - opacity: 100%; - touch-action: manipulation; + position: fixed; + border-radius: var(--btn-brdr-radius); + background-color: var(--background-color); + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + padding: 1rem; + z-index: 10; + height: 50%; + width: 50%; + display: flex; + flex-direction: column; + /* align-items: center; */ + justify-content: space-between; + opacity: 100%; + touch-action: manipulation; } .popup-modal.small { - height: 15rem; - width: 20rem; - top: 10%; + height: 15rem; + width: 20rem; + top: 10%; } .popup-modal.medium { - height: 50rem; - width: 47rem; - top: -10%; - /* height: 35%; */ + height: 50rem; + width: 47rem; + top: -10%; + /* height: 35%; */ } .popup-modal.large { - height: 50%; + height: 50%; } .mobile { - transform: translate(-50%, 50%); - display: flex; - justify-content: space-around; - /* font-size: 50px !important; */ + transform: translate(-50%, 50%); + display: flex; + justify-content: space-around; + /* font-size: 50px !important; */ } .voice-commands-popup-modal { - position: fixed; - border-radius: var(--btn-brdr-radius); - background-color: var(--background-color); - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - padding: 2rem; - z-index: 4; - height: 45rem; - width: 30rem; - display: flex; - flex-direction: column; - /* align-items: center; */ - justify-content: space-between; - opacity: 100%; + position: fixed; + border-radius: var(--btn-brdr-radius); + background-color: var(--background-color); + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + padding: 2rem; + z-index: 4; + height: 45rem; + width: 30rem; + display: flex; + flex-direction: column; + /* align-items: center; */ + justify-content: space-between; + opacity: 100%; } .voice-commands-popup-modal #close-modal { - padding-left: 80%; + padding-left: 80%; } .voice-commands-popup-modal #commands { - padding-right: 20%; + padding-right: 20%; } .popup-modal-bottom-buttons { - width: 100%; + width: 100%; } .popup-modal-bottom-buttons button { - width: 45%; - padding: 0.5em; - color: black; + width: 45%; + padding: 0.5em; + color: black; } /* Dark background behind popup */ #popup-background, .loader-background { - position: fixed; - top: 0; - left: 0; - height: 100%; - width: 100%; - background-color: black; - opacity: 60%; - z-index: 3; + position: fixed; + top: 0; + left: 0; + height: 100%; + width: 100%; + background-color: black; + opacity: 60%; + z-index: 3; } .popup-modal label { - font-size: 30px; + font-size: 30px; } .popup-modal input { - width: 100%; - padding: 0.5em; + width: 100%; + padding: 0.5em; } /* Dropdown *******************************************************************/ .dropdown { - position: relative; + position: relative; } .dropdown-button, .dropdown-input-button { - display: flex; - align-items: center; - justify-content: space-between; - padding-top: 1rem; - padding-bottom: 1rem; - width: 100%; - position: relative; - color: black; + display: flex; + align-items: center; + justify-content: space-between; + padding-top: 1rem; + padding-bottom: 1rem; + width: 100%; + position: relative; + color: black; } .dropdown-button.expanded.bottom, .dropdown-input-button.expanded.bottom { - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - color: black; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + color: black; } .dropdown-button.expanded.top, .dropdown-input-button.expanded.top { - border-top-left-radius: 0; - border-top-right-radius: 0; - margin: 0 !important; - color: black; + border-top-left-radius: 0; + border-top-right-radius: 0; + margin: 0 !important; + color: black; } /* Flip the dropdown arrow when active */ .dropdown-button span, .dropdown-input-button span { - transition: transform 0.2s linear; + transition: transform 0.2s linear; } .dropdown-button.expanded span, .dropdown-input-button.expanded span { - transform: scaleY(-1); + transform: scaleY(-1); } .dropdown-popup, .dropdown-input-popup { - position: absolute; - min-width: 100%; - z-index: 3; - box-shadow: var(--shadow); - border-radius: 0 0 var(--btn-brdr-radius) var(--btn-brdr-radius); - top: 100%; - bottom: auto; - overflow-y: auto; /* Make it scrollable */ + position: absolute; + min-width: 100%; + z-index: 3; + box-shadow: var(--shadow); + border-radius: 0 0 var(--btn-brdr-radius) var(--btn-brdr-radius); + top: 100%; + bottom: auto; + overflow-y: auto; /* Make it scrollable */ } .dropdown-popup.top, .dropdown-input-popup.top { - top: auto; - bottom: 100%; - box-shadow: var(--shadow-bottom); + top: auto; + bottom: 100%; + box-shadow: var(--shadow-bottom); } .dropdown-option, .dropdown-input-option { - padding-top: 1rem; - padding-bottom: 1rem; - cursor: pointer; - width: 100%; - display: block; - border-radius: 0; - text-align: left; - margin: 0 !important; - color: black; + padding-top: 1rem; + padding-bottom: 1rem; + cursor: pointer; + width: 100%; + display: block; + border-radius: 0; + text-align: left; + margin: 0 !important; + color: black; } .dropdown-option.active, .dropdown-input-option.active { - filter: brightness(80%); + filter: brightness(80%); } .dropdown-popup.top .dropdown-option:first-of-type, .dropdown-input-popup.top .dropdown-option:first-of-type { - border-radius: var(--btn-brdr-radius) var(--btn-brdr-radius) 0 0; + border-radius: var(--btn-brdr-radius) var(--btn-brdr-radius) 0 0; } .dropdown-popup.top .dropdown-option:last-of-type, .dropdown-input-popup.top .dropdown-option:last-of-type { - box-shadow: none; + box-shadow: none; } .dropdown-popup.bottom .dropdown-option:last-of-type, .dropdown-input-popup.bottom .dropdown-option:last-of-type { - border-radius: 0 0 var(--btn-brdr-radius) var(--btn-brdr-radius); + border-radius: 0 0 var(--btn-brdr-radius) var(--btn-brdr-radius); } /* Dropdown Input **************************************************************/ .dropdown-input { - position: relative; - display: flex; - align-items: stretch; - justify-content: center; + position: relative; + display: flex; + align-items: stretch; + justify-content: center; } .dropdown-input:focus-within { - border: 1px solid black; - border-radius: 0 var(--btn-brdr-radius) var(--btn-brdr-radius) 0; + border: 1px solid black; + border-radius: 0 var(--btn-brdr-radius) var(--btn-brdr-radius) 0; } .dropdown-input-textarea { - border-right-width: 0px !important; - resize: none; - border-radius: var(--btn-brdr-radius) 0 0 var(--btn-brdr-radius); - box-shadow: var(--shadow); - border: none; - padding: 0.25rem 0 0.25rem 0.5rem; + border-right-width: 0px !important; + resize: none; + border-radius: var(--btn-brdr-radius) 0 0 var(--btn-brdr-radius); + box-shadow: var(--shadow); + border: none; + padding: 0.25rem 0 0.25rem 0.5rem; } .dropdown-input-textarea:focus { - border-radius: var(--btn-brdr-radius) 0 0 var(--btn-brdr-radius); - outline: none; + border-radius: var(--btn-brdr-radius) 0 0 var(--btn-brdr-radius); + outline: none; } .dropdown-input-button { - width: auto !important; - padding-top: 0rem; - padding-bottom: 0rem; - box-shadow: none; - border-radius: 0 var(--btn-brdr-radius) var(--btn-brdr-radius) 0; - box-shadow: var(--shadow); - /* border: 1px solid light-dark(rgb(118, 118, 118), rgb(133, 133, 133)); */ - border-left-width: 0px !important; + width: auto !important; + padding-top: 0rem; + padding-bottom: 0rem; + box-shadow: none; + border-radius: 0 var(--btn-brdr-radius) var(--btn-brdr-radius) 0; + box-shadow: var(--shadow); + /* border: 1px solid light-dark(rgb(118, 118, 118), rgb(133, 133, 133)); */ + border-left-width: 0px !important; } /* CheckToggleButton **********************************************************/ .check-toggle-button { - display: flex; - justify-content: center; - color: black; + display: flex; + justify-content: center; + color: black; } .check-toggle-button span.material-icons { - margin-right: 1rem; + margin-right: 1rem; } .check-toggle-button, .check-toggle-button-mobile { - border-radius: 13px; - display: flex; - justify-content: center; - align-items: center; - text-align: center; - background: transparent; + border-radius: 13px; + display: flex; + justify-content: center; + align-items: center; + text-align: center; + background: transparent; } .check-toggle-button-mobile { - border: 5px solid whitesmoke; - /* margin: 1rem; */ + border: 5px solid whitesmoke; + /* margin: 1rem; */ } .pose-name { - /* padding-top: 5%; */ - align-self: normal; + /* padding-top: 5%; */ + align-self: normal; } .pose-name label { - padding-right: 2.5rem; + padding-right: 2.5rem; } .pose-name input { - width: 65%; + width: 65%; } .mobile-pose-name input { - width: 100%; + width: 100%; } ul.checkbox { - margin: 0; - padding: 0; - margin-left: 1rem; - list-style: none; + margin: 0; + padding: 0; + margin-left: 1rem; + list-style: none; } ul.checkbox li { - border: 0.5rem transparent solid; + border: 0.5rem transparent solid; } hr { - width: 100%; + width: 100%; } button .material-icons { - margin: 0 !important; + margin: 0 !important; } input[type="checkbox"] { - width: 1.5rem; - height: 1.5rem; - background: white; - border-radius: 5px; - border: 2px solid #555; - margin-right: 1rem; + width: 1.5rem; + height: 1.5rem; + background: white; + border-radius: 5px; + border: 2px solid #555; + margin-right: 1rem; } @media screen and (max-device-width: 700px) { - input[type="checkbox"] { - margin-right: 3rem; - transform: scale(2); - } + input[type="checkbox"] { + margin-right: 3rem; + transform: scale(2); + } - .popup-modal label { - font-size: 50px; - } + .popup-modal label { + font-size: 50px; + } } /* AccordionSelect **********************************************************/ /* Style the accordion section */ .accordion_section { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } /* Style the buttons that are used to open and close the accordion panel */ .accordion { - /* background-color: #eee; */ - /* color: #444; */ - cursor: pointer; - /* padding: 18px; */ - display: flex; - align-items: center; - border: none; - outline: none; - transition: background-color 0.6s ease; - justify-content: space-between; + /* background-color: #eee; */ + /* color: #444; */ + cursor: pointer; + /* padding: 18px; */ + display: flex; + align-items: center; + border: none; + outline: none; + transition: background-color 0.6s ease; + justify-content: space-between; } /* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */ .accordion:hover, .active { - background-image: linear-gradient(rgba(0, 0, 0, 0.05) 0 0); + background-image: linear-gradient(rgba(0, 0, 0, 0.05) 0 0); } /* Style the accordion content title */ .accordion_title { - font-family: "Open Sans", sans-serif; - font-weight: 600; - font-size: 14px; + font-family: "Open Sans", sans-serif; + font-weight: 600; + font-size: 14px; } /* Style the accordion content panel. Note: hidden by default */ .accordion_content { - background-color: var(--btn-gray); - overflow: hidden; - transition: max-height 0.6s ease; + background-color: var(--btn-gray); + overflow: hidden; + transition: max-height 0.6s ease; } /* Flip the dropdown arrow when active */ .accordion span { - transition: transform 0.2s linear; + transition: transform 0.2s linear; } .accordion.active span { - transform: scaleY(-1); + transform: scaleY(-1); } .accordion-item { - padding: 0.75rem 0rem 0.75rem 0rem; - text-align: center; + padding: 0.75rem 0rem 0.75rem 0rem; + text-align: center; } .accordion-item:hover { - background-image: linear-gradient(rgba(0, 0, 0, 0.15) 0 0); + background-image: linear-gradient(rgba(0, 0, 0, 0.15) 0 0); } diff --git a/src/pages/operator/css/index.css b/src/pages/operator/css/index.css index c5097051..1853f386 100644 --- a/src/pages/operator/css/index.css +++ b/src/pages/operator/css/index.css @@ -1,158 +1,158 @@ :root { - --btn-brdr-radius: 0.4rem; - --btn-padding: 0.5em 1em; - --btn-padding-med: 0.4rem 0.5rem; + --btn-brdr-radius: 0.4rem; + --btn-padding: 0.5em 1em; + --btn-padding-med: 0.4rem 0.5rem; - --selected-color: hsl(33, 95%, 63%); + --selected-color: hsl(33, 95%, 63%); - --btn-gray: #f0f0f0; - --btn-blue: hsl(200deg 83.23% 22.29%); - --btn-green: rgb(129, 218, 129); - --btn-red: hsl(0, 70%, 70%); - --btn-turquoise: hsl(171, 32%, 46%); + --btn-gray: #f0f0f0; + --btn-blue: hsl(200deg 83.23% 22.29%); + --btn-green: rgb(129, 218, 129); + --btn-red: hsl(0, 70%, 70%); + --btn-turquoise: hsl(171, 32%, 46%); - --shadow-color: rgba(112, 112, 112, 0.196); + --shadow-color: rgba(112, 112, 112, 0.196); - --background-color: hsl(0, 0%, 98%); - --gray-bg: hsl(0, 0%, 88%); + --background-color: hsl(0, 0%, 98%); + --gray-bg: hsl(0, 0%, 88%); - --shadow: 3px 3px 2px var(--shadow-color); + --shadow: 3px 3px 2px var(--shadow-color); - --tab-inactive: hsl(200, 20%, 85%); + --tab-inactive: hsl(200, 20%, 85%); - --font-white: hsl(0, 0%, 100%); + --font-white: hsl(0, 0%, 100%); - --path-blue: hsl(170, 37%, 53%); + --path-blue: hsl(170, 37%, 53%); - --shadow-bottom: 3px 0px 0px var(--shadow-color); + --shadow-bottom: 3px 0px 0px var(--shadow-color); } * { - box-sizing: border-box; - min-width: 0; - min-height: 0; - font: inherit; + box-sizing: border-box; + min-width: 0; + min-height: 0; + font: inherit; } 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: var(--background-color); + 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: var(--background-color); } html { - -webkit-touch-callout: none; - -webkit-tap-highlight-color: transparent; - -moz-user-select: -moz-none; - -webkit-user-select: none; - -ms-user-select: none; - user-select: none; + -webkit-touch-callout: none; + -webkit-tap-highlight-color: transparent; + -moz-user-select: -moz-none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; } html, body, #root { - height: 100%; - margin: 0; - overflow: hidden; - user-select: none; + height: 100%; + margin: 0; + overflow: hidden; + user-select: none; } @media screen and (orientation: landscape) and (max-device-width: 900px) { - html, - body, - #root { - overflow: scroll; - } + html, + body, + #root { + overflow: scroll; + } } /* In customization mode add hidden shadow after each element, to be shown when the element is selected */ .customizing::after { - content: ""; - position: absolute; + content: ""; + position: absolute; - z-index: -1; - width: 100%; - height: 100%; - opacity: 0; - left: 0; - top: 0; + z-index: -1; + width: 100%; + height: 100%; + opacity: 0; + left: 0; + top: 0; - box-shadow: 0 0 1rem 0.5rem var(--selected-color); - transition: opacity 0.25s ease-in-out; + box-shadow: 0 0 1rem 0.5rem var(--selected-color); + transition: opacity 0.25s ease-in-out; } .customizing.selected::after { - opacity: 1; + opacity: 1; } /* Button colors **************************************************************/ button { - background-color: var(--btn-gray); - border: none; - border-radius: var(--btn-brdr-radius); - padding: var(--btn-padding); - box-shadow: var(--shadow); - cursor: pointer; + background-color: var(--btn-gray); + border: none; + border-radius: var(--btn-brdr-radius); + padding: var(--btn-padding); + box-shadow: var(--shadow); + cursor: pointer; } button:hover { - filter: brightness(90%); - box-shadow: none; + filter: brightness(90%); + box-shadow: none; } button:disabled { - background-color: lightgray; - pointer-events: none; - box-shadow: none; + background-color: lightgray; + pointer-events: none; + box-shadow: none; } button .material-icons { - margin: -0.25rem; + margin: -0.25rem; } .btn-green { - background-color: var(--btn-green); + background-color: var(--btn-green); } .btn-red { - background-color: var(--btn-red); + background-color: var(--btn-red); } .btn-blue { - background-color: var(--btn-blue); + background-color: var(--btn-blue); } .btn-turquoise { - background-color: var(--btn-turquoise); + background-color: var(--btn-turquoise); } .font-white { - color: var(--font-white); + color: var(--font-white); } .btn-yellow { - background-color: var(--selected-color); + background-color: var(--selected-color); } @media (max-width: 1300px) { - button { - padding: var(--btn-padding-med); - /* font-size: 90px; */ - } - - .material-icons { - font-size: larger; - } - - .under-video-area button { - /* font-size: 30px; */ - padding: var(--btn-padding); - gap: 10px; - } + button { + padding: var(--btn-padding-med); + /* font-size: 90px; */ + } + + .material-icons { + font-size: larger; + } + + .under-video-area button { + /* font-size: 30px; */ + padding: var(--btn-padding); + gap: 10px; + } } diff --git a/src/pages/operator/html/index.html b/src/pages/operator/html/index.html index 0716ea62..b7956157 100644 --- a/src/pages/operator/html/index.html +++ b/src/pages/operator/html/index.html @@ -1,23 +1,23 @@ - - - Stretch Web Interface - - - - -
-
-
-

Loading...

-
-
- + + + Stretch Web Interface + + + + +
+
+
+

Loading...

+
+
+ diff --git a/src/pages/operator/tsx/MobileOperator.tsx b/src/pages/operator/tsx/MobileOperator.tsx index 7173844c..a0a93971 100644 --- a/src/pages/operator/tsx/MobileOperator.tsx +++ b/src/pages/operator/tsx/MobileOperator.tsx @@ -1,29 +1,29 @@ import React, { PointerEventHandler, useState } from "react"; import { - ActionMode, - ButtonPadIdMobile, - CameraViewId, - ComponentDefinition, - ComponentType, - MapDefinition, + ActionMode, + ButtonPadIdMobile, + CameraViewId, + ComponentDefinition, + ComponentType, + MapDefinition, } from "./utils/component_definitions"; import { - className, - ActionState as MoveBaseState, - RemoteStream, + className, + ActionState as MoveBaseState, + RemoteStream, } from "shared/util"; import { - buttonFunctionProvider, - hasBetaTeleopKit, - stretchTool, - movementRecorderFunctionProvider, - underMapFunctionProvider, - underVideoFunctionProvider, + buttonFunctionProvider, + hasBetaTeleopKit, + stretchTool, + movementRecorderFunctionProvider, + underMapFunctionProvider, + underVideoFunctionProvider, } from "."; import { - ButtonPadButton, - ButtonState, - ButtonStateMap, + ButtonPadButton, + ButtonState, + ButtonStateMap, } from "./function_providers/ButtonFunctionProvider"; import { StorageHandler } from "./storage_handler/StorageHandler"; import { FunctionProvider } from "./function_providers/FunctionProvider"; @@ -37,8 +37,8 @@ import { Map } from "./layout_components/Map"; import { TabGroup } from "./basic_components/TabGroup"; import { RadioFunctions, RadioGroup } from "./basic_components/RadioGroup"; import { - MovementRecorder, - MovementRecorderFunction, + MovementRecorder, + MovementRecorderFunction, } from "./layout_components/MovementRecorder"; import { CheckToggleButton } from "./basic_components/CheckToggleButton"; import { UnderVideoButton } from "./function_providers/UnderVideoFunctionProvider"; @@ -46,326 +46,336 @@ import { Alert } from "./basic_components/Alert"; /** Operator interface webpage */ export const MobileOperator = (props: { - remoteStreams: Map; - storageHandler: StorageHandler; + remoteStreams: Map; + storageHandler: StorageHandler; }) => { - const [buttonCollision, setButtonCollision] = React.useState< - ButtonPadButton[] - >([]); - const [moveBaseState, setMoveBaseState] = React.useState(); - const [cameraID, setCameraID] = React.useState( - CameraViewId.realsense, - ); - const [velocityScale, setVelocityScale] = React.useState(0.8); - const [hideMap, setHideMap] = React.useState(true); - const [hideControls, setHideControls] = React.useState(false); - const [activeMainGroupTab, setActiveMainGroupTab] = React.useState(0); - const [activeControlTab, setActiveControlTab] = React.useState(0); - const [isRecording, setIsRecording] = React.useState(); - const [depthSensing, setDepthSensing] = React.useState(false); - const [showAlert, setShowAlert] = React.useState(true); + const [buttonCollision, setButtonCollision] = React.useState< + ButtonPadButton[] + >([]); + const [moveBaseState, setMoveBaseState] = React.useState(); + const [cameraID, setCameraID] = React.useState( + CameraViewId.realsense, + ); + const [velocityScale, setVelocityScale] = React.useState(0.8); + const [hideMap, setHideMap] = React.useState(true); + const [hideControls, setHideControls] = React.useState(false); + const [activeMainGroupTab, setActiveMainGroupTab] = + React.useState(0); + const [activeControlTab, setActiveControlTab] = React.useState(0); + const [isRecording, setIsRecording] = React.useState(); + const [depthSensing, setDepthSensing] = React.useState(false); + const [showAlert, setShowAlert] = React.useState(true); - React.useEffect(() => { - setTimeout(function () { - setShowAlert(false); - }, 5000); - }, []); + React.useEffect(() => { + setTimeout(function () { + setShowAlert(false); + }, 5000); + }, []); - FunctionProvider.actionMode = ActionMode.PressAndHold; + FunctionProvider.actionMode = ActionMode.PressAndHold; - // Just used as a flag to force the operator to rerender when the button state map - // has been updated - const [buttonStateMapRerender, setButtonStateMapRerender] = - React.useState(false); - const buttonStateMap = React.useRef(); - function operatorCallback(bsm: ButtonStateMap) { - let collisionButtons: ButtonPadButton[] = []; - bsm.forEach((state, button) => { - if (state == ButtonState.Collision) collisionButtons.push(button); - }); - setButtonCollision(collisionButtons); - if (bsm !== buttonStateMap.current) { - buttonStateMap.current = bsm; - setButtonStateMapRerender(!buttonStateMapRerender); + // Just used as a flag to force the operator to rerender when the button state map + // has been updated + const [buttonStateMapRerender, setButtonStateMapRerender] = + React.useState(false); + const buttonStateMap = React.useRef(); + function operatorCallback(bsm: ButtonStateMap) { + let collisionButtons: ButtonPadButton[] = []; + bsm.forEach((state, button) => { + if (state == ButtonState.Collision) collisionButtons.push(button); + }); + setButtonCollision(collisionButtons); + if (bsm !== buttonStateMap.current) { + buttonStateMap.current = bsm; + setButtonStateMapRerender(!buttonStateMapRerender); + } } - } - buttonFunctionProvider.setOperatorCallback(operatorCallback); + buttonFunctionProvider.setOperatorCallback(operatorCallback); - // Just used as a flag to force the operator to rerender when the tablet orientation - // changes. - const [tabletOrientationRerender, setTabletOrientationRerender] = - React.useState(false); - underVideoFunctionProvider.setTabletOrientationOperatorCallback((_) => { - setTabletOrientationRerender(!tabletOrientationRerender); - }); + // Just used as a flag to force the operator to rerender when the tablet orientation + // changes. + const [tabletOrientationRerender, setTabletOrientationRerender] = + React.useState(false); + underVideoFunctionProvider.setTabletOrientationOperatorCallback((_) => { + setTabletOrientationRerender(!tabletOrientationRerender); + }); - function moveBaseStateCallback(state: MoveBaseState) { - setMoveBaseState(state); - } - underMapFunctionProvider.setOperatorCallback(moveBaseStateCallback); - let moveBaseAlertTimeout: NodeJS.Timeout; - React.useEffect(() => { - if (moveBaseState && moveBaseState.alertType != "info") { - if (moveBaseAlertTimeout) clearTimeout(moveBaseAlertTimeout); - moveBaseAlertTimeout = setTimeout(() => { - setMoveBaseState(undefined); - }, 5000); + function moveBaseStateCallback(state: MoveBaseState) { + setMoveBaseState(state); } - }, [moveBaseState]); + underMapFunctionProvider.setOperatorCallback(moveBaseStateCallback); + let moveBaseAlertTimeout: NodeJS.Timeout; + React.useEffect(() => { + if (moveBaseState && moveBaseState.alertType != "info") { + if (moveBaseAlertTimeout) clearTimeout(moveBaseAlertTimeout); + moveBaseAlertTimeout = setTimeout(() => { + setMoveBaseState(undefined); + }, 5000); + } + }, [moveBaseState]); - let remoteStreams = props.remoteStreams; + let remoteStreams = props.remoteStreams; - /** State passed from the operator and shared by all components */ - const sharedState: SharedState = { - customizing: false, - onSelect: () => {}, - remoteStreams: remoteStreams, - selectedPath: "deselected", - dropZoneState: { - onDrop: () => {}, - selectedDefinition: undefined, - }, - buttonStateMap: buttonStateMap.current, - hideLabels: false, - hasBetaTeleopKit: hasBetaTeleopKit, - stretchTool: stretchTool, - }; + /** State passed from the operator and shared by all components */ + const sharedState: SharedState = { + customizing: false, + onSelect: () => {}, + remoteStreams: remoteStreams, + selectedPath: "deselected", + dropZoneState: { + onDrop: () => {}, + selectedDefinition: undefined, + }, + buttonStateMap: buttonStateMap.current, + hideLabels: false, + hasBetaTeleopKit: hasBetaTeleopKit, + stretchTool: stretchTool, + }; - function updateScreens() { - if (hideMap) { - setHideMap(false); - setHideControls(true); - } else { - setHideControls(false); - setHideMap(true); + function updateScreens() { + if (hideMap) { + setHideMap(false); + setHideControls(true); + } else { + setHideControls(false); + setHideMap(true); + } } - } - const swipeHandlers = Swipe({ - onSwipedLeft: () => updateScreens(), - onSwipedRight: () => updateScreens(), - }); + const swipeHandlers = Swipe({ + onSwipedLeft: () => updateScreens(), + onSwipedRight: () => updateScreens(), + }); - const driveMode = (show: boolean) => { - return show ? ( - - {/* { + return show ? ( + + {/* */} - - - ) : ( - <> - ); - }; + + + ) : ( + <> + ); + }; - const armMode = (show: boolean) => { - return show ? ( - - - - ) : ( - <> - ); - }; + const armMode = (show: boolean) => { + return show ? ( + + + + ) : ( + <> + ); + }; - const gripperMode = (show: boolean) => { - return show ? ( - - - - ) : ( - <> - ); - }; + const gripperMode = (show: boolean) => { + return show ? ( + + + + ) : ( + <> + ); + }; - const ControlModes = () => { - return ( - <> -
- Slow - { - setVelocityScale(FunctionProvider.velocityScale); - }} - onChange={(event) => { - FunctionProvider.velocityScale = Number(event.target.value); - }} - /> - Fast -
- setActiveControlTab(index)} - pill={true} - key={"controls-group"} - /> - - ); - }; + const ControlModes = () => { + return ( + <> +
+ Slow + { + setVelocityScale(FunctionProvider.velocityScale); + }} + onChange={(event) => { + FunctionProvider.velocityScale = Number( + event.target.value, + ); + }} + /> + Fast +
+ setActiveControlTab(index)} + pill={true} + key={"controls-group"} + /> + + ); + }; - const controlModes = (show: boolean) => { - return show ? : <>; - }; - const recordingList = (show: boolean) => { - return ( - - ); - }; + const controlModes = (show: boolean) => { + return show ? : <>; + }; + const recordingList = (show: boolean) => { + return ( + + ); + }; - return ( -
e.preventDefault()}> -
- {showAlert ? ( -
- - Beta feature, use at your own risk - -
- ) : ( - <> - )} -
-
- - -
- {cameraID == CameraViewId.realsense && ( -
- { - setDepthSensing(!depthSensing); - underVideoFunctionProvider.provideFunctions( - UnderVideoButton.DepthSensing, - ).onCheck!(!depthSensing); - }} - label="Depth Sensing" - /> + return ( +
e.preventDefault()}> +
+ {showAlert ? ( +
+ + Beta feature, use at your own risk + +
+ ) : ( + <> + )} +
+
+ + +
+ {cameraID == CameraViewId.realsense && ( +
+ { + setDepthSensing(!depthSensing); + underVideoFunctionProvider.provideFunctions( + UnderVideoButton.DepthSensing, + ).onCheck!(!depthSensing); + }} + label="Depth Sensing" + /> +
+ )} + + {/*
*/} +
+ +
+ + setActiveMainGroupTab(index) + } + pill={false} + key={"main-group"} + /> +
+ {/*
*/} +
+
+ +
+ +
- )} - - {/*
*/} -
- -
- setActiveMainGroupTab(index)} - pill={false} - key={"main-group"} - />
- {/*
*/} -
-
- -
- -
-
-
- ); + ); }; diff --git a/src/pages/operator/tsx/Operator.tsx b/src/pages/operator/tsx/Operator.tsx index 309427d5..9ae18d8a 100644 --- a/src/pages/operator/tsx/Operator.tsx +++ b/src/pages/operator/tsx/Operator.tsx @@ -6,34 +6,34 @@ import { CustomizeButton } from "./static_components/CustomizeButton"; import { GlobalOptionsProps, Sidebar } from "./static_components/Sidebar"; import { SharedState } from "./layout_components/CustomizableComponent"; import { - ActionMode, - ComponentDefinition, - LayoutDefinition, + ActionMode, + ComponentDefinition, + LayoutDefinition, } from "./utils/component_definitions"; import { className, ActionState, RemoteStream, RobotPose } from "shared/util"; import { - buttonFunctionProvider, - underMapFunctionProvider, - underVideoFunctionProvider, - hasBetaTeleopKit, - stretchTool, + buttonFunctionProvider, + underMapFunctionProvider, + underVideoFunctionProvider, + hasBetaTeleopKit, + stretchTool, } from "."; import { - ButtonPadButton, - ButtonState, - ButtonStateMap, + ButtonPadButton, + ButtonState, + ButtonStateMap, } from "./function_providers/ButtonFunctionProvider"; import { Dropdown } from "./basic_components/Dropdown"; import { - DEFAULT_LAYOUTS, - DefaultLayoutName, - StorageHandler, + DEFAULT_LAYOUTS, + DefaultLayoutName, + StorageHandler, } from "./storage_handler/StorageHandler"; import { FunctionProvider } from "./function_providers/FunctionProvider"; import { - addToLayout, - moveInLayout, - removeFromLayout, + addToLayout, + moveInLayout, + removeFromLayout, } from "./utils/layout_helpers"; import { MovementRecorder } from "./layout_components/MovementRecorder"; import { Alert } from "./basic_components/Alert"; @@ -42,359 +42,365 @@ import { TextToSpeech } from "./layout_components/TextToSpeech"; /** Operator interface webpage */ export const Operator = (props: { - remoteStreams: Map; - layout: LayoutDefinition; - storageHandler: StorageHandler; + remoteStreams: Map; + layout: LayoutDefinition; + storageHandler: StorageHandler; }) => { - const [customizing, setCustomizing] = React.useState(false); - const [selectedPath, setSelectedPath] = React.useState( - undefined, - ); - const [selectedDefinition, setSelectedDef] = React.useState< - ComponentDefinition | undefined - >(undefined); - const [velocityScale, setVelocityScale] = React.useState( - FunctionProvider.velocityScale, - ); - const [buttonCollision, setButtonCollision] = React.useState< - ButtonPadButton[] - >([]); - const [moveBaseState, setMoveBaseState] = React.useState(); - const [moveToPregraspState, setMoveToPregraspState] = - React.useState(); + const [customizing, setCustomizing] = React.useState(false); + const [selectedPath, setSelectedPath] = React.useState( + undefined, + ); + const [selectedDefinition, setSelectedDef] = React.useState< + ComponentDefinition | undefined + >(undefined); + const [velocityScale, setVelocityScale] = React.useState( + FunctionProvider.velocityScale, + ); + const [buttonCollision, setButtonCollision] = React.useState< + ButtonPadButton[] + >([]); + const [moveBaseState, setMoveBaseState] = React.useState(); + const [moveToPregraspState, setMoveToPregraspState] = + React.useState(); - const layout = React.useRef(props.layout); + const layout = React.useRef(props.layout); - // Just used as a flag to force the operator to rerender when the button state map - // has been updated - const [buttonStateMapRerender, setButtonStateMapRerender] = - React.useState(false); - const buttonStateMap = React.useRef(); - function operatorCallback(bsm: ButtonStateMap) { - let collisionButtons: ButtonPadButton[] = []; - bsm.forEach((state, button) => { - if (state == ButtonState.Collision) collisionButtons.push(button); - }); - setButtonCollision(collisionButtons); - buttonStateMap.current = bsm; - setButtonStateMapRerender(!buttonStateMapRerender); - } - buttonFunctionProvider.setOperatorCallback(operatorCallback); + // Just used as a flag to force the operator to rerender when the button state map + // has been updated + const [buttonStateMapRerender, setButtonStateMapRerender] = + React.useState(false); + const buttonStateMap = React.useRef(); + function operatorCallback(bsm: ButtonStateMap) { + let collisionButtons: ButtonPadButton[] = []; + bsm.forEach((state, button) => { + if (state == ButtonState.Collision) collisionButtons.push(button); + }); + setButtonCollision(collisionButtons); + buttonStateMap.current = bsm; + setButtonStateMapRerender(!buttonStateMapRerender); + } + buttonFunctionProvider.setOperatorCallback(operatorCallback); - // Just used as a flag to force the operator to rerender when the tablet orientation - // changes. - const [tabletOrientationRerender, setTabletOrientationRerender] = - React.useState(false); - underVideoFunctionProvider.setTabletOrientationOperatorCallback((_) => { - setTabletOrientationRerender(!tabletOrientationRerender); - }); + // Just used as a flag to force the operator to rerender when the tablet orientation + // changes. + const [tabletOrientationRerender, setTabletOrientationRerender] = + React.useState(false); + underVideoFunctionProvider.setTabletOrientationOperatorCallback((_) => { + setTabletOrientationRerender(!tabletOrientationRerender); + }); - // Callback for when the move base state is updated (e.g., the ROS2 action returns) - // Used to render alerts to the operator. - function moveBaseStateCallback(state: ActionState) { - setMoveBaseState(state); - } - underMapFunctionProvider.setOperatorCallback(moveBaseStateCallback); - let moveBaseAlertTimeout: NodeJS.Timeout; - React.useEffect(() => { - if (moveBaseState && moveBaseState.alert_type != "info") { - if (moveBaseAlertTimeout) clearTimeout(moveBaseAlertTimeout); - moveBaseAlertTimeout = setTimeout(() => { - setMoveBaseState(undefined); - }, 5000); + // Callback for when the move base state is updated (e.g., the ROS2 action returns) + // Used to render alerts to the operator. + function moveBaseStateCallback(state: ActionState) { + setMoveBaseState(state); } - }, [moveBaseState]); + underMapFunctionProvider.setOperatorCallback(moveBaseStateCallback); + let moveBaseAlertTimeout: NodeJS.Timeout; + React.useEffect(() => { + if (moveBaseState && moveBaseState.alert_type != "info") { + if (moveBaseAlertTimeout) clearTimeout(moveBaseAlertTimeout); + moveBaseAlertTimeout = setTimeout(() => { + setMoveBaseState(undefined); + }, 5000); + } + }, [moveBaseState]); - // Callback for when the move to pregrasp state is updated (e.g., the ROS2 action returns) - // Used to render alerts to the operator. - function moveToPregraspStateCallback(state: ActionState) { - setMoveToPregraspState(state); - } - underVideoFunctionProvider.setMoveToPregraspOperatorCallback( - moveToPregraspStateCallback, - ); - let moveToPregraspAlertTimeout: NodeJS.Timeout; - React.useEffect(() => { - if (moveToPregraspState && moveToPregraspState.alert_type != "info") { - if (moveToPregraspAlertTimeout) clearTimeout(moveToPregraspAlertTimeout); - moveToPregraspAlertTimeout = setTimeout(() => { - setMoveToPregraspState(undefined); - }, 5000); + // Callback for when the move to pregrasp state is updated (e.g., the ROS2 action returns) + // Used to render alerts to the operator. + function moveToPregraspStateCallback(state: ActionState) { + setMoveToPregraspState(state); } - }, [moveToPregraspState]); + underVideoFunctionProvider.setMoveToPregraspOperatorCallback( + moveToPregraspStateCallback, + ); + let moveToPregraspAlertTimeout: NodeJS.Timeout; + React.useEffect(() => { + if (moveToPregraspState && moveToPregraspState.alert_type != "info") { + if (moveToPregraspAlertTimeout) + clearTimeout(moveToPregraspAlertTimeout); + moveToPregraspAlertTimeout = setTimeout(() => { + setMoveToPregraspState(undefined); + }, 5000); + } + }, [moveToPregraspState]); - let remoteStreams = props.remoteStreams; + let remoteStreams = props.remoteStreams; - /** Rerenders the operator */ - function updateLayout() { - console.log("update layout"); - setButtonStateMapRerender(!buttonStateMapRerender); - setTabletOrientationRerender(!tabletOrientationRerender); - } + /** Rerenders the operator */ + function updateLayout() { + console.log("update layout"); + setButtonStateMapRerender(!buttonStateMapRerender); + setTabletOrientationRerender(!tabletOrientationRerender); + } - /** - * Updates the action mode in the layout (visually) and in the function - * provider (functionally). - */ - function setActionMode(actionMode: ActionMode) { - layout.current.actionMode = actionMode; - FunctionProvider.actionMode = actionMode; - props.storageHandler.saveCurrentLayout(layout.current); - updateLayout(); - } + /** + * Updates the action mode in the layout (visually) and in the function + * provider (functionally). + */ + function setActionMode(actionMode: ActionMode) { + layout.current.actionMode = actionMode; + FunctionProvider.actionMode = actionMode; + props.storageHandler.saveCurrentLayout(layout.current); + updateLayout(); + } - /** - * Sets the movement recorder component to display or hidden. - * - * @param displayMovementRecorder if the movement recorder component at the - * top of the operator body should be displayed - */ - function setDisplayMovementRecorder(displayMovementRecorder: boolean) { - layout.current.displayMovementRecorder = displayMovementRecorder; - updateLayout(); - } + /** + * Sets the movement recorder component to display or hidden. + * + * @param displayMovementRecorder if the movement recorder component at the + * top of the operator body should be displayed + */ + function setDisplayMovementRecorder(displayMovementRecorder: boolean) { + layout.current.displayMovementRecorder = displayMovementRecorder; + updateLayout(); + } - /** - * Sets the text-to-speech component to display or hidden. - * - * @param displayTextToSpeech whether the text-to-speech component should - * be displayed. - */ - function setDisplayTextToSpeech(displayTextToSpeech: boolean) { - layout.current.displayTextToSpeech = displayTextToSpeech; - updateLayout(); - } + /** + * Sets the text-to-speech component to display or hidden. + * + * @param displayTextToSpeech whether the text-to-speech component should + * be displayed. + */ + function setDisplayTextToSpeech(displayTextToSpeech: boolean) { + layout.current.displayTextToSpeech = displayTextToSpeech; + updateLayout(); + } - /** - * Sets the display labels property to display or hidden. - * - * @param displayLabels if the button text labels should be displayed - */ - function setDisplayLabels(displayLabels: boolean) { - layout.current.displayLabels = displayLabels; - updateLayout(); - } + /** + * Sets the display labels property to display or hidden. + * + * @param displayLabels if the button text labels should be displayed + */ + function setDisplayLabels(displayLabels: boolean) { + layout.current.displayLabels = displayLabels; + updateLayout(); + } - /** - * Callback when the user clicks on a drop zone, moves the active component - * into the drop zone - * @param path path to the clicked drop zone - */ - function handleDrop(path: string) { - console.log("handleDrop", path); - if (!selectedDefinition) - throw Error("Active definition undefined on drop event"); - let newPath: string = path; - if (!selectedPath) { - // New element not already in the layout - newPath = addToLayout(selectedDefinition, path, layout.current); - } else { - newPath = moveInLayout(selectedPath, path, layout.current); + /** + * Callback when the user clicks on a drop zone, moves the active component + * into the drop zone + * @param path path to the clicked drop zone + */ + function handleDrop(path: string) { + console.log("handleDrop", path); + if (!selectedDefinition) + throw Error("Active definition undefined on drop event"); + let newPath: string = path; + if (!selectedPath) { + // New element not already in the layout + newPath = addToLayout(selectedDefinition, path, layout.current); + } else { + newPath = moveInLayout(selectedPath, path, layout.current); + } + setSelectedPath(newPath); + console.log("new active path", newPath); + updateLayout(); } - setSelectedPath(newPath); - console.log("new active path", newPath); - updateLayout(); - } - /** - * Callback when a component is selected during customization - * @param path path to the selected component - * @param def definition of the selected component - */ - function handleSelect(def: ComponentDefinition, path?: string) { - console.log("selected", path); - if (!customizing) return; + /** + * Callback when a component is selected during customization + * @param path path to the selected component + * @param def definition of the selected component + */ + function handleSelect(def: ComponentDefinition, path?: string) { + console.log("selected", path); + if (!customizing) return; - // If reselected the same component at the same path, or the same component - // without a path from the sidebar, then unactivate it - const pathsMatch = selectedPath && selectedPath == path; - const defsMatch = - !selectedPath && - def.type === selectedDefinition?.type && - def.id === selectedDefinition?.id; - if (pathsMatch || defsMatch) { - setSelectedDef(undefined); - setSelectedPath(undefined); - return; + // If reselected the same component at the same path, or the same component + // without a path from the sidebar, then unactivate it + const pathsMatch = selectedPath && selectedPath == path; + const defsMatch = + !selectedPath && + def.type === selectedDefinition?.type && + def.id === selectedDefinition?.id; + if (pathsMatch || defsMatch) { + setSelectedDef(undefined); + setSelectedPath(undefined); + return; + } + + // Activate the selected component + setSelectedDef(def); + setSelectedPath(path); } - // Activate the selected component - setSelectedDef(def); - setSelectedPath(path); - } + /** Callback when the delete button in the sidebar is clicked */ + function handleDelete() { + if (!selectedPath) + throw Error("handleDelete called when selectedPath is undefined"); + removeFromLayout(selectedPath, layout.current); + updateLayout(); + setSelectedPath(undefined); + setSelectedDef(undefined); + } - /** Callback when the delete button in the sidebar is clicked */ - function handleDelete() { - if (!selectedPath) - throw Error("handleDelete called when selectedPath is undefined"); - removeFromLayout(selectedPath, layout.current); - updateLayout(); - setSelectedPath(undefined); - setSelectedDef(undefined); - } + /** + * Callback when the customization button is clicked. + */ + const handleToggleCustomize = () => { + if (customizing) { + console.log("saving layout"); + props.storageHandler.saveCurrentLayout(layout.current); + } + setCustomizing(!customizing); + setSelectedDef(undefined); + setSelectedPath(undefined); + }; - /** - * Callback when the customization button is clicked. - */ - const handleToggleCustomize = () => { - if (customizing) { - console.log("saving layout"); - props.storageHandler.saveCurrentLayout(layout.current); + /** Un-select current component when click inside of header */ + function handleClickHeader() { + setSelectedDef(undefined); + setSelectedPath(undefined); } - setCustomizing(!customizing); - setSelectedDef(undefined); - setSelectedPath(undefined); - }; - /** Un-select current component when click inside of header */ - function handleClickHeader() { - setSelectedDef(undefined); - setSelectedPath(undefined); - } + /** State passed from the operator and shared by all components */ + const sharedState: SharedState = { + customizing: customizing, + onSelect: handleSelect, + remoteStreams: remoteStreams, + selectedPath: selectedPath, + dropZoneState: { + onDrop: handleDrop, + selectedDefinition: selectedDefinition, + }, + buttonStateMap: buttonStateMap.current, + hideLabels: !layout.current.displayLabels, + hasBetaTeleopKit: hasBetaTeleopKit, + stretchTool: stretchTool, + }; - /** State passed from the operator and shared by all components */ - const sharedState: SharedState = { - customizing: customizing, - onSelect: handleSelect, - remoteStreams: remoteStreams, - selectedPath: selectedPath, - dropZoneState: { - onDrop: handleDrop, - selectedDefinition: selectedDefinition, - }, - buttonStateMap: buttonStateMap.current, - hideLabels: !layout.current.displayLabels, - hasBetaTeleopKit: hasBetaTeleopKit, - stretchTool: stretchTool, - }; + /** Properties for the global options area of the sidebar */ + const globalOptionsProps: GlobalOptionsProps = { + displayMovementRecorder: layout.current.displayMovementRecorder, + displayTextToSpeech: layout.current.displayTextToSpeech, + displayLabels: layout.current.displayLabels, + setDisplayMovementRecorder: setDisplayMovementRecorder, + setDisplayTextToSpeech: setDisplayTextToSpeech, + setDisplayLabels: setDisplayLabels, + defaultLayouts: Object.keys(DEFAULT_LAYOUTS), + customLayouts: props.storageHandler.getCustomLayoutNames(), + loadLayout: (layoutName: string, dflt: boolean) => { + layout.current = dflt + ? props.storageHandler.loadDefaultLayout( + layoutName as DefaultLayoutName, + ) + : props.storageHandler.loadCustomLayout(layoutName); + updateLayout(); + }, + saveLayout: (layoutName: string) => { + props.storageHandler.saveCustomLayout(layout.current, layoutName); + }, + }; - /** Properties for the global options area of the sidebar */ - const globalOptionsProps: GlobalOptionsProps = { - displayMovementRecorder: layout.current.displayMovementRecorder, - displayTextToSpeech: layout.current.displayTextToSpeech, - displayLabels: layout.current.displayLabels, - setDisplayMovementRecorder: setDisplayMovementRecorder, - setDisplayTextToSpeech: setDisplayTextToSpeech, - setDisplayLabels: setDisplayLabels, - defaultLayouts: Object.keys(DEFAULT_LAYOUTS), - customLayouts: props.storageHandler.getCustomLayoutNames(), - loadLayout: (layoutName: string, dflt: boolean) => { - layout.current = dflt - ? props.storageHandler.loadDefaultLayout( - layoutName as DefaultLayoutName, - ) - : props.storageHandler.loadCustomLayout(layoutName); - updateLayout(); - }, - saveLayout: (layoutName: string) => { - props.storageHandler.saveCustomLayout(layout.current, layoutName); - }, - }; + const actionModes = Object.values(ActionMode); - const actionModes = Object.values(ActionMode); - - return ( -
-
- {/* Action mode button */} - setActionMode(actionModes[idx])} - selectedIndex={actionModes.indexOf(layout.current.actionMode)} - possibleOptions={actionModes} - showActive - placement="bottom" - /> - - { - setVelocityScale(newScale); - FunctionProvider.velocityScale = newScale; - }} - /> - -
- { -
-
0, - fadeOut: buttonCollision.length == 0, - })} - > - - - {buttonCollision.length > 0 - ? buttonCollision.join(", ") + " in collision!" - : ""} - - -
-
- } - {moveBaseState && ( -
-
- +
+ {/* Action mode button */} + setActionMode(actionModes[idx])} + selectedIndex={actionModes.indexOf( + layout.current.actionMode, + )} + possibleOptions={actionModes} + showActive + placement="bottom" + /> + + { + setVelocityScale(newScale); + FunctionProvider.velocityScale = newScale; + }} + /> + +
+ { +
+
0, + fadeOut: buttonCollision.length == 0, + })} + > + + + {buttonCollision.length > 0 + ? buttonCollision.join(", ") + + " in collision!" + : ""} + + +
+
+ } + {moveBaseState && ( +
+
+ +
+
+ )} + {moveToPregraspState && ( +
+
+ +
+
+ )} +
+ + +
+
+ +
+
-
- )} - {moveToPregraspState && ( -
-
- -
-
- )} -
- - -
-
- -
-
- ); + ); }; diff --git a/src/pages/operator/tsx/basic_components/AccordionSelect.tsx b/src/pages/operator/tsx/basic_components/AccordionSelect.tsx index 889e89da..af1b1eac 100644 --- a/src/pages/operator/tsx/basic_components/AccordionSelect.tsx +++ b/src/pages/operator/tsx/basic_components/AccordionSelect.tsx @@ -3,61 +3,61 @@ import "operator/css/basic_components.css"; import { className } from "shared/util"; export const AccordionSelect = (props: { - title: string; - possibleOptions: T[]; - backgroundColor?: string; - onChange: (selectedIndex: number) => void; - toggleAccordianCallback?: () => void; + title: string; + possibleOptions: T[]; + backgroundColor?: string; + onChange: (selectedIndex: number) => void; + toggleAccordianCallback?: () => void; }) => { - const [active, setActiveState] = useState(false); - const [height, setHeightState] = useState("0px"); - const [rotate, setRotateState] = useState("accordion_icon"); - const content = useRef(null); + const [active, setActiveState] = useState(false); + const [height, setHeightState] = useState("0px"); + const [rotate, setRotateState] = useState("accordion_icon"); + const content = useRef(null); - function toggleAccordion() { - if (props.toggleAccordianCallback) { - props.toggleAccordianCallback(); + function toggleAccordion() { + if (props.toggleAccordianCallback) { + props.toggleAccordianCallback(); + } + setActiveState(active ? false : true); + setHeightState(active ? "0px" : `${content.current.scrollHeight}px`); + setRotateState(active ? "accordion_icon" : "accordion_icon rotate"); + } + + function mapFunc(option: T, idx: number) { + return ( +
{ + props.onChange(idx); + toggleAccordion(); + }} + > + {option} +
+ ); } - setActiveState(active ? false : true); - setHeightState(active ? "0px" : `${content.current.scrollHeight}px`); - setRotateState(active ? "accordion_icon" : "accordion_icon rotate"); - } - function mapFunc(option: T, idx: number) { return ( -
{ - props.onChange(idx); - toggleAccordion(); - }} - > - {option} -
+
+ +
+
{props.possibleOptions.map(mapFunc)}
+
+
); - } - - return ( -
- -
-
{props.possibleOptions.map(mapFunc)}
-
-
- ); }; diff --git a/src/pages/operator/tsx/basic_components/Alert.tsx b/src/pages/operator/tsx/basic_components/Alert.tsx index 87c14961..086b7817 100644 --- a/src/pages/operator/tsx/basic_components/Alert.tsx +++ b/src/pages/operator/tsx/basic_components/Alert.tsx @@ -5,26 +5,26 @@ import "operator/css/Alert.css"; // https://blog.logrocket.com/create-custom-react-alert-message/ export const Alert = (props: { - children?: ReactElement>; - type: string; - message?: string; + children?: ReactElement>; + type: string; + message?: string; }) => { - const [isShow, setIsShow] = useState(true); + const [isShow, setIsShow] = useState(true); - function renderElAlert() { - return React.cloneElement(props.children!); - } + function renderElAlert() { + return React.cloneElement(props.children!); + } - React.useEffect(() => { - setIsShow(true); - }, [props]); + React.useEffect(() => { + setIsShow(true); + }, [props]); - return ( -
- setIsShow(false)}> - × - - {props.children ? renderElAlert() : props.message} -
- ); + return ( +
+ setIsShow(false)}> + × + + {props.children ? renderElAlert() : props.message} +
+ ); }; diff --git a/src/pages/operator/tsx/basic_components/CheckToggleButton.tsx b/src/pages/operator/tsx/basic_components/CheckToggleButton.tsx index c2397e6e..69cee64d 100644 --- a/src/pages/operator/tsx/basic_components/CheckToggleButton.tsx +++ b/src/pages/operator/tsx/basic_components/CheckToggleButton.tsx @@ -7,17 +7,17 @@ import React from "react"; * Properties for {@link CheckToggleButton} */ type CheckToggleButtonProps = { - /** Toggled on if true, toggled off if false. */ - checked: boolean; - /** - * Function when button is clicked, this should probably toggle the state - * of `checked` - */ - onClick: () => void; - /** - * Text to display on the button to the right of the checkbox. - */ - label: string; + /** Toggled on if true, toggled off if false. */ + checked: boolean; + /** + * Function when button is clicked, this should probably toggle the state + * of `checked` + */ + onClick: () => void; + /** + * Text to display on the button to the right of the checkbox. + */ + label: string; }; /** @@ -27,18 +27,18 @@ type CheckToggleButtonProps = { * @param props {@link CheckToggleButtonProps} */ export const CheckToggleButton = (props: CheckToggleButtonProps) => { - const { checked } = props; - const icon = checked ? "check_box" : "check_box_outline_blank"; - return ( - - ); + const { checked } = props; + const icon = checked ? "check_box" : "check_box_outline_blank"; + return ( + + ); }; diff --git a/src/pages/operator/tsx/basic_components/Dropdown.tsx b/src/pages/operator/tsx/basic_components/Dropdown.tsx index 6178c212..6eb1f0b1 100644 --- a/src/pages/operator/tsx/basic_components/Dropdown.tsx +++ b/src/pages/operator/tsx/basic_components/Dropdown.tsx @@ -3,93 +3,93 @@ import { className } from "shared/util"; import "operator/css/basic_components.css"; export const Dropdown = (props: { - onChange: (selectedIndex: number) => void; - possibleOptions: T[]; - selectedIndex?: number; - placeholderText?: string; - showActive?: boolean; - placement: string; + onChange: (selectedIndex: number) => void; + possibleOptions: T[]; + selectedIndex?: number; + placeholderText?: string; + showActive?: boolean; + placement: string; }) => { - const [showDropdown, setShowDropdown] = React.useState(false); - const [placement, setPlacement] = React.useState(props.placement); - const inputRef = React.useRef(null); - const dropdownPopupRef = React.useRef(null); - if (props.selectedIndex === undefined && !props.placeholderText) - throw Error("both selectedOption and placeholderText undefined"); + const [showDropdown, setShowDropdown] = React.useState(false); + const [placement, setPlacement] = React.useState(props.placement); + const inputRef = React.useRef(null); + const dropdownPopupRef = React.useRef(null); + if (props.selectedIndex === undefined && !props.placeholderText) + throw Error("both selectedOption and placeholderText undefined"); - // Handler to close dropdown when click outside - React.useEffect(() => { - const handler = (e: any) => { - if (inputRef.current && !inputRef.current.contains(e.target)) { - setShowDropdown(false); - } - }; - if (showDropdown) { - window.addEventListener("click", handler); - return () => { - window.removeEventListener("click", handler); - }; - } - }); + // Handler to close dropdown when click outside + React.useEffect(() => { + const handler = (e: any) => { + if (inputRef.current && !inputRef.current.contains(e.target)) { + setShowDropdown(false); + } + }; + if (showDropdown) { + window.addEventListener("click", handler); + return () => { + window.removeEventListener("click", handler); + }; + } + }); - // Function to convert each possible option into a button - function mapFunc(option: T, idx: number) { - const active = idx === props.selectedIndex; - if (active && !props.showActive) return null; - return ( - - ); - } + // Function to convert each possible option into a button + function mapFunc(option: T, idx: number) { + const active = idx === props.selectedIndex; + if (active && !props.showActive) return null; + return ( + + ); + } - // Set the max-height of the popup to the screen height minus the top of the popup - function resizeDropdownPopup() { - if (dropdownPopupRef.current) { - const top = dropdownPopupRef.current.getBoundingClientRect().top; - dropdownPopupRef.current.style.maxHeight = `calc(100vh - ${top}px)`; + // Set the max-height of the popup to the screen height minus the top of the popup + function resizeDropdownPopup() { + if (dropdownPopupRef.current) { + const top = dropdownPopupRef.current.getBoundingClientRect().top; + dropdownPopupRef.current.style.maxHeight = `calc(100vh - ${top}px)`; + } } - } - React.useEffect(resizeDropdownPopup, [showDropdown]); - React.useEffect(() => { - window.addEventListener("resize", resizeDropdownPopup); - return () => { - window.removeEventListener("resize", resizeDropdownPopup); - }; - }); + React.useEffect(resizeDropdownPopup, [showDropdown]); + React.useEffect(() => { + window.addEventListener("resize", resizeDropdownPopup); + return () => { + window.removeEventListener("resize", resizeDropdownPopup); + }; + }); - return ( -
- - -
- ); + return ( +
+ + +
+ ); }; diff --git a/src/pages/operator/tsx/basic_components/DropdownInput.tsx b/src/pages/operator/tsx/basic_components/DropdownInput.tsx index f2a84316..1fee073e 100644 --- a/src/pages/operator/tsx/basic_components/DropdownInput.tsx +++ b/src/pages/operator/tsx/basic_components/DropdownInput.tsx @@ -5,124 +5,127 @@ import e from "express"; import { text } from "stream/consumers"; export const DropdownInput = (props: { - text: string; - setText: (text: string) => void; - selectedIndex?: number; - setSelectedIndex: (index?: number) => void; - possibleOptions: T[]; - placeholderText: string; - placement: string; - rows: number; + text: string; + setText: (text: string) => void; + selectedIndex?: number; + setSelectedIndex: (index?: number) => void; + possibleOptions: T[]; + placeholderText: string; + placement: string; + rows: number; }) => { - const [showDropdown, setShowDropdown] = React.useState(false); - const componentRef = React.useRef(null); - const dropdownPopupRef = React.useRef(null); + const [showDropdown, setShowDropdown] = React.useState(false); + const componentRef = React.useRef(null); + const dropdownPopupRef = React.useRef(null); - // Handler to close dropdown when click outside - React.useEffect(() => { - const handler = (e: any) => { - if (componentRef.current && !componentRef.current.contains(e.target)) { - setShowDropdown(false); - } - }; - if (showDropdown) { - window.addEventListener("click", handler); - return () => { - window.removeEventListener("click", handler); - }; + // Handler to close dropdown when click outside + React.useEffect(() => { + const handler = (e: any) => { + if ( + componentRef.current && + !componentRef.current.contains(e.target) + ) { + setShowDropdown(false); + } + }; + if (showDropdown) { + window.addEventListener("click", handler); + return () => { + window.removeEventListener("click", handler); + }; + } + }); + + // Handler to update the selected index if the possible options or text changes + React.useEffect(() => { + let text = props.text.trim(); + if (props.possibleOptions.includes(text as T)) { + props.setSelectedIndex(props.possibleOptions.indexOf(text as T)); + } else { + props.setSelectedIndex(undefined); + } + }, [props.possibleOptions, props.text]); + + // Function to convert each possible option into a button + function mapFunc(option: T, idx: number) { + const active = idx === props.selectedIndex; + return ( + + ); } - }); - // Handler to update the selected index if the possible options or text changes - React.useEffect(() => { - let text = props.text.trim(); - if (props.possibleOptions.includes(text as T)) { - props.setSelectedIndex(props.possibleOptions.indexOf(text as T)); - } else { - props.setSelectedIndex(undefined); + // Set the max-height of the popup to the screen height minus the top of the popup + function resizeDropdownPopup() { + if (dropdownPopupRef.current) { + const top = dropdownPopupRef.current.getBoundingClientRect().top; + dropdownPopupRef.current.style.maxHeight = `calc(100vh - ${top}px)`; + } } - }, [props.possibleOptions, props.text]); + React.useEffect(resizeDropdownPopup, [showDropdown]); + React.useEffect(() => { + window.addEventListener("resize", resizeDropdownPopup); + return () => { + window.removeEventListener("resize", resizeDropdownPopup); + }; + }); - // Function to convert each possible option into a button - function mapFunc(option: T, idx: number) { - const active = idx === props.selectedIndex; return ( - +
+