diff --git a/app/components/Input.tsx b/app/components/Input.tsx index e6d5bb68..74593055 100644 --- a/app/components/Input.tsx +++ b/app/components/Input.tsx @@ -91,7 +91,7 @@ export default function Input({ value, onValueChange, handelSubmit, graph, icon, case "ArrowUp": { e.preventDefault() setSelectedOption(prev => { - containerRef.current?.scrollTo({ behavior: 'smooth', top: (prev <= 0 ? options.length - 1 : prev - 1) * 64 }) + containerRef.current?.scrollTo({ behavior: 'smooth', top: (prev <= 0 ? options.length - 1 : prev - 1) * containerRef.current.children[0].clientHeight }) return prev <= 0 ? options.length - 1 : prev - 1 }) return @@ -99,7 +99,7 @@ export default function Input({ value, onValueChange, handelSubmit, graph, icon, case "ArrowDown": { e.preventDefault() setSelectedOption(prev => { - containerRef.current?.scrollTo({ behavior: 'smooth', top: ((prev + 1) % options.length) * 64 }) + containerRef.current?.scrollTo({ behavior: 'smooth', top: ((prev + 1) % options.length) * containerRef.current.children[0].clientHeight }) return (prev + 1) % options.length }) return @@ -163,7 +163,6 @@ export default function Input({ value, onValueChange, handelSubmit, graph, icon, selectedOption === index && "bg-gray-100" )} onMouseEnter={() => setSelectedOption(index)} - onMouseLeave={() => setSelectedOption(-1)} onClick={() => { onValueChange({ name: option.properties.name, id: option.id }) handelSubmit && handelSubmit(option) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 3e8983d1..4e2e4ef6 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -1,13 +1,14 @@ import { toast } from "@/components/ui/use-toast"; import { Dispatch, FormEvent, MutableRefObject, SetStateAction, useEffect, useRef, useState } from "react"; import Image from "next/image"; -import { AlignLeft, ArrowRight, ChevronDown, Lightbulb, Undo2 } from "lucide-react"; +import { AlignLeft, ArrowDown, ArrowRight, ChevronDown, Lightbulb, Undo2 } from "lucide-react"; import { Path } from "../page"; import Input from "./Input"; import { Graph } from "./model"; import { cn } from "@/lib/utils"; import { LAYOUT } from "./code-graph"; import { TypeAnimation } from "react-type-animation"; +import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; enum MessageTypes { Query, @@ -35,6 +36,14 @@ interface Props { setIsPath: (isPathResponse: boolean) => void } +const SUGGESTIONS = [ + "List a few recursive functions", + "What is the name of the most used method?", + "Who is calling the most used method?", + "Which function has the largest number of arguments? List a few arguments", + "Show a calling path between the drop_edge_range_index function and _query, only return function(s) names", +] + const RemoveLastPath = (messages: Message[]) => { const index = messages.findIndex((m) => m.type === MessageTypes.Path) @@ -63,19 +72,13 @@ export function Chat({ repo, path, setPath, graph, chartRef, selectedPathId, isP const [tipOpen, setTipOpen] = useState(false); + const [sugOpen, setSugOpen] = useState(false); + // A reference to the chat container to allow scrolling to the bottom const containerRef: React.RefObject = useRef(null); - const tipRef: React.RefObject = useRef(null); - const isSendMessage = messages.some(m => m.type === MessageTypes.Pending) || (messages.some(m => m.text === "Please select a starting point and the end point. Select or press relevant item on the graph") && !messages.some(m => m.type === MessageTypes.Path)) - useEffect(() => { - if (tipOpen) { - tipRef.current?.focus() - } - }, [tipOpen]) - useEffect(() => { const p = paths.find((path) => [...path.edges, ...path.nodes].some((e: any) => e.id === selectedPathId)) @@ -202,11 +205,13 @@ export function Chat({ repo, path, setPath, graph, chartRef, selectedPathId, isP } // Send the user query to the server - async function sendQuery(event: FormEvent) { + async function sendQuery(event?: FormEvent, sugQuery?: string) { - event.preventDefault(); + event?.preventDefault(); - const q = query.trim() + if (isSendMessage) return + + const q = query?.trim() || sugQuery! if (!q) { toast({ @@ -486,27 +491,52 @@ export function Chat({ repo, path, setPath, graph, chartRef, selectedPathId, isP } { tipOpen && -
setTipOpen(false)}> +
ref?.focus()} className="bg-white absolute bottom-0 border rounded-md flex flex-col gap-3 p-2 overflow-y-auto" tabIndex={-1} onMouseDown={(e) => e.preventDefault()} onBlur={() => setTipOpen(false)}> {getTip()}
} -
- { - repo && -
- -
- - -
-
- } -
+
+ + + + + +
+
+ } + + + { + SUGGESTIONS.map((s, i) => ( + + )) + } + + ); } diff --git a/app/components/dataPanel.tsx b/app/components/dataPanel.tsx index eae6f1b6..b38d40a5 100644 --- a/app/components/dataPanel.tsx +++ b/app/components/dataPanel.tsx @@ -36,7 +36,7 @@ export default function DataPanel({ obj, setObj, url }: Props) { const object = Object.entries(obj).filter(([k]) => !excludedProperties.includes(k)) return ( -
+

{label.toUpperCase()}