Skip to content

Commit

Permalink
Add URDF viewer (#155)
Browse files Browse the repository at this point in the history
* urdf

* drei_bootstrap_error

* converted urdf component to typsecript

* Fix

* custom button and urdf ui

* completed urdf component

* format

* conditional rendering of carousel arrows and fix arrows

* CSS improvements

* user interaction

* url_params

* urdf form

* added urdf packages interface

* fix @ts-nocheck associated lints

* small changes

* minor fixes

---------

Co-authored-by: Isaac Light <[email protected]>
  • Loading branch information
chennisden and is2ac2 authored Jun 24, 2024
1 parent 143387b commit 29754af
Show file tree
Hide file tree
Showing 29 changed files with 1,222 additions and 319 deletions.
469 changes: 465 additions & 4 deletions frontend/package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@react-three/drei": "^9.107.0",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
Expand All @@ -20,6 +21,7 @@
"react-scripts": "5.0.1",
"react-spring": "^9.7.3",
"typescript": "^4.9.5",
"urdf-loader": "^0.12.1",
"uuid": "^10.0.0",
"web-vitals": "^2.1.4"
},
Expand Down
13 changes: 7 additions & 6 deletions frontend/src/components/PartForm.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import TCButton from "components/files/TCButton";
import { Image } from "hooks/api";
import { Theme } from "hooks/theme";
import { ChangeEvent, Dispatch, FormEvent, SetStateAction } from "react";
import { Button, Col, Form, Row } from "react-bootstrap";
import { Col, Form, Row } from "react-bootstrap";
import ImageUploadComponent from "./files/UploadImage";

interface PartFormProps {
Expand Down Expand Up @@ -100,27 +101,27 @@ const PartForm: React.FC<PartFormProps> = ({
/>
</Col>
<Col md={12}>
<Button
<TCButton
className="mb-2 mt-2"
variant="danger"
onClick={() => handleRemoveImage(index)}
>
Remove
</Button>
</TCButton>
</Col>
</Row>
))}
<Col>
<Button
<TCButton
className="mb-3"
variant={theme === "dark" ? "outline-light" : "outline-dark"}
onClick={handleAddImage}
>
Add Image
</Button>
</TCButton>
</Col>
<Col md={12}>
<Button type="submit">Submit</Button>
<TCButton type="submit">Submit</TCButton>
</Col>
</Form>
</>
Expand Down
111 changes: 97 additions & 14 deletions frontend/src/components/RobotForm.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Bom, Image, Part } from "hooks/api";
import TCButton from "components/files/TCButton";
import { Bom, Image, Package, Part } from "hooks/api";
import { Theme } from "hooks/theme";
import { ChangeEvent, Dispatch, FormEvent, SetStateAction } from "react";
import { Button, Col, Form, Row } from "react-bootstrap";
import { Col, Form, Row } from "react-bootstrap";
import ImageUploadComponent from "./files/UploadImage";

interface RobotFormProps {
Expand All @@ -24,6 +25,10 @@ interface RobotFormProps {
handleSubmit: (event: FormEvent<HTMLFormElement>) => void;
robot_images: Image[];
setImages: Dispatch<SetStateAction<Image[]>>;
robotURDF: string;
setURDF: Dispatch<SetStateAction<string>>;
robot_packages: Package[];
setPackages: Dispatch<SetStateAction<Package[]>>;
}

const RobotForm: React.FC<RobotFormProps> = ({
Expand All @@ -46,7 +51,27 @@ const RobotForm: React.FC<RobotFormProps> = ({
handleSubmit,
robot_images,
setImages,
robotURDF,
setURDF,
robot_packages,
setPackages,
}) => {
const handlePackageChange = (
index: number,
e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
const { name, value } = e.target;
const newPackages = [...robot_packages];
newPackages[index][name as keyof Package] = value;
setPackages(newPackages);
};
const handleAddPackage = () => {
setPackages([...robot_packages, { name: "", url: "" }]);
};
const handleRemovePackage = (index: number) => {
const newPackages = robot_packages.filter((_, i) => i !== index);
setPackages(newPackages);
};
const handleImageChange = (
index: number,
e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
Expand Down Expand Up @@ -112,7 +137,7 @@ const RobotForm: React.FC<RobotFormProps> = ({
value={robot_name}
required
/>
<label htmlFor="height">Height</label>
<label htmlFor="height">Height (Optional)</label>
<Form.Control
id="height"
className="mb-3"
Expand All @@ -123,7 +148,7 @@ const RobotForm: React.FC<RobotFormProps> = ({
}}
value={robot_height}
/>
<label htmlFor="weight">Weight</label>
<label htmlFor="weight">Weight (Optional)</label>
<Form.Control
id="weight"
className="mb-3"
Expand All @@ -134,7 +159,7 @@ const RobotForm: React.FC<RobotFormProps> = ({
}}
value={robot_weight}
/>
<label htmlFor="dof">Total Degrees of Freedom</label>
<label htmlFor="dof">Total Degrees of Freedom (Optional)</label>
<Form.Control
id="dof"
className="mb-3"
Expand All @@ -156,6 +181,64 @@ const RobotForm: React.FC<RobotFormProps> = ({
value={robot_description}
required
/>
<h2>URDF (Optional)</h2>
<label htmlFor="urdf">URDF Link (Optional)</label>
<Form.Control
id="urdf"
className="mb-3"
type="text"
placeholder="ex. https://raw.githubusercontent.com/path/to/urdf.urdf"
onChange={(e) => {
setURDF(e.target.value);
}}
value={robotURDF}
/>
<label htmlFor="packages">URDF Packages (Optional)</label>
{robot_packages &&
robot_packages.map((pkg, index) => (
<Row key={index} className="mb-3">
<Col md={12}>
<label htmlFor={"name-" + index}>Caption</label>
<Form.Control
id={"name-" + index}
className="mb-1"
type="text"
name="name"
value={pkg.name}
onChange={(e) => handlePackageChange(index, e)}
required
/>
<Form.Control
id={"url-" + index}
className="mb-1"
type="text"
name="url"
value={pkg.url}
onChange={(e) => handlePackageChange(index, e)}
required
/>
</Col>
<Col md={12}>
<TCButton
className="mb-2 mt-2"
variant="danger"
onClick={() => handleRemovePackage(index)}
>
Remove
</TCButton>
</Col>
</Row>
))}
<Col>
<TCButton
className="mb-3"
variant={theme === "dark" ? "outline-light" : "outline-dark"}
onClick={handleAddPackage}
>
Add Package
</TCButton>
</Col>

<h2>Images</h2>
{robot_images.map((image, index) => (
<Row key={index} className="mb-3">
Expand All @@ -175,24 +258,24 @@ const RobotForm: React.FC<RobotFormProps> = ({
/>
</Col>
<Col md={12}>
<Button
<TCButton
className="mb-2 mt-2"
variant="danger"
onClick={() => handleRemoveImage(index)}
>
Remove
</Button>
</TCButton>
</Col>
</Row>
))}
<Col>
<Button
<TCButton
className="mb-3"
variant={theme === "dark" ? "outline-light" : "outline-dark"}
onClick={handleAddImage}
>
Add Image
</Button>
</TCButton>
</Col>
<h2>Bill of Materials</h2>
{robot_bom.map((bom, index) => (
Expand Down Expand Up @@ -229,27 +312,27 @@ const RobotForm: React.FC<RobotFormProps> = ({
/>
</Col>
<Col md={12}>
<Button
<TCButton
className="mb-2 mt-2"
variant="danger"
onClick={() => handleRemoveBom(index)}
>
Remove
</Button>
</TCButton>
</Col>
</Row>
))}
<Col>
<Button
<TCButton
className="mb-3"
variant={theme === "dark" ? "outline-light" : "outline-dark"}
onClick={handleAddBom}
>
Add Part
</Button>
</TCButton>
</Col>
<Col>
<Button type="submit">Submit</Button>
<TCButton type="submit">Submit</TCButton>
</Col>
</Form>
</>
Expand Down
16 changes: 4 additions & 12 deletions frontend/src/components/auth/EmailAuthComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
import { faEnvelope } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import TCButton from "components/files/TCButton";
import { humanReadableError } from "constants/backend";
import { useAlertQueue } from "hooks/alerts";
import { useAuthentication } from "hooks/auth";
import { useRef, useState } from "react";
import {
Button,
Col,
Form,
InputGroup,
Overlay,
Row,
Tooltip,
} from "react-bootstrap";
import { Col, Form, InputGroup, Overlay, Row, Tooltip } from "react-bootstrap";
import { CheckCircle } from "react-bootstrap-icons";

const isValidEmail = (email: string) => {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
};
Expand Down Expand Up @@ -79,15 +71,15 @@ const EmailAuthComponent = () => {
value={email}
disabled={isDisabled}
/>
<Button
<TCButton
variant="primary"
type="submit"
disabled={isDisabled || email.length === 0 || !isValidEmail(email)}
ref={target}
>
Sign In
<FontAwesomeIcon icon={faEnvelope} style={{ marginLeft: 15 }} />
</Button>
</TCButton>
<Overlay
placement="bottom-end"
show={email !== null && email.length > 3 && !isValidEmail(email)}
Expand Down
Loading

0 comments on commit 29754af

Please sign in to comment.