diff options
| author | Dhravya <[email protected]> | 2024-03-01 11:43:40 -0700 |
|---|---|---|
| committer | Dhravya <[email protected]> | 2024-03-01 11:43:40 -0700 |
| commit | b8e070c1ac37251129774f8e7d70fdbcf94bee8c (patch) | |
| tree | f9793b1146446c9c709a8f752c6b334760a62c36 /apps/web/src | |
| parent | extension workoing (diff) | |
| download | supermemory-b8e070c1ac37251129774f8e7d70fdbcf94bee8c.tar.xz supermemory-b8e070c1ac37251129774f8e7d70fdbcf94bee8c.zip | |
feat: Added AI query UI
Diffstat (limited to 'apps/web/src')
| -rw-r--r-- | apps/web/src/app/api/query/route.ts | 16 | ||||
| -rw-r--r-- | apps/web/src/app/api/store/route.ts | 2 | ||||
| -rw-r--r-- | apps/web/src/app/page.tsx | 139 | ||||
| -rw-r--r-- | apps/web/src/components/component.tsx | 87 | ||||
| -rw-r--r-- | apps/web/src/server/auth.ts | 19 |
5 files changed, 150 insertions, 113 deletions
diff --git a/apps/web/src/app/api/query/route.ts b/apps/web/src/app/api/query/route.ts index 9be23321..4e2f0674 100644 --- a/apps/web/src/app/api/query/route.ts +++ b/apps/web/src/app/api/query/route.ts @@ -24,22 +24,26 @@ export async function GET(req: NextRequest) { const session = {session: sessionData[0], user: user[0]} const query = new URL(req.url).searchParams.get("q"); + const sourcesOnly = new URL(req.url).searchParams.get("sourcesOnly") ?? "false"; if (!query) { return new Response(JSON.stringify({ message: "Invalid query" }), { status: 400 }); } - const resp = await fetch(`https://cf-ai-backend.dhravya.workers.dev/query?q=${query}&user=${session.user.email ?? session.user.name}`, { + const resp = await fetch(`https://cf-ai-backend.dhravya.workers.dev/query?q=${query}&user=${session.user.email ?? session.user.name}&sourcesOnly=${sourcesOnly}`, { headers: { "X-Custom-Auth-Key": env.BACKEND_SECURITY_KEY, } }) - const data = await resp.json() - - if (resp.status !== 200) { - return new Response(JSON.stringify({ message: "Error in CF function", error: data }), { status: resp.status }); + if (resp.status !== 200 || !resp.ok) { + const errorData = await resp.json(); + return new Response(JSON.stringify({ message: "Error in CF function", error: errorData }), { status: resp.status }); } - return new Response(JSON.stringify({ message: "OK", data: data }), { status: 200 }); + // Stream the response back to the client + const { readable, writable } = new TransformStream(); + resp && resp.body!.pipeTo(writable); + + return new Response(readable, { status: 200 }); }
\ No newline at end of file diff --git a/apps/web/src/app/api/store/route.ts b/apps/web/src/app/api/store/route.ts index 5856bc4f..46e4cdfb 100644 --- a/apps/web/src/app/api/store/route.ts +++ b/apps/web/src/app/api/store/route.ts @@ -80,6 +80,8 @@ export async function POST(req: NextRequest) { const _ = await res.text(); + console.log(_) + if (res.status !== 200) { return NextResponse.json({ message: "Error", error: "Error in CF function" }, { status: 500 }); } diff --git a/apps/web/src/app/page.tsx b/apps/web/src/app/page.tsx index c78483db..6de490f8 100644 --- a/apps/web/src/app/page.tsx +++ b/apps/web/src/app/page.tsx @@ -1,16 +1,135 @@ -import Image from "next/image"; -import MessagePoster from "./MessagePoster"; -import { cookies } from "next/headers"; -import { Component } from "@/components/component"; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { CardContent, Card } from '@/components/ui/card'; +import { db } from '@/server/db'; +import { + sessions, + storedContent, + userStoredContent, + users, +} from '@/server/db/schema'; +import { eq, inArray } from 'drizzle-orm'; +import { cookies, headers } from 'next/headers'; +import { redirect } from 'next/navigation'; +import { Label } from '@/components/ui/label'; +import Image from 'next/image'; +import QueryAI from '@/components/QueryAI'; export const runtime = 'edge'; -export default function Home() { - const token = cookies().get('next-auth.session-token')?.value ?? cookies().get("__Secure-authjs.session-token")?.value ?? cookies().get("authjs.session-token")?.value +export default async function Home() { + const token = + cookies().get('next-auth.session-token')?.value ?? + cookies().get('__Secure-authjs.session-token')?.value ?? + cookies().get('authjs.session-token')?.value ?? + headers().get('Authorization')?.replace('Bearer ', ''); + + if (!token) { + return redirect('/api/auth/signin'); + } + + const session = await db + .select() + .from(sessions) + .where(eq(sessions.sessionToken, token!)); + + if (!session || session.length === 0) { + return redirect('/api/auth/signin'); + } + + const userContent = await db + .select() + .from(userStoredContent) + .where(eq(userStoredContent.userId, session[0].userId)); + + const userData = await db + .select() + .from(users) + .where(eq(users.id, session[0].userId)) + .limit(1); + + if (!userData || userData.length === 0) { + return redirect('/api/auth/signin'); + } + + const listOfContent = + userContent.map((content) => content.contentId).length > 0 + ? userContent.map((content) => content.contentId) + : [1]; + + const posts = await db + .select() + .from(storedContent) + .where(inArray(storedContent.id, listOfContent)); + return ( - <main> - {token && <MessagePoster jwt={token} />} - <Component/> - </main> + <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex flex-col items-center"> + <div className="flex flex-col mt-16"> + <div className="flex flex-col md:flex-row gap-4"> + <Image + className="rounded-2xl" + src="/logo.png" + width={120} + height={120} + alt="logo" + /> + <div className="mt-4 text-gray-400 max-w-md"> + <h1 className="text-xl font-bold text-white">SuperMemory</h1> + Remember that one thing you read a while ago? We got you covered. + Add the extension, click a button and I'll remember it for you.{' '} + <a + href="https://github.com/dhravyashah/anycontext" + target="_blank" + rel="noreferrer" + className="text-sky-500" + > + Get the Extension + </a> + </div> + </div> + </div> + + <QueryAI /> + + {/* TODO: LABEL THE WEBSITES USING A CLASSIFICATION MODEL */} + {/* <nav className="flex space-x-2 my-4"> + <Badge variant="secondary">Technology (2)</Badge> + <Badge variant="secondary">Business & Finance (1)</Badge> + <Badge variant="secondary">Education & Career (1)</Badge> + </nav> */} + <main className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mt-16"> + {posts.reverse().map((post) => ( + <a + href={post.url} + target="_blank" + rel="noreferrer" + className="hover:scale-105 ease-in-out transition-transform duration-300" + > + <Card className="w-full"> + <img + alt="Not found" + className="w-full h-48 object-cover rounded-md" + height="200" + src={ + post.image && post.image !== 'Image not found' + ? post.image + : '/placeholder.svg' + } + style={{ + aspectRatio: '300/200', + objectFit: 'cover', + }} + width="300" + /> + <CardContent> + <h3 className="text-lg font-semibold mt-4">{post.title}</h3> + <p className="text-sm text-gray-600">{post.baseUrl}</p> + <p className="text-sm">{post.description}</p> + </CardContent> + </Card> + </a> + ))} + </main> + </div> ); } diff --git a/apps/web/src/components/component.tsx b/apps/web/src/components/component.tsx deleted file mode 100644 index 117c23b5..00000000 --- a/apps/web/src/components/component.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { Input } from '@/components/ui/input'; -import { AvatarImage, AvatarFallback, Avatar } from '@/components/ui/avatar'; -import { Button } from '@/components/ui/button'; -import { Badge } from '@/components/ui/badge'; -import { CardContent, CardFooter, Card } from '@/components/ui/card'; -import { db } from '@/server/db'; -import { storedContent } from '@/server/db/schema'; -import { parser } from 'html-metadata-parser'; -import { getMetaData } from '@/server/helpers'; - - -export async function Component() { - // const posts = await db.query.storedContent.findMany({ - // where: (users, { eq }) => eq(users.id, 1), - // }); - - return ( - <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> - <header className="flex justify-between items-center py-6"> - <div className="flex items-center space-x-4"> - <FlagIcon className="h-8 w-8 text-blue-500" /> - <h1 className="text-3xl font-bold text-gray-900">zenfetch</h1> - </div> - <div className="flex items-center space-x-4"> - <Input className="w-72" placeholder="Search..." /> - <Avatar> - <AvatarImage - alt="User avatar" - src="/placeholder.svg?height=32&width=32" - /> - <AvatarFallback>U</AvatarFallback> - </Avatar> - <Button className="whitespace-nowrap" variant="outline"> - Chat with AI - </Button> - </div> - </header> - <nav className="flex space-x-2 my-4"> - <Badge variant="secondary">Technology (2)</Badge> - <Badge variant="secondary">Business & Finance (1)</Badge> - <Badge variant="secondary">Education & Career (1)</Badge> - </nav> - <main className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> - {/* {metadata.map((post) => ( - <Card className="w-full"> - <img - alt="Hard drive" - className="w-full h-48 object-cover" - height="200" - src={post.image} - style={{ - aspectRatio: '300/200', - objectFit: 'cover', - }} - width="300" - /> - <CardContent> - <h3 className="text-lg font-semibold mt-4">{post.title}</h3> - <p className="text-sm text-gray-600">{post.baseUrl}</p> - <p className="text-sm">{post.description}</p> - </CardContent> - </Card> - ))} */} - </main> - </div> - ); -} - -function FlagIcon(props: React.SVGProps<SVGSVGElement>) { - return ( - <svg - {...props} - xmlns="http://www.w3.org/2000/svg" - width="24" - height="24" - viewBox="0 0 24 24" - fill="none" - stroke="currentColor" - strokeWidth="2" - strokeLinecap="round" - strokeLinejoin="round" - > - <path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z" /> - <line x1="4" x2="4" y1="22" y2="15" /> - </svg> - ); -} diff --git a/apps/web/src/server/auth.ts b/apps/web/src/server/auth.ts index 3ceb7ac9..c32efe55 100644 --- a/apps/web/src/server/auth.ts +++ b/apps/web/src/server/auth.ts @@ -10,16 +10,15 @@ export const { } = NextAuth({ secret: env.NEXTAUTH_SECRET, trustHost: true, - // callbacks: { - // session: ({ session, token }) => ({ - // ...session, - // user: { - // // ...session.user, - // id: token.id as string, - // token: token, - // }, - // }) - // }, + callbacks: { + session: ({ session, token, user }) => ({ + ...session, + user: { + ...session.user, + id: user.id + }, + }) + }, adapter: DrizzleAdapter(db), providers: [ Google({ |