Skip to content

Commit 55373bb

Browse files
committed
add comment polling
1 parent 8e0d214 commit 55373bb

8 files changed

+86
-28
lines changed

prisma/schema.prisma

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ model Document {
2424

2525
model Comment {
2626
id String @id @default(uuid()) @map("_id")
27-
text String
27+
content String
2828
document Document @relation(fields: [documentId], references: [id])
2929
documentId String
3030
createdAt DateTime @default(now())

src/components/Comment.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { Comment } from "@prisma/client";
2+
13
function Comment({ title, content }: { title: string; content: string }) {
24
return (
35
<div className="px-3 border-black-10 rounded-lg p-2 bg-[#fff] border">
@@ -10,7 +12,7 @@ function Comment({ title, content }: { title: string; content: string }) {
1012
export default function Comments({
1113
comments,
1214
}: {
13-
comments: { title: string; content: string }[]
15+
comments: Comment[]
1416
}) {
1517
return (
1618
<div className="grid gap-4">

src/components/CommentInput.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@
22

33
import { Button } from "@/components/ui/button";
44
import { Textarea } from "@/components/ui/textarea";
5+
import { useState } from "react";
56
import { toast } from "sonner";
7+
import { createComment } from "./comment-actions";
68

7-
export default function CommentInput() {
9+
export default function CommentInput({ documentId }: { documentId: string }) {
10+
const [content, setContent] = useState("");
811
const handleSubmit = () => {
12+
createComment(content, documentId);
913
toast.success("Comment submitted!");
1014
};
1115

1216
return (
1317
<div className="grid w-full gap-2">
14-
<Textarea placeholder="Type your message here." className="resize-none" />
18+
<Textarea placeholder="Type your message here." className="resize-none" value={content} onChange={(e) => setContent(e.target.value)} />
1519
<Button onClick={handleSubmit}>Send comment</Button>
1620
</div>
1721
);

src/components/DocumentView.tsx

+15-19
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
'use client'
12
import { Button } from "@/components/ui/button";
23
import {
34
Dialog,
@@ -8,27 +9,21 @@ import {
89
DialogTitle,
910
DialogTrigger,
1011
} from "@/components/ui/dialog";
11-
import Comment from "./Comment";
12-
import Comments from "./Comment";
1312
import Tags from "./Tags";
1413
import CommentInput from "./CommentInput";
1514
import { useEffect, useRef } from "react";
15+
import { SearchResults } from "@/lib/embedding";
16+
import Comments from "./Comment";
1617

17-
export default function DocumentView({
18-
documentName,
19-
documentTags,
20-
documentUrl,
21-
comments,
22-
}: {
23-
documentName: string;
24-
documentTags: string[];
25-
documentUrl: string;
26-
comments: { title: string; content: string }[];
27-
}) {
18+
export default function DocumentView(results
19+
: {
20+
results: SearchResults["results"][number];
21+
}) {
2822
const embedRef = useRef<HTMLEmbedElement>(null);
2923

3024
useEffect(() => {
31-
fetch(documentUrl)
25+
console.log(results.results.url);
26+
fetch(results.results.url)
3227
.then((res) => res.blob())
3328
.then((blob) => {
3429
const blobToBase64 = (blob) => {
@@ -53,14 +48,15 @@ export default function DocumentView({
5348
}
5449
const embed = embedRef.current;
5550
// replace octet-stream with pdf
56-
const url = documentUrl.replace(
51+
const url = results.results.url.replace(
5752
"application/octet-stream",
5853
"application/pdf"
5954
);
6055
embed.setAttribute("type", "application/pdf");
6156
embed.setAttribute("src", url);
6257
});
6358
}, []);
59+
6460
return (
6561
<Dialog aria-label="Edit Profile" defaultOpen>
6662
<DialogContent className="sm:max-w-[80vw] max-[50vw]: grid gap-4 grid-cols-3 h-[90vh] bg-gray-100">
@@ -74,12 +70,12 @@ export default function DocumentView({
7470
</div>
7571
<div className="col-span-3 sm:col-span-1 max-h-[100%] flex flex-col justify-between bg-white p-3 rounded-lg">
7672
<div className="flex flex-col gap-4 overflow-y-auto">
77-
<h1 className="text-3xl font-bold">{documentName}</h1>
78-
<Tags text={documentTags} />
73+
<h1 className="text-3xl font-bold">{results.results.name}</h1>
74+
<Tags text={results.results.tags} />
7975

80-
<Comments comments={comments} />
76+
<Comments comments={results.results.comments} />
8177
</div>
82-
<CommentInput />
78+
<CommentInput documentId={results.results.documentId} />
8379
</div>
8480
</DialogContent>
8581
</Dialog>

src/components/Thumbnails.tsx

+33-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,46 @@
11
'use client'
22
import { useSearch } from '@/context/SearchContext'
3-
import React, { useEffect, useState } from 'react'
3+
import React, { useEffect, useRef, useState } from 'react'
44
import { AspectRatio } from './ui/aspect-ratio';
55
import Image from 'next/image';
66
import DocumentView from './DocumentView';
7+
import { search } from '@/lib/embedding';
78

89

10+
export function useInterval(callback: () => void, delay: number) {
11+
const savedCallback = useRef<() => void>(() => {
12+
console.log('Default useInterval callback, unreachable');
13+
});
14+
15+
// Remember the latest callback.
16+
useEffect(() => {
17+
savedCallback.current = callback;
18+
}, [callback]);
19+
20+
// Set up the interval.
21+
useEffect(() => {
22+
function tick() {
23+
savedCallback.current();
24+
}
25+
if (delay !== null) {
26+
let id = setInterval(tick, delay);
27+
return () => clearInterval(id);
28+
}
29+
}, [delay]);
30+
}
931
export const Thumbnails = (props: {}) => {
1032
const [results, setResults] = useSearch();
1133
const [selectedDoc, setSelectedDoc] = useState<number | null>(null);
34+
35+
useInterval(async () => {
36+
if (results === null) return;
37+
console.log('polling for new search results');
38+
setResults(await search(results!.query));
39+
}, 2000);
40+
1241
return (
1342
<div className="flex gap-2 w-full h-full">
14-
{results?.map((result, index) => {
43+
{results?.results.map((result, index) => {
1544
return (
1645
// paper aspect ratio
1746
<AspectRatio ratio={9 / 16} key={result.documentId} className='w-60 h-60'
@@ -28,8 +57,8 @@ export const Thumbnails = (props: {}) => {
2857
)
2958
}
3059
)}
31-
{selectedDoc !== null && (
32-
<DocumentView documentName={results![selectedDoc]!.name} documentTags={results![selectedDoc]!.tags} documentUrl={results![selectedDoc]!.url} comments={[]} />
60+
{selectedDoc !== null && results !== null && (
61+
<DocumentView results={results.results[selectedDoc]} />
3362
)}
3463
</div>
3564
)

src/components/comment-actions.ts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use server'
2+
import { db } from "@/lib/db";
3+
4+
export async function createComment(content: string, documentId: string) {
5+
const comment = await db.comment.create({
6+
data: {
7+
content: content,
8+
documentId: documentId,
9+
}
10+
})
11+
}

src/context/SearchContext.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ const useSearch = () => {
1818
return context;
1919
};
2020

21+
22+
// poll for search results
23+
24+
2125
function SearchProvider({ children }: { children: React.ReactNode }) {
2226
const [results, setResults] = useState<SearchResults | null>(null);
2327
return (

src/lib/embedding.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ export async function search(query: string, n: number = 3) {
4747
.sort((a, b) => a.similarity - b.similarity)
4848
.slice(0, Math.min(similarities.length, n))
4949

50+
const comments = await db.comment.findMany({
51+
where: {
52+
documentId: {
53+
in: topN.map((r) => r.documentId),
54+
},
55+
},
56+
});
57+
5058

5159
const resultsWithThumbnails = await Promise.all(
5260
topN.map(async (r) => {
@@ -55,10 +63,14 @@ export async function search(query: string, n: number = 3) {
5563
...r,
5664
thumbnail,
5765
url: await getPdf(r.documentId),
66+
comments: comments.filter((c) => c.documentId === r.documentId),
5867
};
5968
})
6069
);
61-
return resultsWithThumbnails;
70+
return {
71+
results: resultsWithThumbnails,
72+
query,
73+
};
6274

6375

6476

0 commit comments

Comments
 (0)