aboutsummaryrefslogtreecommitdiff
path: root/apps/web/src
diff options
context:
space:
mode:
authorDhravya <[email protected]>2024-03-01 11:43:40 -0700
committerDhravya <[email protected]>2024-03-01 11:43:40 -0700
commitb8e070c1ac37251129774f8e7d70fdbcf94bee8c (patch)
treef9793b1146446c9c709a8f752c6b334760a62c36 /apps/web/src
parentextension workoing (diff)
downloadsupermemory-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.ts16
-rw-r--r--apps/web/src/app/api/store/route.ts2
-rw-r--r--apps/web/src/app/page.tsx139
-rw-r--r--apps/web/src/components/component.tsx87
-rw-r--r--apps/web/src/server/auth.ts19
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({