Skip to content

Commit

Permalink
Add edit environment info features
Browse files Browse the repository at this point in the history
  • Loading branch information
jinyu-loopmind committed Sep 16, 2023
1 parent 9a47cb0 commit 54fd387
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 33 deletions.
49 changes: 45 additions & 4 deletions frontend/src/components/environment_card.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,54 @@
import { Environment } from "@/types/environment";
import { Environment, VectorSpec } from "@/types/environment";
import VariableSpec from "@/components/variable_spec";
import { useState, useEffect } from "react";

export default function EnvironmentCard({ env }: { env: Environment }) {
const [envSpecs, setEnvSpecs] = useState<Environment>(env);
const [obsSpecs, setObsSpecs] = useState<VectorSpec[]>(
env.observation_spec ?? []
);
const [actSpecs, setActSpecs] = useState<VectorSpec[]>(env.action_spec ?? []);
useEffect(() => {
setEnvSpecs((prevState) => {
const newState = { ...prevState };
newState.observation_spec = obsSpecs;
newState.action_spec = actSpecs;
return newState;
});
}, [obsSpecs, actSpecs]);
const onSave = () => {
fetch(`/api/env/${env.id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(envSpecs),
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
console.log("Environment saved successfully!");
})
.catch((error) => {
console.error("There was a problem saving the environment:", error);
});
};

return (
<div className="card m-5">
<div className="card-body">
<h2 className="card-title">{env.name}</h2>
<VariableSpec title="Observation Space" specs={env.observation_spec} />
<VariableSpec title="Action Space" specs={env.action_spec} />
<h2 className="card-title">{envSpecs.name}</h2>
<VariableSpec
title="Observation Space"
specs={obsSpecs}
setSpecs={setObsSpecs}
onSave={onSave}
/>
<VariableSpec
title="Action Space"
specs={actSpecs}
setSpecs={setActSpecs}
onSave={onSave}
/>
<div className="card bg-base-100 max-w m-3">
<div className="card-body">
<h2 className="card-title">Detailed Env Specs</h2>
Expand Down
120 changes: 91 additions & 29 deletions frontend/src/components/variable_spec.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,112 @@
import React from "react";
import { VectorSpec } from "@/types/environment";

interface Props {
const VAR_DISP_LIMIT = 50;

export default function VariableSpec({
title,
specs,
setSpecs,
onSave,
}: {
title: string;
specs?: VectorSpec[];
}
specs: VectorSpec[];
setSpecs: React.Dispatch<React.SetStateAction<VectorSpec[]>>;
onSave: () => void;
}) {
const [isEditing, setIsEditing] = React.useState<boolean[]>(
specs.map(() => false) ?? []
);
const handleEditSubmitClick = (i: number) => {
setIsEditing((prevIsEditing) => {
const newIsEditing = [...prevIsEditing];
newIsEditing[i] = !prevIsEditing[i];
if (!newIsEditing[i]) {
onSave();
}
return newIsEditing;
});
};

export default function VariableSpec(props: Props) {
return (
<div className="card flex-shrink-0 max-w bg-base-100 m-3">
<div className="card-body">
<h2 className="card-title">{props.title}</h2>
{props.specs?.map((spec, i) => (
<h2 className="card-title">{title}</h2>
{specs.map((spec, i) => (
<div key={i}>
<p>{spec.space}</p>
<div className="card flex-shrink-0 shadow m-10">
<code className="bg-base-200">{spec.space}</code>
<div className="card flex-shrink-0 m-10">
<table className="table table-zebra">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Description</th>
<th></th>
</tr>
</thead>
<tbody>
{spec.var_info?.slice(0, 50).map((var_info, i) => (
<tr key={i}>
<th>{i + 1}</th>
<td>
<input
type="text"
className="input input-bordered w-full max-w-xs"
placeholder="Add Varible Name"
defaultValue={var_info.name ?? ""}
/>
</td>
<td>
<input
type="text"
className="input input-bordered w-full max-w-xs"
placeholder="Add Variable Description"
defaultValue={var_info.description ?? ""}
/>
</td>
</tr>
))}
{spec.var_info
?.slice(0, VAR_DISP_LIMIT)
.map((var_info, j) => (
<tr key={j}>
<th>{j + 1}</th>
<td>
{isEditing[j] ? (
<input
type="text"
className="input w-full max-w-xs bg-transparent input-bordered"
placeholder="Add Variable Name"
defaultValue={var_info.name ?? ""}
onBlur={(event) => {
setSpecs((prevState) => {
const newState = JSON.parse(
JSON.stringify(prevState)
);

newState[i].var_info[j].name =
event.target.value;
return newState;
});
}}
/>
) : (
<p>{var_info.name}</p>
)}
</td>
<td>
{isEditing[j] ? (
<textarea
className="input w-full max-w-xs bg-transparent input-bordered"
placeholder="Add Variable Description"
defaultValue={var_info.description ?? ""}
readOnly={!isEditing[j]}
onBlur={(event) => {
setSpecs((prevState) => {
const newState = JSON.parse(
JSON.stringify(prevState)
);

newState[i].var_info[j].description =
event.target.value;
return newState;
});
}}
/>
) : (
<p>{var_info.description}</p>
)}
</td>
<td>
<button
className="btn btn-sm btn-ghost normal-case"
onClick={() => handleEditSubmitClick(j)}
>
{isEditing[j] ? "Save" : "Edit"}
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
Expand Down

0 comments on commit 54fd387

Please sign in to comment.