Add scenario editing modal, twitter sentiment seeding (#101)

* testing agi-eval benchmark

* Add scenario modal editor

* Add initial values to ScenarioEditorModal

* Add seedTwitterSentiment.ts

---------

Co-authored-by: Kyle Corbitt <kyle@corbt.com>
This commit is contained in:
arcticfly
2023-08-01 01:26:43 -07:00
committed by GitHub
parent 6316eaae6d
commit 1fb428ef4a
11 changed files with 621 additions and 102 deletions

View File

@@ -1,15 +1,27 @@
import { type DragEvent } from "react";
import { useEffect, type DragEvent } from "react";
import { api } from "~/utils/api";
import { isEqual } from "lodash-es";
import { type Scenario } from "./types";
import { useExperiment, useExperimentAccess, useHandledAsyncCallback } from "~/utils/hooks";
import { useState } from "react";
import { Box, Button, Flex, HStack, Icon, Spinner, Stack, Tooltip, VStack } from "@chakra-ui/react";
import {
Box,
Button,
HStack,
Icon,
IconButton,
Spinner,
Stack,
Tooltip,
VStack,
Text,
} from "@chakra-ui/react";
import { cellPadding } from "../constants";
import { BsX } from "react-icons/bs";
import { BsArrowsAngleExpand, BsX } from "react-icons/bs";
import { RiDraggable } from "react-icons/ri";
import { FloatingLabelInput } from "./FloatingLabelInput";
import { ScenarioEditorModal } from "./ScenarioEditorModal";
export default function ScenarioEditor({
scenario,
@@ -28,6 +40,10 @@ export default function ScenarioEditor({
const [values, setValues] = useState<Record<string, string>>(savedValues);
useEffect(() => {
if (savedValues) setValues(savedValues);
}, [savedValues]);
const experiment = useExperiment();
const vars = api.templateVars.list.useQuery({ experimentId: experiment.data?.id ?? "" });
@@ -71,83 +87,98 @@ export default function ScenarioEditor({
[reorderMutation, scenario.id],
);
return (
<HStack
alignItems="flex-start"
px={cellPadding.x}
py={cellPadding.y}
spacing={0}
height="100%"
draggable={!variableInputHovered}
onDragStart={(e) => {
e.dataTransfer.setData("text/plain", scenario.id);
e.currentTarget.style.opacity = "0.4";
}}
onDragEnd={(e) => {
e.currentTarget.style.opacity = "1";
}}
onDragOver={(e) => {
e.preventDefault();
setIsDragTarget(true);
}}
onDragLeave={() => {
setIsDragTarget(false);
}}
onDrop={onReorder}
backgroundColor={isDragTarget ? "gray.100" : "transparent"}
>
{canModify && props.canHide && (
<Stack
alignSelf="flex-start"
opacity={props.hovered ? 1 : 0}
spacing={0}
ml={-cellPadding.x}
>
<Tooltip label="Hide scenario" hasArrow>
{/* for some reason the tooltip can't position itself properly relative to the icon without the wrapping box */}
<Button
variant="unstyled"
color="gray.400"
height="unset"
width="unset"
minW="unset"
onClick={onHide}
_hover={{
color: "gray.800",
cursor: "pointer",
}}
>
<Icon as={hidingInProgress ? Spinner : BsX} boxSize={hidingInProgress ? 4 : 6} />
</Button>
</Tooltip>
<Icon
as={RiDraggable}
boxSize={6}
color="gray.400"
_hover={{ color: "gray.800", cursor: "pointer" }}
/>
</Stack>
)}
const [scenarioEditorModalOpen, setScenarioEditorModalOpen] = useState(false);
{variableLabels.length === 0 ? (
<Box color="gray.500">{vars.data ? "No scenario variables configured" : "Loading..."}</Box>
) : (
<VStack spacing={4} flex={1} py={2}>
{variableLabels.map((key) => {
const value = values[key] ?? "";
const layoutDirection = value.length > 20 ? "column" : "row";
return (
<Flex
key={key}
direction={layoutDirection}
alignItems={layoutDirection === "column" ? "flex-start" : "center"}
flexWrap="wrap"
width="full"
return (
<>
<HStack
alignItems="flex-start"
px={cellPadding.x}
py={cellPadding.y}
spacing={0}
height="100%"
draggable={!variableInputHovered}
onDragStart={(e) => {
e.dataTransfer.setData("text/plain", scenario.id);
e.currentTarget.style.opacity = "0.4";
}}
onDragEnd={(e) => {
e.currentTarget.style.opacity = "1";
}}
onDragOver={(e) => {
e.preventDefault();
setIsDragTarget(true);
}}
onDragLeave={() => {
setIsDragTarget(false);
}}
onDrop={onReorder}
backgroundColor={isDragTarget ? "gray.100" : "transparent"}
>
{canModify && props.canHide && (
<Stack
alignSelf="flex-start"
opacity={props.hovered ? 1 : 0}
spacing={0}
ml={-cellPadding.x}
>
<Tooltip label="Hide scenario" hasArrow>
{/* for some reason the tooltip can't position itself properly relative to the icon without the wrapping box */}
<Button
variant="unstyled"
color="gray.400"
height="unset"
width="unset"
minW="unset"
onClick={onHide}
_hover={{
color: "gray.800",
cursor: "pointer",
}}
>
<Icon as={hidingInProgress ? Spinner : BsX} boxSize={hidingInProgress ? 4 : 6} />
</Button>
</Tooltip>
<Icon
as={RiDraggable}
boxSize={6}
color="gray.400"
_hover={{ color: "gray.800", cursor: "pointer" }}
/>
</Stack>
)}
{variableLabels.length === 0 ? (
<Box color="gray.500">
{vars.data ? "No scenario variables configured" : "Loading..."}
</Box>
) : (
<VStack spacing={4} flex={1} py={2}>
<HStack justifyContent="space-between" w="100%">
<Text color="gray.500">Scenario</Text>
<IconButton
className="fullscreen-toggle"
aria-label="Maximize"
icon={<BsArrowsAngleExpand />}
onClick={() => setScenarioEditorModalOpen(true)}
boxSize={6}
borderRadius={4}
p={1.5}
minW={0}
colorScheme="gray"
color="gray.500"
variant="ghost"
/>
</HStack>
{variableLabels.map((key) => {
const value = values[key] ?? "";
return (
<FloatingLabelInput
key={key}
label={key}
isDisabled={!canModify}
style={{ width: "100%" }}
maxHeight={32}
value={value}
onChange={(e) => {
setValues((prev) => ({ ...prev, [key]: e.target.value }));
@@ -162,27 +193,34 @@ export default function ScenarioEditor({
onMouseEnter={() => setVariableInputHovered(true)}
onMouseLeave={() => setVariableInputHovered(false)}
/>
</Flex>
);
})}
{hasChanged && (
<HStack justify="right">
<Button
size="sm"
onMouseDown={() => {
setValues(savedValues);
}}
colorScheme="gray"
>
Reset
</Button>
<Button size="sm" onMouseDown={onSave} colorScheme="blue">
Save
</Button>
</HStack>
)}
</VStack>
);
})}
{hasChanged && (
<HStack justify="right">
<Button
size="sm"
onMouseDown={() => {
setValues(savedValues);
}}
colorScheme="gray"
>
Reset
</Button>
<Button size="sm" onMouseDown={onSave} colorScheme="blue">
Save
</Button>
</HStack>
)}
</VStack>
)}
</HStack>
{scenarioEditorModalOpen && (
<ScenarioEditorModal
scenarioId={scenario.id}
initialValues={savedValues}
onClose={() => setScenarioEditorModalOpen(false)}
/>
)}
</HStack>
</>
);
}