Spaces:
Sleeping
Sleeping
harryagasi commited on
Commit ·
e9814c9
1
Parent(s): 3baad7e
fix(upload file): drag and drop file
Browse files- src/app/App.tsx +14 -0
- src/app/components/KnowledgeManagement.tsx +40 -3
src/app/App.tsx
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
|
|
| 1 |
import { ThemeProvider } from "next-themes";
|
| 2 |
import { RouterProvider } from "react-router";
|
| 3 |
import { router } from "./routes";
|
| 4 |
import { Toaster } from "./components/ui/sonner";
|
| 5 |
|
| 6 |
export default function App() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
return (
|
| 8 |
<ThemeProvider attribute="class" defaultTheme="light" enableSystem disableTransitionOnChange>
|
| 9 |
<RouterProvider router={router} />
|
|
|
|
| 1 |
+
import { useEffect } from "react";
|
| 2 |
import { ThemeProvider } from "next-themes";
|
| 3 |
import { RouterProvider } from "react-router";
|
| 4 |
import { router } from "./routes";
|
| 5 |
import { Toaster } from "./components/ui/sonner";
|
| 6 |
|
| 7 |
export default function App() {
|
| 8 |
+
// Safety net: without this, a file dropped just outside a dropzone
|
| 9 |
+
// (whitespace, a child element) falls through to the browser's
|
| 10 |
+
// default behavior, which opens/downloads the file instead of no-op.
|
| 11 |
+
useEffect(() => {
|
| 12 |
+
const preventDefault = (e: DragEvent) => e.preventDefault();
|
| 13 |
+
window.addEventListener("dragover", preventDefault);
|
| 14 |
+
window.addEventListener("drop", preventDefault);
|
| 15 |
+
return () => {
|
| 16 |
+
window.removeEventListener("dragover", preventDefault);
|
| 17 |
+
window.removeEventListener("drop", preventDefault);
|
| 18 |
+
};
|
| 19 |
+
}, []);
|
| 20 |
+
|
| 21 |
return (
|
| 22 |
<ThemeProvider attribute="class" defaultTheme="light" enableSystem disableTransitionOnChange>
|
| 23 |
<RouterProvider router={router} />
|
src/app/components/KnowledgeManagement.tsx
CHANGED
|
@@ -103,6 +103,7 @@ export default function KnowledgeManagement({
|
|
| 103 |
const [docsError, setDocsError] = useState<string | null>(null);
|
| 104 |
const [uploading, setUploading] = useState(false);
|
| 105 |
const [uploadError, setUploadError] = useState<string | null>(null);
|
|
|
|
| 106 |
const [processing, setProcessing] = useState<string | null>(null);
|
| 107 |
const [deleting, setDeleting] = useState<string | null>(null);
|
| 108 |
|
|
@@ -227,8 +228,7 @@ export default function KnowledgeManagement({
|
|
| 227 |
}
|
| 228 |
};
|
| 229 |
|
| 230 |
-
const
|
| 231 |
-
const files = e.target.files;
|
| 232 |
if (!files || files.length === 0) return;
|
| 233 |
const userId = getUserId();
|
| 234 |
if (!userId) return;
|
|
@@ -251,9 +251,25 @@ export default function KnowledgeManagement({
|
|
| 251 |
}
|
| 252 |
|
| 253 |
setUploading(false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 254 |
e.target.value = "";
|
| 255 |
};
|
| 256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 257 |
const processDocumentById = async (userId: string, docId: string) => {
|
| 258 |
setProcessing(docId);
|
| 259 |
setDocuments((prev) =>
|
|
@@ -584,7 +600,26 @@ export default function KnowledgeManagement({
|
|
| 584 |
{/* Upload zone */}
|
| 585 |
<label
|
| 586 |
htmlFor="file-upload"
|
| 587 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 588 |
>
|
| 589 |
<div className="w-10 h-10 rounded-xl bg-slate-100 group-hover:bg-orange-100 flex items-center justify-center transition-colors">
|
| 590 |
{uploading ? (
|
|
@@ -597,6 +632,8 @@ export default function KnowledgeManagement({
|
|
| 597 |
<p className="text-sm font-medium text-slate-700">
|
| 598 |
{uploading
|
| 599 |
? "Uploading..."
|
|
|
|
|
|
|
| 600 |
: <>Drop files, or <span className="text-[#FF8F00]">browse</span></>
|
| 601 |
}
|
| 602 |
</p>
|
|
|
|
| 103 |
const [docsError, setDocsError] = useState<string | null>(null);
|
| 104 |
const [uploading, setUploading] = useState(false);
|
| 105 |
const [uploadError, setUploadError] = useState<string | null>(null);
|
| 106 |
+
const [isDragging, setIsDragging] = useState(false);
|
| 107 |
const [processing, setProcessing] = useState<string | null>(null);
|
| 108 |
const [deleting, setDeleting] = useState<string | null>(null);
|
| 109 |
|
|
|
|
| 228 |
}
|
| 229 |
};
|
| 230 |
|
| 231 |
+
const uploadFiles = async (files: FileList) => {
|
|
|
|
| 232 |
if (!files || files.length === 0) return;
|
| 233 |
const userId = getUserId();
|
| 234 |
if (!userId) return;
|
|
|
|
| 251 |
}
|
| 252 |
|
| 253 |
setUploading(false);
|
| 254 |
+
};
|
| 255 |
+
|
| 256 |
+
const handleFileUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
| 257 |
+
const files = e.target.files;
|
| 258 |
+
if (!files) return;
|
| 259 |
+
await uploadFiles(files);
|
| 260 |
e.target.value = "";
|
| 261 |
};
|
| 262 |
|
| 263 |
+
const handleFileDrop = async (e: React.DragEvent<HTMLLabelElement>) => {
|
| 264 |
+
e.preventDefault();
|
| 265 |
+
e.stopPropagation();
|
| 266 |
+
setIsDragging(false);
|
| 267 |
+
if (uploading) return;
|
| 268 |
+
const files = e.dataTransfer.files;
|
| 269 |
+
if (!files || files.length === 0) return;
|
| 270 |
+
await uploadFiles(files);
|
| 271 |
+
};
|
| 272 |
+
|
| 273 |
const processDocumentById = async (userId: string, docId: string) => {
|
| 274 |
setProcessing(docId);
|
| 275 |
setDocuments((prev) =>
|
|
|
|
| 600 |
{/* Upload zone */}
|
| 601 |
<label
|
| 602 |
htmlFor="file-upload"
|
| 603 |
+
onDragEnter={(e) => {
|
| 604 |
+
e.preventDefault();
|
| 605 |
+
e.stopPropagation();
|
| 606 |
+
if (!uploading) setIsDragging(true);
|
| 607 |
+
}}
|
| 608 |
+
onDragOver={(e) => {
|
| 609 |
+
e.preventDefault();
|
| 610 |
+
e.stopPropagation();
|
| 611 |
+
}}
|
| 612 |
+
onDragLeave={(e) => {
|
| 613 |
+
e.preventDefault();
|
| 614 |
+
e.stopPropagation();
|
| 615 |
+
setIsDragging(false);
|
| 616 |
+
}}
|
| 617 |
+
onDrop={handleFileDrop}
|
| 618 |
+
className={`group flex flex-col items-center gap-2.5 border-2 border-dashed rounded-xl p-7 cursor-pointer transition-colors ${
|
| 619 |
+
isDragging
|
| 620 |
+
? "border-[#FF8F00] bg-orange-50/50"
|
| 621 |
+
: "border-slate-200 hover:border-[#FF8F00] hover:bg-orange-50/30"
|
| 622 |
+
}`}
|
| 623 |
>
|
| 624 |
<div className="w-10 h-10 rounded-xl bg-slate-100 group-hover:bg-orange-100 flex items-center justify-center transition-colors">
|
| 625 |
{uploading ? (
|
|
|
|
| 632 |
<p className="text-sm font-medium text-slate-700">
|
| 633 |
{uploading
|
| 634 |
? "Uploading..."
|
| 635 |
+
: isDragging
|
| 636 |
+
? "Drop to upload"
|
| 637 |
: <>Drop files, or <span className="text-[#FF8F00]">browse</span></>
|
| 638 |
}
|
| 639 |
</p>
|