Skip to content

Commit b975d17

Browse files
committed
Merge branch 'main' into add-archive-and-misc
2 parents 2794a51 + 2e8da22 commit b975d17

File tree

15 files changed

+308
-91
lines changed

15 files changed

+308
-91
lines changed

app/api/document/[datasetId]/[documentId]/route.ts

Lines changed: 0 additions & 40 deletions
This file was deleted.

app/chatrooms/[chatroomId]/components/message-area.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ const MessageArea = ({
198198
const askResult = await askLLM(classroomInfo, chatroomId, chatClient);
199199
if (!askResult.clientCreationSuccess) {
200200
if (!askResult.failedBecauseEmptyDataset) {
201-
// TODO: ask result has more detailed error differntiations if we want to tell the user
201+
// TODO: ask result has more detailed error differentiations if we want to tell the user
202202
toast.error("Error sending communicating with LLM", {
203203
description: "Please refresh and try again",
204204
});
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
"use client";
2+
import { useState, useRef } from "react";
3+
4+
import { Button } from "@shared/components/ui/button";
5+
import { Input } from "@shared/components/ui/input";
6+
7+
import { FileText, Upload } from "lucide-react";
8+
import { toast } from "sonner";
9+
10+
export default function AugmentComponent({
11+
// TODO: remove for classroomId and setIsProcessing once we actually implement augments
12+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
13+
classroomId,
14+
}: {
15+
classroomId: string;
16+
}) {
17+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
18+
const [isProcessing, setIsProcessing] = useState(false);
19+
const [file, setFile] = useState<File | null>(null);
20+
const inputFile = useRef<HTMLInputElement>(null);
21+
22+
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
23+
const selectedFile = e.target.files?.[0];
24+
if (!selectedFile) return;
25+
26+
// Double-check that file passed by user is markdown or pdf
27+
const fileExtension = selectedFile.name.split(".").at(-1)?.toLowerCase();
28+
if (fileExtension !== "pdf" && fileExtension !== "md") {
29+
toast.error("Invalid file format", {
30+
description: "Please upload a Markdown (.md) or PDF (.pdf) file",
31+
});
32+
return;
33+
}
34+
35+
setFile(selectedFile);
36+
};
37+
38+
const handleUpload = async () => {
39+
// TODO
40+
};
41+
42+
return (
43+
<div className="flex flex-col items-center justify-center gap-4 p-8">
44+
<h1 className="text-3xl font-bold">Augment Notes</h1>
45+
<p className="text-muted-foreground">
46+
Upload your notes to get AI-powered enhancements and improvements
47+
</p>
48+
<div className="flex items-center gap-2">
49+
<Input
50+
type="file"
51+
onChange={handleFileChange}
52+
ref={inputFile}
53+
className="hidden"
54+
accept=".md,.pdf"
55+
/>
56+
<Button
57+
variant="outline"
58+
size="lg"
59+
className="cursor-pointer"
60+
disabled={isProcessing}
61+
onClick={() => inputFile.current?.click()}
62+
>
63+
{isProcessing ? (
64+
<Upload className="mr-2 h-4 w-4 animate-spin" />
65+
) : (
66+
<FileText className="mr-2 h-4 w-4" />
67+
)}
68+
Upload Notes
69+
</Button>
70+
{file && (
71+
<Button
72+
variant="default"
73+
size="lg"
74+
onClick={handleUpload}
75+
disabled={isProcessing}
76+
>
77+
Process Notes
78+
</Button>
79+
)}
80+
</div>
81+
</div>
82+
);
83+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { createClient } from "@shared/utils/supabase/server";
2+
import { notFound } from "next/navigation";
3+
4+
import AugmentComponent from "./AugmentNotes";
5+
6+
export default async function UploadPage({
7+
params,
8+
}: {
9+
params: Promise<{ classroomId: string }>;
10+
}) {
11+
const { classroomId } = await params;
12+
13+
const supabase = await createClient();
14+
const { data, error } = await supabase
15+
.from("Classrooms")
16+
.select("name")
17+
.eq("id", Number(classroomId))
18+
.single();
19+
20+
if (error || !data || !data.name) {
21+
console.error("Error fetching classroom or its name:", error);
22+
notFound();
23+
}
24+
25+
return (
26+
<>
27+
<h1>Classroom: {data.name}</h1>
28+
<AugmentComponent classroomId={classroomId} />
29+
</>
30+
);
31+
}

app/classrooms/[classroomId]/chat/MessageBox.tsx

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
import { ChatMessageList } from "@shared/components/ui/chat/chat-message-list";
99
import { ChatInput } from "@shared/components/ui/chat/chat-input";
1010
import { Button } from "@/shared/components/ui/button";
11-
1211
import {
1312
ChatClientWithSession,
1413
RagFlowMessage,
@@ -36,8 +35,7 @@ export default function MessageBox({
3635
const [isLoading, setIsLoading] = useState(false);
3736

3837
function cleanMessage(content: string): string {
39-
// Remove any reference patterns like ##number$$
40-
return content.replace(/##\d+\$\$/g, "").trim();
38+
return content.replace(/\s##\d+\$\$/g, "").trim();
4139
}
4240

4341
async function handleSend() {
@@ -66,17 +64,19 @@ export default function MessageBox({
6664
}
6765

6866
return (
69-
<div className="flex h-[600px] w-11/12 flex-col place-self-center rounded border p-4 text-gray-800 shadow dark:text-white">
67+
<div className="flex h-[80vh] min-h-[400px] w-11/12 flex-col place-self-center rounded border p-4 text-gray-800 shadow dark:text-white max-[500px]:w-full">
7068
<Logo
71-
className={"size-24 place-self-center stroke-black stroke-[10px]"}
69+
className={
70+
"size-[6vmin] h-fit min-w-10 place-self-center stroke-black stroke-[10px]"
71+
}
7272
/>
73-
{/* doesn't seem like 400 px does much */}
74-
<div className="h-[400px] flex-1 overflow-auto">
75-
<ChatMessageList smooth>
73+
<div className="flex-1 overflow-auto">
74+
<ChatMessageList smooth className="max-[500px]:px-0">
7675
{messages.map((msg, index) => (
7776
<ChatBubble
7877
key={index}
7978
variant={msg.role === "assistant" ? "received" : "sent"}
79+
className="max-w-[80%]"
8080
>
8181
{msg.role === "assistant" ? (
8282
<ChatBubbleAvatar fallback="AI" />
@@ -99,18 +99,15 @@ export default function MessageBox({
9999
)}
100100
</ChatMessageList>
101101
</div>
102-
<div className="relative mt-4">
102+
<div className="flex w-full items-center justify-between gap-2 rounded-lg border bg-background p-1">
103103
<ChatInput
104104
value={value}
105105
onChange={(e) => setValue(e.target.value)}
106106
placeholder="Type your message..."
107107
onEnter={handleSend}
108+
className="focus-visible:ringof min-h-10 resize-none border-0 bg-background shadow-none focus-visible:ring-0"
108109
/>
109-
<Button
110-
onClick={handleSend}
111-
size="default"
112-
className="absolute right-2 top-1/2 -translate-y-1/2"
113-
>
110+
<Button onClick={handleSend} size="sm" className="ml-auto mr-3">
114111
Send <SendIcon />
115112
</Button>
116113
</div>

app/classrooms/[classroomId]/chat/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ export default async function ChatPage({
139139

140140
// // console.log("chatAssistant", chatAssistant);
141141
return (
142-
<div className="p-4">
142+
<div className="p-4 max-[500px]:px-0">
143143
{/* <p>
144144
<strong>Classroom ID: </strong>
145145
{classroomId}

app/classrooms/[classroomId]/manage/_components/inviteMember.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@ export default function InviteMember({ classroomId }: { classroomId: number }) {
1515
} catch (error: unknown) {
1616
//type unknown for typescript lint
1717
if (error instanceof Error) {
18-
toast.error(
19-
"The user is already part of the classroom."
20-
// description: { email } + "was added to the class.",
21-
);
18+
toast.error("The user is already part of the classroom.");
2219
// console.error(error.message);
2320
} else {
2421
console.error("Error Occured");

app/classrooms/[classroomId]/upload/page.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import { isUserAdminForClassroom } from "./actions";
2-
import UploadComponent from "./uploadComponent";
1+
import { notFound } from "next/navigation";
32
import { createClient } from "@shared/utils/supabase/server";
43

4+
import UploadComponent from "./uploadComponent";
5+
import { isUserAdminForClassroom } from "./actions";
6+
57
export default async function UploadPage({
68
params,
79
}: {
@@ -10,9 +12,7 @@ export default async function UploadPage({
1012
const { classroomId } = await params;
1113
const isAdmin = await isUserAdminForClassroom(Number(classroomId));
1214
if (!isAdmin) {
13-
return (
14-
<h1> Not the admin for this classroom! But change this to 404 page </h1>
15-
);
15+
notFound();
1616
}
1717

1818
// #TODO: move this out to general supabase place
@@ -25,7 +25,7 @@ export default async function UploadPage({
2525

2626
if (error || !data || !data.name) {
2727
console.error("Error fetching classroom or its name:", error);
28-
return <h1> Insert 404 page here</h1>;
28+
notFound();
2929
}
3030

3131
return (
Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,42 @@
1+
import { downloadDocument } from "@/shared/lib/ragflow/dataset-client";
2+
import { notFound } from "next/navigation";
3+
14
export default async function PreviewPage({
25
searchParams,
36
}: {
47
searchParams: Promise<{ documentId: string; datasetId: string }>;
58
}) {
69
const { documentId, datasetId } = await searchParams;
710

8-
return (
9-
<div className="h-screen w-screen">
10-
<embed
11-
src={`/api/document/${datasetId}/${documentId}`}
12-
width="100%"
13-
height="100%"
14-
/>
15-
</div>
16-
);
11+
const { ragflowCallSuccess, content, mimeType, fileName } =
12+
await downloadDocument(datasetId, documentId);
13+
14+
if (!ragflowCallSuccess) {
15+
notFound();
16+
}
17+
18+
console.log(`Rendering file: ${fileName}, with MIME type: ${mimeType}`);
19+
20+
if (mimeType === "application/octet-stream") {
21+
// We fallback to rendering as text
22+
const text = new TextDecoder().decode(new Uint8Array(content));
23+
return (
24+
<div className="mx-auto h-screen w-4/5">
25+
<pre className="overflow-auto whitespace-pre-wrap p-4">{text}</pre>
26+
</div>
27+
);
28+
} else {
29+
// Convert binary content to base64 for embedding non-text file types
30+
// Allows us to render PDFs, images and other binary formats directly in the browser
31+
const base64Content = Buffer.from(content).toString("base64");
32+
return (
33+
<div className="mx-auto h-screen w-4/5">
34+
<embed
35+
src={`data:${mimeType};base64,${base64Content}`}
36+
width="100%"
37+
height="100%"
38+
/>
39+
</div>
40+
);
41+
}
1742
}

0 commit comments

Comments
 (0)