Skip to content

Commit

Permalink
sidebar interact update
Browse files Browse the repository at this point in the history
  • Loading branch information
ankushKun committed Jul 19, 2024
1 parent bd7b7d8 commit 9d933eb
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 70 deletions.
81 changes: 46 additions & 35 deletions next_app/src/components/drawer/components/interact.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { useEffect, useState } from "react";
import { runLua, Tag } from "@/lib/ao-vars";
import { Delete, Loader, MinusCircle } from "lucide-react";
import { ChevronsLeftRight, Copy, Delete, Loader, Minus, MinusCircle, Tag as TagIcon } from "lucide-react";
import { Combobox } from "@/components/ui/combo-box";
import { toast } from "sonner";
import Link from "next/link";

Expand Down Expand Up @@ -46,47 +47,57 @@ function Interact() {

return <div className="max-h-[calc(100vh-50px)]">
<h1 className="text-left p-3 text-muted-foreground">INTERACT</h1>
{globalState.activeProject ? <div className="overflow-scroll p-2 pt-0 flex flex-col gap-2">
<Input placeholder={`Target (${project?.process})`} onChange={(e) => setTarget(e.target.value)} />
<Input placeholder="Action" onChange={(e) => setAction(e.target.value)} />
<Input placeholder="Data" onChange={(e) => setData(e.target.value)} />
<span className="text-sm text-muted-foreground">Tags:</span>
{globalState.activeProject ? <div className="overflow-scroll p-2 pt-0.5 flex flex-col gap-2">
{/* <Input placeholder={`Target (${project?.process})`} onChange={(e) => setTarget(e.target.value)} className="bg-foreground/5 rounded" /> */}
<Combobox triggerClassName="bg-foreground/5 p-1.5" className="bg-background" placeholder={`Target: ${target}`} onChange={(e) => { if (e) { setTarget(e) } else { setTarget(project.process) } }} options={Object.keys(manager.projects).filter(pid => { return manager.projects[pid].process }).map(pid => ({ label: `${pid}: ${manager.projects[pid].process}`, value: manager.projects[pid].process }))} />
<Input placeholder="Action" onChange={(e) => setAction(e.target.value)} className="bg-foreground/5 rounded" />
<Input placeholder="Data" onChange={(e) => setData(e.target.value)} className="bg-foreground/5 rounded" />
<hr className="my-3" />
<span className="text-sm text-muted-foreground flex gap-1 items-center"><TagIcon size={16} />Tags</span>
<div className="flex gap-2.5 my-4">
<Input placeholder="Name" id="input-tag-name-1" className="bg-foreground/5 rounded h-8" />
<Input placeholder="Value" id="input-tag-value-1" className="bg-foreground/5 rounded h-8" />
<Button className="bg-foreground/5 text-foreground hover:text-background rounded border border-border/50 h-8"
onClick={() => {
const name = (document.getElementById("input-tag-name-1") as HTMLInputElement)?.value;
const value = (document.getElementById("input-tag-value-1") as HTMLInputElement)?.value;
if (!name || !value) return toast.error("Name and Value are required");
setInputTags([...inputTags, { name, value }]);
(document.getElementById("input-tag-name-1") as HTMLInputElement).value = "";
(document.getElementById("input-tag-value-1") as HTMLInputElement).value = "";
}}>+ Add</Button>
</div>
{
inputTags.map((tag, i) => <div key={i} className="flex gap-2">
<Input placeholder="Name" value={tag.name} onChange={e => {
const tags = [...inputTags];
tags[i].name = e.target.value;
setInputTags(tags);
}} />
<Input placeholder="Value" value={tag.value} onChange={e => {
const tags = [...inputTags];
tags[i].value = e.target.value;
setInputTags(tags);
}} />
<Button variant="destructive" className="p-3" onClick={() => {
inputTags.map((tag, i) => <div key={i} className="flex gap-1.5 my-1 items-center">
<Button variant="destructive" className="w-5 h-5 p-1 !aspect-square rounded-full border border-destructive-foreground" onClick={() => {
const tags = [...inputTags];
tags.splice(i, 1);
setInputTags(tags);
}}><MinusCircle size={18} /></Button>
}}><Minus size={18} /></Button>
<span className="text-muted-foreground text-sm mx-2">TAG {i + 1}</span>
<Input placeholder="Name" value={tag.name} className="bg-primary/20 text-center text-primary border border-primary rounded-full h-6 p-0 px-1"
onChange={e => {
const tags = [...inputTags];
tags[i].name = e.target.value;
setInputTags(tags);
}} />
<Input placeholder="Value" value={tag.value} className="bg-primary/20 text-center text-primary border border-primary rounded-full h-6 p-0 px-1"
onChange={e => {
const tags = [...inputTags];
tags[i].value = e.target.value;
setInputTags(tags);
}} />
</div>)
}
<div className="flex gap-1">
<Input placeholder="Name" id="input-tag-name-1" />
<Input placeholder="Value" id="input-tag-value-1" />
<Button onClick={() => {
const name = (document.getElementById("input-tag-name-1") as HTMLInputElement)?.value;
const value = (document.getElementById("input-tag-value-1") as HTMLInputElement)?.value;
if (!name || !value) return toast.error("Name and Value are required");
setInputTags([...inputTags, { name, value }]);
(document.getElementById("input-tag-name-1") as HTMLInputElement).value = "";
(document.getElementById("input-tag-value-1") as HTMLInputElement).value = "";
}}>+ Add Tag</Button>
</div>
<span className="text-sm text-muted-foreground">Eequivalent Lua code:</span>
<pre className="text-xs overflow-scroll border border-border/40 p-2 rounded-md">{eqLua}</pre>
<hr className="my-3" />
<details className="text-sm text-muted-foreground" open={false}>
<summary><span className="inline-flex items-center gap-1.5 cursor-pointer mb-1.5">Lua Code <button><Copy size={15} className="cursor-pointer" onClick={() => { navigator.clipboard.writeText(eqLua); toast.info("Copied to clipboard") }} /></button></span></summary>
<pre className="text-xs bg-foreground/10 text-foreground font-btr-code overflow-scroll border border-border/40 p-2 rounded-md">{eqLua}</pre>
</details>
<Button onClick={sendMessage} disabled={sendingMessage}>Send Message {sendingMessage && <Loader size={18} className="animate-spin ml-1.5" />}</Button>
<span className="text-sm text-muted-foreground">Result: {id && id != "..." && <Link className="text-primary" href={`https://www.ao.link/#/message/${id}`} target="_blank">View on ao.link</Link>} <pre className="overflow-scroll">{id || "..."}</pre></span>
<pre className="text-xs overflow-scroll border border-border/40 p-2 rounded-md">{output || "..."}</pre>

<span className="mt-4 items-center text-muted-foreground flex gap-1"><ChevronsLeftRight size={24} /> Results <Link className="ml-auto" href={id ? `https://www.ao.link/#/message/${id}` : "#"} target={id ? "_blank" : "_self"}>view on <span className="text-primary">ao.link</span></Link></span>
<pre className="text-xs overflow-scroll border border-border/40 p-2 rounded-md bg-foreground/10 font-btr-code">{output || "..."}</pre>
</div> : <div className="p-2 text-muted text-center">No active project</div>}
</div>
}
Expand Down
2 changes: 1 addition & 1 deletion next_app/src/components/drawer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import drawerItems from "./components"
export default function SidebarDrawer() {
const globalState = useGlobalState()

return <div className="whitespace-nowrap overflow-scroll">
return <div className="whitespace-nowrap overflow-scroll bg-foreground/[3%] h-full">
{
drawerItems.map((item, i) => {
return item.value == globalState.activeSidebarItem ? <item.component key={i} /> : null
Expand Down
33 changes: 17 additions & 16 deletions next_app/src/components/menubar/components/new-project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function NewProject() {
const [usingManualModuleId, setUsingManualModuleId] = useState("");
const [fileDragOver, setFileDragOver] = useState(false);
const [uploadedFiles, setUploadedFiles] = useState<{ [foo: string]: PFile | string }>({});
const [processes, setProcesses] = useState([{ label: "+ Create New", value: "NEW_PROCESS" }]);
const [processes, setProcesses] = useState([{ label: "+ Create New Process", value: "NEW_PROCESS" }]);

async function fetchProcesses() {
if (!window.arweaveWallet) return;
Expand Down Expand Up @@ -71,7 +71,7 @@ export default function NewProject() {
}
});

setProcesses([{ label: "+ Create New", value: "NEW_PROCESS" }, ...ids]);
setProcesses([{ label: "+ Create New Process", value: "NEW_PROCESS" }, ...ids]);
}

async function createProject() {
Expand Down Expand Up @@ -238,22 +238,23 @@ export default function NewProject() {

<Combobox placeholder="Select Process (or search with ID)" options={usingManualProcessId.length==43 ? [{ label: `Process ID: ${usingManualProcessId}`, value: usingManualProcessId }] : processes} onChange={(e) => setProcessUsed(e)} onOpen={fetchProcesses} onSearchChange={(e) => setUsingManualProcessId(e)} />

{processUsed == "NEW_PROCESS" && <Input type="text" placeholder={`Process Name (${newProjName || "optional"})`} onChange={(e) => setNewProcessName(e.target.value)} />}
<details>
<summary>All Options</summary>

{processUsed == "NEW_PROCESS" && <Input type="text" placeholder={`Process Name (${newProjName || "optional"})`} onChange={(e) => setNewProcessName(e.target.value)} />}

<Combobox placeholder="Select Template" disabled={Object.keys(uploadedFiles).length > 0} options={Object.keys(AOTemplates).map((key) => ({ label: key, value: key })).filter((e) => e.value != "")}
onChange={(e) => setSelectedTemplate(e)} onOpen={() => { }} />
{/* advanced settings dropdown */}
{/* <details>
<summary className="text-foreground/60 text-sm pl-2 pb-2">Advanced Settings</summary> */}
{/* <div className="flex flex-col gap-2"> */}
<Combobox placeholder="Select Template" disabled={Object.keys(uploadedFiles).length > 0} options={Object.keys(AOTemplates).map((key) => ({ label: key, value: key })).filter((e) => e.value != "")}
onChange={(e) => setSelectedTemplate(e)} onOpen={() => { }} />

<Combobox disabled={processUsed != "NEW_PROCESS"} placeholder="AO Process Module (default: WASM64)" options={usingManualModuleId.length==43?[{label:`Module ID: ${usingManualModuleId}`, value:`${usingManualModuleId}`}]: Object.keys(AOModules).map((key) => ({ label: `${key} (${AOModules[key]})`, value: AOModules[key] }))} onChange={(e) => setNewProcessModule(e)} onSearchChange={(e)=>setUsingManualModuleId(e)} />
<input id="projext-zip" type="file" accept=".zip" placeholder="Upload project zip" hidden onChange={handleFileDrop} />
<label htmlFor="projext-zip" className="text-center" onDragOver={handleFileDragOver} onDrop={handleFileDrop} onDragLeave={() => setFileDragOver(false)}>
<div data-draggedover={fileDragOver} className="border border-dashed data-[draggedover=true]:border-primary rounded-lg p-4">{Object.keys(uploadedFiles).length > 0 ? `Found ${Object.keys(uploadedFiles).length} files` : "Upload project zip"}</div>
</label>
{/* </div> */}
{/* </details> */}
<Combobox disabled={processUsed != "NEW_PROCESS"} placeholder="AO Process Module (default: WASM64)" options={usingManualModuleId.length == 43 ? [{ label: `Module ID: ${usingManualModuleId}`, value: `${usingManualModuleId}` }] : Object.keys(AOModules).map((key) => ({ label: `${key} (${AOModules[key]})`, value: AOModules[key] }))} onChange={(e) => setNewProcessModule(e)} onSearchChange={(e) => setUsingManualModuleId(e)} />
<input id="projext-zip" type="file" accept=".zip" placeholder="Upload project zip" hidden onChange={handleFileDrop} />
<label htmlFor="projext-zip" className="text-center" onDragOver={handleFileDragOver} onDrop={handleFileDrop} onDragLeave={() => setFileDragOver(false)}>
<div data-draggedover={fileDragOver} className="border border-dashed data-[draggedover=true]:border-primary rounded-lg p-4">{Object.keys(uploadedFiles).length > 0 ? `Found ${Object.keys(uploadedFiles).length} files` : "Upload project zip"}</div>
</label>

</details>




<RadioGroup defaultValue="NOTEBOOK" className="py-2" onValueChange={(e) => setDefaultFiletype(e as "NORMAL" | "NOTEBOOK")}>
Expand Down
16 changes: 9 additions & 7 deletions next_app/src/components/sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,24 @@ export default function Sidebar({ drawerRef }: { drawerRef: MutableRefObject<Imp
default:
if (globalState.activeSidebarItem == sidebarValue)
drawerRef.current.isCollapsed() ? drawerRef.current.expand() : drawerRef.current.collapse()
else{drawerRef.current.expand()
globalState.setActiveSidebarItem(sidebarValue)}
else {
drawerRef.current.expand()
globalState.setActiveSidebarItem(sidebarValue)
}
}
}
}

return <div className="w-[50px] border-r flex flex-col items-center justify-start overflow-x-clip overflow-y-scroll">
return <div className="w-[50px] border-r flex flex-col items-center justify-start overflow-x-clip overflow-y-scroll bg-foreground/[3%]">
{
sidebarItems.map((Item, i) => <TooltipProvider key={i} delayDuration={0}>
<Tooltip>
<TooltipTrigger>
<Button variant="ghost" data-active={globalState.activeSidebarItem == Item.value}
className="rounded-none h-12 w-12 flex items-center justify-center p-0 data-[active=true]:bg-primary"
onClick={sidebarButtonClicked(Item.value)}
<Button variant="ghost" data-active={globalState.activeSidebarItem == Item.value}
className="rounded-none h-12 w-12 flex items-center justify-center p-0 data-[active=true]:bg-primary"
onClick={sidebarButtonClicked(Item.value)}
><Item.icon strokeWidth={1.5} data-active={globalState.activeSidebarItem == Item.value}
className="data-[active=true]:text-white"
className="data-[active=true]:text-white"
/>
</Button>
</TooltipTrigger>
Expand Down
4 changes: 2 additions & 2 deletions next_app/src/components/ui/combo-box.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover
import { useTimeout } from "usehooks-ts";
import { GraphQLClient, gql } from "graphql-request";

export function Combobox({ className = "", placeholder, options, onChange, onOpen = () => { }, disabled = false, onSearchChange = (e) => { } }: { className?: string; placeholder: string, options: { label: string; value: string }[]; onChange: (val: string) => void; onOpen?: () => void; disabled?: boolean; onSearchChange?: (e: string) => void }) {
export function Combobox({ triggerClassName = "", className = "", placeholder, options, onChange, onOpen = () => { }, disabled = false, onSearchChange = (e) => { } }: { triggerClassName?: string, className?: string; placeholder: string, options: { label: string; value: string }[]; onChange: (val: string) => void; onOpen?: () => void; disabled?: boolean; onSearchChange?: (e: string) => void }) {
const [open, setOpen] = useState(false);
const [value, setValue] = useState("");

Expand All @@ -20,7 +20,7 @@ export function Combobox({ className = "", placeholder, options, onChange, onOpe
onOpen();
}}
>
<PopoverTrigger asChild disabled={disabled}>
<PopoverTrigger asChild disabled={disabled} className={triggerClassName}>
<Button variant="outline" role="combobox" aria-expanded={open} className="w-full mx-auto overflow-clip truncate justify-between border-border/60">
{value ? value : <span className="text-muted-foreground">{placeholder}</span>}
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
Expand Down
4 changes: 2 additions & 2 deletions next_app/src/components/ui/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import * as React from "react"
import { cn } from "@/lib/utils"

export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
extends React.InputHTMLAttributes<HTMLInputElement> { }

const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-border/60 focus-visible:ring-1 bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-ring focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50",
"flex h-10 w-full rounded-md border border-border/60 focus-visible:ring-1 bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-ring/30 focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50",
className
)}
ref={ref}
Expand Down
8 changes: 4 additions & 4 deletions next_app/src/components/views/components/editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ function Editor() {
<TabsTrigger value="terminal" className="rounded-none data-[state=active]:bg-primary data-[state=active]:text-white">Terminal</TabsTrigger>
<TabsTrigger value="inbox" className="rounded-none data-[state=active]:bg-primary data-[state=active]:text-white">Inbox</TabsTrigger>
<TabsTrigger value="output" className="rounded-none data-[state=active]:bg-primary data-[state=active]:text-white">Output</TabsTrigger>
<TabsTrigger value="interact" className="rounded-none data-[state=active]:bg-primary data-[state=active]:text-white">Interact</TabsTrigger>
{/* <TabsTrigger value="interact" className="rounded-none data-[state=active]:bg-primary data-[state=active]:text-white">Interact</TabsTrigger> */}
</TabsList>
<TabsContent value="terminal" className="h-[calc(100%-30px)] overflow-scroll m-0">
<AOTerminal prompt={prompt} setPrompt={setPrompt} commandOutputs={commandOutputs} setCommandOutputs={setCommandOutputs} />
Expand All @@ -158,9 +158,9 @@ function Editor() {
<TabsContent value="output" className="h-[calc(100%-30px)] overflow-scroll m-0">
<Output />
</TabsContent>
<TabsContent value="interact" className="h-[calc(100%-30px)] overflow-scroll m-0">
<Interact/>
</TabsContent>
{/* <TabsContent value="interact" className="h-[calc(100%-30px)] overflow-scroll m-0">
<Interact />
</TabsContent> */}
</Tabs>
</div>
{/* <div className="h-[calc(100%-30px)] overflow-scroll ring-1">
Expand Down
Loading

0 comments on commit 9d933eb

Please sign in to comment.