diff options
| author | Dhravya <[email protected]> | 2024-06-29 02:10:13 -0500 |
|---|---|---|
| committer | Dhravya <[email protected]> | 2024-06-29 02:10:13 -0500 |
| commit | 9272d87e5f46aeaf1aea0927d47cf3dd69507867 (patch) | |
| tree | 063812c491ff5a898e6e15d271e11bf61d1d134c | |
| parent | fix: Spaces filter not working (diff) | |
| download | supermemory-9272d87e5f46aeaf1aea0927d47cf3dd69507867.tar.xz supermemory-9272d87e5f46aeaf1aea0927d47cf3dd69507867.zip | |
fixed new chat button showing up on all pages
| -rw-r--r-- | apps/cf-ai-backend/src/index.ts | 4 | ||||
| -rw-r--r-- | apps/web/app/(auth)/signin/page.tsx | 8 | ||||
| -rw-r--r-- | apps/web/app/(dash)/chat/chatWindow.tsx | 2 | ||||
| -rw-r--r-- | apps/web/app/(dash)/header/header.tsx (renamed from apps/web/app/(dash)/header.tsx) | 12 | ||||
| -rw-r--r-- | apps/web/app/(dash)/header/newChatButton.tsx | 27 | ||||
| -rw-r--r-- | apps/web/app/(dash)/home/page.tsx | 1 | ||||
| -rw-r--r-- | apps/web/app/(dash)/home/queryinput.tsx | 36 | ||||
| -rw-r--r-- | apps/web/app/(dash)/layout.tsx | 2 | ||||
| -rw-r--r-- | apps/web/app/(dash)/menu.tsx | 113 | ||||
| -rw-r--r-- | apps/web/app/(landing)/page.tsx | 5 | ||||
| -rw-r--r-- | apps/web/app/actions/doers.ts | 2 | ||||
| -rw-r--r-- | apps/web/middleware.ts | 13 | ||||
| -rw-r--r-- | packages/ui/shadcn/combobox.tsx | 12 | ||||
| -rw-r--r-- | packages/ui/shadcn/command.tsx | 5 |
14 files changed, 188 insertions, 54 deletions
diff --git a/apps/cf-ai-backend/src/index.ts b/apps/cf-ai-backend/src/index.ts index dbc0989b..78e1c596 100644 --- a/apps/cf-ai-backend/src/index.ts +++ b/apps/cf-ai-backend/src/index.ts @@ -375,10 +375,6 @@ app.post( // SLICED to 5 to avoid too many queries for (const space of spaces.slice(0, 5)) { if (space && space.length >= 1) { - console.log( - "this is the key being used", - `space-${query.user}-${space}`, - ); // it's possible for space list to be [undefined] so we only add space filter conditionally filter[`space-${query.user}-${space}`] = 1; } diff --git a/apps/web/app/(auth)/signin/page.tsx b/apps/web/app/(auth)/signin/page.tsx index b117716e..bfb341ff 100644 --- a/apps/web/app/(auth)/signin/page.tsx +++ b/apps/web/app/(auth)/signin/page.tsx @@ -1,14 +1,20 @@ import Image from "next/image"; import Link from "next/link"; import Logo from "@/public/logo.svg"; -import { signIn } from "@/server/auth"; +import { auth, signIn } from "@/server/auth"; import { Google } from "@repo/ui/components/icons"; import gradientStyle from "./_components/TextGradient/gradient.module.css"; import { cn } from "@repo/ui/lib/utils"; +import { redirect } from "next/navigation"; export const runtime = "edge"; async function Signin() { + const user = await auth(); + + if (user) { + await redirect("/home"); + } return ( <div className="flex relative font-geistSans overflow-hidden items-center justify-between min-h-screen"> <div className="relative w-full lg:w-1/2 flex items-center min-h-screen bg-page-gradient p-8 border-r-[1px] border-white/5"> diff --git a/apps/web/app/(dash)/chat/chatWindow.tsx b/apps/web/app/(dash)/chat/chatWindow.tsx index 99c997e4..32c45246 100644 --- a/apps/web/app/(dash)/chat/chatWindow.tsx +++ b/apps/web/app/(dash)/chat/chatWindow.tsx @@ -412,7 +412,7 @@ function ChatWindow({ mini className="w-full shadow-md" initialQuery={""} - initialSpaces={[]} + initialSpaces={spaces} handleSubmit={async (q, spaces) => { setChatHistory((prevChatHistory) => { return [ diff --git a/apps/web/app/(dash)/header.tsx b/apps/web/app/(dash)/header/header.tsx index 1265fc93..9154ead8 100644 --- a/apps/web/app/(dash)/header.tsx +++ b/apps/web/app/(dash)/header/header.tsx @@ -1,11 +1,10 @@ import React from "react"; import Image from "next/image"; import Link from "next/link"; -import Logo from "../../public/logo.svg"; -import { AddIcon, ChatIcon } from "@repo/ui/icons"; +import Logo from "../../../public/logo.svg"; -import { db } from "@/server/db"; -import { getChatHistory } from "../actions/fetchers"; +import { getChatHistory } from "../../actions/fetchers"; +import NewChatButton from "./newChatButton"; async function Header() { const chatThreads = await getChatHistory(); @@ -26,10 +25,7 @@ async function Header() { </Link> <div className="flex items-center gap-2"> - <button className="flex duration-200 items-center text-[#7D8994] hover:bg-[#1F2429] text-[13px] gap-2 px-3 py-2 rounded-xl"> - <Image src={ChatIcon} alt="Chat icon" className="w-5" /> - Start new chat - </button> + <NewChatButton /> <div className="relative group"> <button className="flex duration-200 items-center text-[#7D8994] hover:bg-[#1F2429] text-[13px] gap-2 px-3 py-2 rounded-xl"> diff --git a/apps/web/app/(dash)/header/newChatButton.tsx b/apps/web/app/(dash)/header/newChatButton.tsx new file mode 100644 index 00000000..0e9e1c5a --- /dev/null +++ b/apps/web/app/(dash)/header/newChatButton.tsx @@ -0,0 +1,27 @@ +"use client"; + +import { ChatIcon } from "@repo/ui/icons"; +import Image from "next/image"; +import Link from "next/link"; +import { usePathname } from "next/navigation"; +import React from "react"; + +function NewChatButton() { + const path = usePathname(); + + if (path.startsWith("/chat")) { + return ( + <Link + href="/home" + className="flex duration-200 items-center text-[#7D8994] hover:bg-[#1F2429] text-[13px] gap-2 px-3 py-2 rounded-xl" + > + <Image src={ChatIcon} alt="Chat icon" className="w-5" /> + Start new chat + </Link> + ); + } + + return null; +} + +export default NewChatButton; diff --git a/apps/web/app/(dash)/home/page.tsx b/apps/web/app/(dash)/home/page.tsx index 17d52529..aabb4d80 100644 --- a/apps/web/app/(dash)/home/page.tsx +++ b/apps/web/app/(dash)/home/page.tsx @@ -74,6 +74,7 @@ function Page({ ); }} initialSpaces={spaces} + setInitialSpaces={setSpaces} /> </div> </div> diff --git a/apps/web/app/(dash)/home/queryinput.tsx b/apps/web/app/(dash)/home/queryinput.tsx index 868f93f9..3c944c05 100644 --- a/apps/web/app/(dash)/home/queryinput.tsx +++ b/apps/web/app/(dash)/home/queryinput.tsx @@ -8,6 +8,8 @@ import { useRouter } from "next/navigation"; import { getSpaces } from "@/app/actions/fetchers"; import Combobox from "@repo/ui/shadcn/combobox"; import { MinusIcon } from "lucide-react"; +import { toast } from "sonner"; +import { createSpace } from "@/app/actions/doers"; function QueryInput({ initialQuery = "", @@ -16,6 +18,7 @@ function QueryInput({ className, mini = false, handleSubmit, + setInitialSpaces, }: { initialQuery?: string; initialSpaces?: { @@ -26,6 +29,9 @@ function QueryInput({ className?: string; mini?: boolean; handleSubmit: (q: string, spaces: { id: number; name: string }[]) => void; + setInitialSpaces?: React.Dispatch< + React.SetStateAction<{ id: number; name: string }[]> + >; }) { const [q, setQ] = useState(initialQuery); @@ -104,6 +110,7 @@ function QueryInput({ <div className="flex justify-between items-center gap-6 h-auto bg-secondary rounded-b-3xl border-2 border-border"> <Combobox options={options} + className="rounded-bl-3xl bg-[#3C464D] w-44" onSelect={(v) => setSelectedSpaces((prev) => { if (v === "") { @@ -112,8 +119,33 @@ function QueryInput({ return [...prev, parseInt(v)]; }) } - onSubmit={() => {}} - placeholder="Filter spaces..." + onSubmit={async (spaceName) => { + const space = options.find((x) => x.label === spaceName); + toast.info("Creating space..."); + + if (space) { + toast.error("A space with that name already exists."); + } + + const creationTask = await createSpace(spaceName); + if (creationTask.success && creationTask.data) { + toast.success("Space created " + creationTask.data); + setInitialSpaces?.((prev) => [ + ...prev, + { + name: spaceName, + id: creationTask.data!, + }, + ]); + setSelectedSpaces((prev) => [...prev, creationTask.data!]); + } else { + toast.error( + "Space creation failed: " + creationTask.error ?? + "Unknown error", + ); + } + }} + placeholder="Chat with a space..." /> <div className="flex flex-row gap-0.5 h-full"> diff --git a/apps/web/app/(dash)/layout.tsx b/apps/web/app/(dash)/layout.tsx index 3ae4e76d..edac6048 100644 --- a/apps/web/app/(dash)/layout.tsx +++ b/apps/web/app/(dash)/layout.tsx @@ -1,4 +1,4 @@ -import Header from "./header"; +import Header from "./header/header"; import Menu from "./menu"; import { redirect } from "next/navigation"; import { auth } from "../../server/auth"; diff --git a/apps/web/app/(dash)/menu.tsx b/apps/web/app/(dash)/menu.tsx index 29d25574..4b03604f 100644 --- a/apps/web/app/(dash)/menu.tsx +++ b/apps/web/app/(dash)/menu.tsx @@ -5,7 +5,7 @@ import Image from "next/image"; import Link from "next/link"; import { MemoriesIcon, ExploreIcon, CanvasIcon, AddIcon } from "@repo/ui/icons"; import { Button } from "@repo/ui/shadcn/button"; -import { PlusCircleIcon } from "lucide-react"; +import { MinusIcon, PlusCircleIcon } from "lucide-react"; import { Dialog, DialogContent, @@ -34,8 +34,9 @@ import { TooltipTrigger, } from "@repo/ui/shadcn/tooltip"; import { InformationCircleIcon } from "@heroicons/react/24/outline"; -import { createMemory } from "../actions/doers"; +import { createMemory, createSpace } from "../actions/doers"; import { Input } from "@repo/ui/shadcn/input"; +import ComboboxWithCreate from "@repo/ui/shadcn/combobox"; function Menu() { const [spaces, setSpaces] = useState<Space[]>([]); @@ -77,7 +78,7 @@ function Menu() { ]; const [content, setContent] = useState(""); - const [selectedSpace, setSelectedSpace] = useState<string | null>(null); + const [selectedSpaces, setSelectedSpaces] = useState<number[]>([]); const autoDetectedType = useMemo(() => { if (content.length === 0) { @@ -97,6 +98,15 @@ function Menu() { const [dialogOpen, setDialogOpen] = useState(false); + const options = useMemo( + () => + spaces.map((x) => ({ + label: x.name, + value: x.id.toString(), + })), + [spaces], + ); + const handleSubmit = async (content?: string, space?: string) => { setDialogOpen(false); @@ -212,7 +222,7 @@ function Menu() { className="text-[#858B92] flex items-center gap-1 duration-200 transform transition-transform" htmlFor="space" > - Space + Spaces <TooltipProvider> <Tooltip> <TooltipTrigger> @@ -227,26 +237,81 @@ function Menu() { </Tooltip> </TooltipProvider> </Label> - <Select - onValueChange={(value) => setSelectedSpace(value)} - value={selectedSpace ?? "none"} - defaultValue="none" - name="space" - > - <SelectTrigger className="mt-2"> - <SelectValue placeholder="None" /> - </SelectTrigger> - <SelectContent className="bg-secondary text-white"> - <SelectItem defaultChecked value="none"> - None - </SelectItem> - {spaces.map((space) => ( - <SelectItem key={space.id} value={space.id.toString()}> - {space.name} - </SelectItem> - ))} - </SelectContent> - </Select> + + <ComboboxWithCreate + options={spaces.map((x) => ({ + label: x.name, + value: x.id.toString(), + }))} + onSelect={(v) => + setSelectedSpaces((prev) => { + if (v === "") { + return []; + } + return [...prev, parseInt(v)]; + }) + } + onSubmit={async (spaceName) => { + const space = options.find((x) => x.label === spaceName); + toast.info("Creating space..."); + + if (space) { + toast.error("A space with that name already exists."); + } + + const creationTask = await createSpace(spaceName); + if (creationTask.success && creationTask.data) { + toast.success("Space created " + creationTask.data); + setSpaces?.((prev) => [ + ...prev, + { + name: spaceName, + id: creationTask.data!, + }, + ]); + setSelectedSpaces((prev) => [ + ...prev, + creationTask.data!, + ]); + } else { + toast.error( + "Space creation failed: " + creationTask.error ?? + "Unknown error", + ); + } + }} + placeholder="Save or create space by typing." + className="bg-[#2B3237] h-min rounded-md mt-2 mb-4" + /> + + <div> + {selectedSpaces.length > 0 && ( + <div className="flex flex-row flex-wrap gap-0.5 h-min"> + {selectedSpaces.map((x, idx) => ( + <button + key={x} + onClick={() => + setSelectedSpaces((prev) => + prev.filter((y) => y !== x), + ) + } + className={`relative group p-2 py-3 bg-[#3C464D] max-w-32 ${ + idx === selectedSpaces.length - 1 + ? "rounded-br-xl" + : "" + }`} + > + <p className="line-clamp-1"> + {spaces.find((y) => y.id === x)?.name} + </p> + <div className="absolute h-full right-0 top-0 p-1 opacity-0 group-hover:opacity-100 items-center"> + <MinusIcon className="w-6 h-6 rounded-full bg-secondary" /> + </div> + </button> + ))} + </div> + )} + </div> </div> )} diff --git a/apps/web/app/(landing)/page.tsx b/apps/web/app/(landing)/page.tsx index 4e574ad5..2b36df2a 100644 --- a/apps/web/app/(landing)/page.tsx +++ b/apps/web/app/(landing)/page.tsx @@ -9,16 +9,15 @@ import { auth } from "@/server/auth"; import Services from "./Features/index"; import { Showcases } from "./Showcase"; import BackgroundPlus from "./GridPatterns/PlusGrid"; +import { redirect } from "next/navigation"; export const runtime = "edge"; export default async function Home() { const user = await auth(); - console.log(user); - if (user) { - // await redirect("/home") + await redirect("/home"); } return ( diff --git a/apps/web/app/actions/doers.ts b/apps/web/app/actions/doers.ts index 95b31392..0c4e98db 100644 --- a/apps/web/app/actions/doers.ts +++ b/apps/web/app/actions/doers.ts @@ -41,7 +41,7 @@ export const createSpace = async ( .values({ name: input, user: data.user.id }); revalidatePath("/home"); - return { success: true, data: 1 }; + return { success: true, data: resp.meta.last_row_id }; } catch (e: unknown) { const error = e as Error; if ( diff --git a/apps/web/middleware.ts b/apps/web/middleware.ts new file mode 100644 index 00000000..b6cc4548 --- /dev/null +++ b/apps/web/middleware.ts @@ -0,0 +1,13 @@ +// middleware.js +import { NextRequest, NextResponse } from "next/server"; + +export function middleware(request: NextRequest) { + const requestHeaders = new Headers(request.headers); + requestHeaders.set("x-pathname", request.nextUrl.pathname); + + return NextResponse.next({ + request: { + headers: requestHeaders, + }, + }); +} diff --git a/packages/ui/shadcn/combobox.tsx b/packages/ui/shadcn/combobox.tsx index 9eb62cf8..9ab54ef1 100644 --- a/packages/ui/shadcn/combobox.tsx +++ b/packages/ui/shadcn/combobox.tsx @@ -21,10 +21,11 @@ interface Option { interface ComboboxWithCreateProps { options: Option[]; onSelect: (value: string) => void; - onSubmit: () => void; + onSubmit: (newName: string) => void; placeholder?: string; emptyMessage?: string; createNewMessage?: string; + className?: string; } const ComboboxWithCreate: React.FC<ComboboxWithCreateProps> = ({ @@ -34,9 +35,8 @@ const ComboboxWithCreate: React.FC<ComboboxWithCreateProps> = ({ placeholder = "Select an option", emptyMessage = "No option found.", createNewMessage = "Create", + className, }) => { - const [open, setOpen] = useState(false); - const [value, setValue] = useState(""); const [options, setOptions] = useState<Option[]>(initialOptions); const [inputValue, setInputValue] = useState(""); @@ -45,7 +45,7 @@ const ComboboxWithCreate: React.FC<ComboboxWithCreateProps> = ({ }, [initialOptions]); return ( - <Command className="w-40 group"> + <Command className={cn("group", className)}> <CommandInput onChangeCapture={(e) => setInputValue(e.currentTarget.value)} placeholder={placeholder} @@ -53,7 +53,9 @@ const ComboboxWithCreate: React.FC<ComboboxWithCreateProps> = ({ /> <CommandList className="z-10 translate-y-12 translate-x-5 opacity-0 absolute group-focus-within:opacity-100 bg-secondary p-2 rounded-b-xl max-w-64"> <CommandEmpty> - {createNewMessage} "{inputValue}" + <Button onClick={async () => onSubmit(inputValue)} variant="link"> + {createNewMessage} "{inputValue}" + </Button> </CommandEmpty> <CommandGroup className="hidden group-focus-within:block" diff --git a/packages/ui/shadcn/command.tsx b/packages/ui/shadcn/command.tsx index 802dfb11..dfc54283 100644 --- a/packages/ui/shadcn/command.tsx +++ b/packages/ui/shadcn/command.tsx @@ -14,10 +14,7 @@ const Command = React.forwardRef< >(({ className, ...props }, ref) => ( <CommandPrimitive ref={ref} - className={cn( - "flex h-full w-full flex-col overflow-hidden rounded-bl-3xl bg-[#3C464D]", - className, - )} + className={cn("flex h-full w-full flex-col overflow-hidden", className)} {...props} /> )); |