mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-09 15:52:40 +02:00
feat: enhance metadata viewing in DocumentsTableShell with on-demand fetching and loading state
This commit is contained in:
parent
c19aa5fa99
commit
c706b5f417
2 changed files with 51 additions and 8 deletions
|
|
@ -158,7 +158,10 @@ export function DocumentsTableShell({
|
||||||
const { openDialog } = useDocumentUploadDialog();
|
const { openDialog } = useDocumentUploadDialog();
|
||||||
|
|
||||||
// State for metadata viewer (opened via Ctrl/Cmd+Click)
|
// State for metadata viewer (opened via Ctrl/Cmd+Click)
|
||||||
|
// Real-time documents don't sync metadata - we fetch on-demand when viewing
|
||||||
const [metadataDoc, setMetadataDoc] = useState<Document | null>(null);
|
const [metadataDoc, setMetadataDoc] = useState<Document | null>(null);
|
||||||
|
const [metadataContent, setMetadataContent] = useState<any>(null);
|
||||||
|
const [metadataLoading, setMetadataLoading] = useState(false);
|
||||||
|
|
||||||
// State for lazy document content viewer
|
// State for lazy document content viewer
|
||||||
// Real-time documents don't sync content - we fetch on-demand when viewing
|
// Real-time documents don't sync content - we fetch on-demand when viewing
|
||||||
|
|
@ -166,6 +169,36 @@ export function DocumentsTableShell({
|
||||||
const [viewingContent, setViewingContent] = useState<string>("");
|
const [viewingContent, setViewingContent] = useState<string>("");
|
||||||
const [viewingLoading, setViewingLoading] = useState(false);
|
const [viewingLoading, setViewingLoading] = useState(false);
|
||||||
|
|
||||||
|
// Fetch document metadata on-demand when metadata viewer is opened
|
||||||
|
const handleViewMetadata = useCallback(async (doc: Document) => {
|
||||||
|
setMetadataDoc(doc);
|
||||||
|
|
||||||
|
// If metadata is already available (from API/search), use it directly
|
||||||
|
if (doc.document_metadata) {
|
||||||
|
setMetadataContent(doc.document_metadata);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, fetch from API (lazy loading for real-time synced documents)
|
||||||
|
setMetadataLoading(true);
|
||||||
|
try {
|
||||||
|
const fullDoc = await documentsApiService.getDocument({ id: doc.id });
|
||||||
|
setMetadataContent(fullDoc.document_metadata);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("[DocumentsTableShell] Failed to fetch document metadata:", err);
|
||||||
|
setMetadataContent(null);
|
||||||
|
} finally {
|
||||||
|
setMetadataLoading(false);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Close metadata viewer
|
||||||
|
const handleCloseMetadata = useCallback(() => {
|
||||||
|
setMetadataDoc(null);
|
||||||
|
setMetadataContent(null);
|
||||||
|
setMetadataLoading(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Fetch document content on-demand when viewer is opened
|
// Fetch document content on-demand when viewer is opened
|
||||||
const handleViewDocument = useCallback(async (doc: Document) => {
|
const handleViewDocument = useCallback(async (doc: Document) => {
|
||||||
setViewingDoc(doc);
|
setViewingDoc(doc);
|
||||||
|
|
@ -474,7 +507,7 @@ export function DocumentsTableShell({
|
||||||
if (e.ctrlKey || e.metaKey) {
|
if (e.ctrlKey || e.metaKey) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setMetadataDoc(doc);
|
handleViewMetadata(doc);
|
||||||
} else {
|
} else {
|
||||||
// Normal click opens document viewer (lazy loads content)
|
// Normal click opens document viewer (lazy loads content)
|
||||||
handleViewDocument(doc);
|
handleViewDocument(doc);
|
||||||
|
|
@ -484,7 +517,7 @@ export function DocumentsTableShell({
|
||||||
// Ctrl/Cmd + Enter opens metadata
|
// Ctrl/Cmd + Enter opens metadata
|
||||||
if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
|
if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setMetadataDoc(doc);
|
handleViewMetadata(doc);
|
||||||
} else if (e.key === "Enter") {
|
} else if (e.key === "Enter") {
|
||||||
// Enter opens document viewer
|
// Enter opens document viewer
|
||||||
handleViewDocument(doc);
|
handleViewDocument(doc);
|
||||||
|
|
@ -553,7 +586,7 @@ export function DocumentsTableShell({
|
||||||
if (e.ctrlKey || e.metaKey) {
|
if (e.ctrlKey || e.metaKey) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setMetadataDoc(doc);
|
handleViewMetadata(doc);
|
||||||
} else {
|
} else {
|
||||||
// Normal click opens document viewer (lazy loads content)
|
// Normal click opens document viewer (lazy loads content)
|
||||||
handleViewDocument(doc);
|
handleViewDocument(doc);
|
||||||
|
|
@ -563,7 +596,7 @@ export function DocumentsTableShell({
|
||||||
// Ctrl/Cmd + Enter opens metadata
|
// Ctrl/Cmd + Enter opens metadata
|
||||||
if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
|
if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setMetadataDoc(doc);
|
handleViewMetadata(doc);
|
||||||
} else if (e.key === "Enter") {
|
} else if (e.key === "Enter") {
|
||||||
// Enter opens document viewer
|
// Enter opens document viewer
|
||||||
handleViewDocument(doc);
|
handleViewDocument(doc);
|
||||||
|
|
@ -602,12 +635,14 @@ export function DocumentsTableShell({
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Metadata Viewer - opened via Ctrl/Cmd+Click on document title */}
|
{/* Metadata Viewer - opened via Ctrl/Cmd+Click on document title */}
|
||||||
|
{/* Lazy loads metadata from API for real-time synced documents */}
|
||||||
<JsonMetadataViewer
|
<JsonMetadataViewer
|
||||||
title={metadataDoc?.title ?? ""}
|
title={metadataDoc?.title ?? ""}
|
||||||
metadata={metadataDoc?.document_metadata}
|
metadata={metadataContent}
|
||||||
|
loading={metadataLoading}
|
||||||
open={!!metadataDoc}
|
open={!!metadataDoc}
|
||||||
onOpenChange={(open) => {
|
onOpenChange={(open) => {
|
||||||
if (!open) setMetadataDoc(null);
|
if (!open) handleCloseMetadata();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { FileJson } from "lucide-react";
|
import { FileJson, Loader2 } from "lucide-react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { defaultStyles, JsonView } from "react-json-view-lite";
|
import { defaultStyles, JsonView } from "react-json-view-lite";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
@ -17,6 +17,7 @@ interface JsonMetadataViewerProps {
|
||||||
trigger?: React.ReactNode;
|
trigger?: React.ReactNode;
|
||||||
open?: boolean;
|
open?: boolean;
|
||||||
onOpenChange?: (open: boolean) => void;
|
onOpenChange?: (open: boolean) => void;
|
||||||
|
loading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function JsonMetadataViewer({
|
export function JsonMetadataViewer({
|
||||||
|
|
@ -25,6 +26,7 @@ export function JsonMetadataViewer({
|
||||||
trigger,
|
trigger,
|
||||||
open,
|
open,
|
||||||
onOpenChange,
|
onOpenChange,
|
||||||
|
loading,
|
||||||
}: JsonMetadataViewerProps) {
|
}: JsonMetadataViewerProps) {
|
||||||
// Ensure metadata is a valid object
|
// Ensure metadata is a valid object
|
||||||
const jsonData = React.useMemo(() => {
|
const jsonData = React.useMemo(() => {
|
||||||
|
|
@ -54,7 +56,13 @@ export function JsonMetadataViewer({
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="mt-2 sm:mt-4 p-2 sm:p-4 bg-muted/30 rounded-md text-xs sm:text-sm">
|
<div className="mt-2 sm:mt-4 p-2 sm:p-4 bg-muted/30 rounded-md text-xs sm:text-sm">
|
||||||
<JsonView data={jsonData} style={defaultStyles} />
|
{loading ? (
|
||||||
|
<div className="flex items-center justify-center py-12">
|
||||||
|
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<JsonView data={jsonData} style={defaultStyles} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue