diff --git a/frontend/package.json b/frontend/package.json index 901a83a..8a68a62 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -21,6 +21,7 @@ "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-progress": "^1.0.3", + "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 93afce7..e68f16d 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -29,8 +29,10 @@ import html2canvas from "html2canvas"; import { USER_CLOSE_WEB_SOCKET_CODE } from "./constants"; import CodeTab from "./components/CodeTab"; import OutputSettingsSection from "./components/OutputSettingsSection"; +import { History } from "./history_types"; +import HistoryDisplay from "./components/HistoryDisplay"; -const IS_OPENAI_DOWN = true; +const IS_OPENAI_DOWN = false; function App() { const [appState, setAppState] = useState(AppState.INITIAL); @@ -54,6 +56,9 @@ function App() { "setting" ); + // App history + const [appHistory, setAppHistory] = useState([]); + const [shouldIncludeResultImage, setShouldIncludeResultImage] = useState(false); @@ -107,6 +112,7 @@ function App() { setReferenceImages([]); setExecutionConsole([]); setHistory([]); + setAppHistory([]); }; const stop = () => { @@ -128,7 +134,32 @@ function App() { (token) => setGeneratedCode((prev) => prev + token), (code) => setGeneratedCode(code), (line) => setExecutionConsole((prev) => [...prev, line]), - () => setAppState(AppState.CODE_READY) + () => { + setAppState(AppState.CODE_READY); + if (params.generationType === "create") { + setAppHistory([ + { + type: "ai_create", + code: generatedCode, + // TODO: Doesn't typecheck correctly + inputs: { image_url: referenceImages[0] }, + }, + ]); + } else { + setAppHistory((prev) => [ + { + type: "ai_edit", + code: generatedCode, + // TODO: Doesn't typecheck correctly + inputs: { + previous_commands: [], + new_instruction: updateInstruction, + }, + }, + ...prev, + ]); + } + } ); } @@ -317,6 +348,7 @@ function App() { )} + {} diff --git a/frontend/src/components/HistoryDisplay.tsx b/frontend/src/components/HistoryDisplay.tsx new file mode 100644 index 0000000..26a428f --- /dev/null +++ b/frontend/src/components/HistoryDisplay.tsx @@ -0,0 +1,42 @@ +import { ScrollArea } from "@/components/ui/scroll-area"; +import { History, HistoryItemType } from "../history_types"; + +interface Props { + history: History; +} + +function displayHistoryItemType(itemType: HistoryItemType) { + switch (itemType) { + case "ai_create": + return "Create"; + case "ai_edit": + return "Edit"; + case "code_create": + return "Create"; + case "code_edit": + return "Code Edit"; + case "revert": + return "Revert"; + default: + // TODO: Error out since this is exhaustive + return "Unknown"; + } +} + +export default function HistoryDisplay({ history }: Props) { + return ( +
+

History

+ +
    + {history.map((item, index) => ( +
  • +

    {displayHistoryItemType(item.type)}

    +

    v{history.length - index}

    +
  • + ))} +
+
+
+ ); +} diff --git a/frontend/src/components/ui/scroll-area.tsx b/frontend/src/components/ui/scroll-area.tsx new file mode 100644 index 0000000..cf253cf --- /dev/null +++ b/frontend/src/components/ui/scroll-area.tsx @@ -0,0 +1,46 @@ +import * as React from "react" +import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" + +import { cn } from "@/lib/utils" + +const ScrollArea = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + {children} + + + + +)) +ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName + +const ScrollBar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, orientation = "vertical", ...props }, ref) => ( + + + +)) +ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName + +export { ScrollArea, ScrollBar } diff --git a/frontend/src/history_types.ts b/frontend/src/history_types.ts new file mode 100644 index 0000000..1486a99 --- /dev/null +++ b/frontend/src/history_types.ts @@ -0,0 +1,40 @@ +export type HistoryItemType = + | "ai_create" + | "code_create" + | "ai_edit" + | "revert" + | "code_edit"; + +export type HistoryItem = { + type: HistoryItemType; + code?: string; + inputs: + | AiCreateInputs + | CodeCreateInputs + | AiEditInputs + | RevertInputs + | CodeEditInputs; +}; + +export type AiCreateInputs = { + image_url?: string; +}; + +export type CodeCreateInputs = { + // Define specific properties relevant for code creation +}; + +export type AiEditInputs = { + previous_commands: string[]; + new_instruction: string; +}; + +export type RevertInputs = { + parent: number; +}; + +export type CodeEditInputs = { + // TODO: Fill in +}; + +export type History = HistoryItem[]; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index d2a33d1..66b48db 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -894,6 +894,22 @@ "@radix-ui/react-use-callback-ref" "1.0.1" "@radix-ui/react-use-controllable-state" "1.0.1" +"@radix-ui/react-scroll-area@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-scroll-area/-/react-scroll-area-1.0.5.tgz#01160c6893f24a2ddb5aa399ae5b3ba84ad4d3cc" + integrity sha512-b6PAgH4GQf9QEn8zbT2XUHpW5z8BzqEc7Kl11TwDrvuTrxlkcjTD5qa/bxgKr+nmuXKu4L/W5UZ4mlP/VG/5Gw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/number" "1.0.1" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-direction" "1.0.1" + "@radix-ui/react-presence" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-use-layout-effect" "1.0.1" + "@radix-ui/react-select@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-select/-/react-select-2.0.0.tgz#a3511792a51a7018d6559357323a7f52e0e38887"