diff --git a/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/components/DocumentsTableShell.tsx b/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/components/DocumentsTableShell.tsx index 296308a17..218b85da2 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/components/DocumentsTableShell.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/components/DocumentsTableShell.tsx @@ -54,7 +54,7 @@ import { import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; import { documentsApiService } from "@/lib/apis/documents-api.service"; import { getDocumentTypeIcon, getDocumentTypeLabel } from "./DocumentTypeIcon"; -import type { ColumnVisibility, Document, DocumentStatus } from "./types"; +import type { Document, DocumentStatus } from "./types"; const EDITABLE_DOCUMENT_TYPES = ["FILE", "NOTE"] as const; const NON_DELETABLE_DOCUMENT_TYPES = ["SURFSENSE_DOCS"] as const; @@ -288,7 +288,6 @@ export function DocumentsTableShell({ error, selectedIds, setSelectedIds, - columnVisibility: _columnVisibility, sortKey, sortDesc, onSortChange, @@ -304,7 +303,6 @@ export function DocumentsTableShell({ error: boolean; selectedIds: Set; setSelectedIds: (update: Set) => void; - columnVisibility: ColumnVisibility; sortKey: SortKey; sortDesc: boolean; onSortChange: (key: SortKey) => void; @@ -447,122 +445,122 @@ export function DocumentsTableShell({ animate={{ opacity: 1, y: 0 }} transition={{ type: "spring", stiffness: 300, damping: 30, delay: 0.2 }} > - {/* Desktop Table View */} -
- - - - -
- toggleAll(!!v)} - aria-label="Select all" - className="border-foreground data-[state=checked]:bg-primary data-[state=checked]:border-primary" - /> -
-
- - } - > - Document - - - - - - - - - - Status - - -
-
-
- {loading ? ( -
- - - {[65, 80, 45, 72, 55, 88, 40, 60, 50, 75].map((widthPercent) => ( - +
+ + + +
+ toggleAll(!!v)} + aria-label="Select all" + className="border-foreground data-[state=checked]:bg-primary data-[state=checked]:border-primary" + /> +
+
+ + } > - -
- -
-
- - - - - - - - - -
- ))} - -
-
- ) : error ? ( -
-
- -

{t("error_loading")}

+ Document + + + + + + + + + + Status + + + + + + {loading ? ( +
+ + + {[65, 80, 45, 72, 55, 88, 40, 60, 50, 75].map((widthPercent) => ( + + +
+ +
+
+ + + + + + + + + +
+ ))} +
+
-
- ) : sorted.length === 0 ? ( -
- -
- + ) : error ? ( +
+
+ +

{t("error_loading")}

-
-

{t("no_documents")}

-

- Get started by uploading your first document. -

-
- - -
- ) : ( -
- - - {sorted.map((doc, index) => { - const isSelected = selectedIds.has(doc.id); - const canSelect = isSelectable(doc); - return ( - - + ) : sorted.length === 0 ? ( +
+ +
+ +
+
+

{t("no_documents")}

+

+ Get started by uploading your first document. +

+
+ +
+
+ ) : ( +
+
+ + {sorted.map((doc, index) => { + const isSelected = selectedIds.has(doc.id); + const canSelect = isSelectable(doc); + return ( + + - - - ); - })} - -
+ + + ); + })} + + + {hasMore && ( +
+ )} +
+ )} +
+ + {/* Mobile Card View */} + {loading ? ( +
+ {[70, 85, 55, 78, 62, 90].map((widthPercent) => ( +
+
+ +
+ +
+
+ + +
+
+
+ ))} +
+ ) : error ? ( +
+
+ +

{t("error_loading")}

+
+
+ ) : sorted.length === 0 ? ( +
+ +
+ +
+
+

{t("no_documents")}

+

+ Get started by uploading your first document. +

+
+ +
+
+ ) : ( +
+ {sorted.map((doc, index) => { + const isSelected = selectedIds.has(doc.id); + const canSelect = isSelectable(doc); + return ( + + +
+ + canSelect && toggleOne(doc.id, !!v) + } + disabled={!canSelect} + aria-label={ + canSelect + ? "Select row" + : "Cannot select while processing" + } + className={`border-foreground data-[state=checked]:bg-primary data-[state=checked]:border-primary shrink-0 ${!canSelect ? "opacity-40 cursor-not-allowed" : ""}`} + /> +
+ +
+
+ + + + {getDocumentTypeIcon( + doc.document_type, + "h-4 w-4" + )} + + + + {getDocumentTypeLabel(doc.document_type)} + + + +
+
+
+
+ ); + })} {hasMore && ( -
+
)}
)} -
- - {/* Mobile Card View */} - {loading ? ( -
- {[70, 85, 55, 78, 62, 90].map((widthPercent) => ( -
-
- -
- -
-
- - -
-
-
- ))} -
- ) : !error && sorted.length > 0 && ( -
- {sorted.map((doc, index) => { - const isSelected = selectedIds.has(doc.id); - const canSelect = isSelectable(doc); - return ( - - -
- - canSelect && toggleOne(doc.id, !!v) - } - disabled={!canSelect} - aria-label={ - canSelect - ? "Select row" - : "Cannot select while processing" - } - className={`border-foreground data-[state=checked]:bg-primary data-[state=checked]:border-primary shrink-0 ${!canSelect ? "opacity-40 cursor-not-allowed" : ""}`} - /> -
- -
-
- - - - {getDocumentTypeIcon( - doc.document_type, - "h-4 w-4" - )} - - - - {getDocumentTypeLabel(doc.document_type)} - - - -
-
-
-
- ); - })} - {hasMore && ( -
- )} -
- )} {/* Document Content Viewer */} !open && handleCloseViewer()}> diff --git a/surfsense_web/components/layout/ui/sidebar/DocumentsSidebar.tsx b/surfsense_web/components/layout/ui/sidebar/DocumentsSidebar.tsx index 616932475..c397c91d2 100644 --- a/surfsense_web/components/layout/ui/sidebar/DocumentsSidebar.tsx +++ b/surfsense_web/components/layout/ui/sidebar/DocumentsSidebar.tsx @@ -19,7 +19,6 @@ import { DocumentsTableShell, type SortKey, } from "@/app/dashboard/[search_space_id]/documents/(manage)/components/DocumentsTableShell"; -import type { ColumnVisibility } from "@/app/dashboard/[search_space_id]/documents/(manage)/components/types"; import { SidebarSlideOutPanel } from "./SidebarSlideOutPanel"; const SEARCH_INITIAL_SIZE = 20; @@ -49,12 +48,6 @@ export function DocumentsSidebar({ open, onOpenChange }: DocumentsSidebarProps) const [search, setSearch] = useState(""); const debouncedSearch = useDebounced(search, 250); const [activeTypes, setActiveTypes] = useState([]); - const [columnVisibility, setColumnVisibility] = useState({ - document_type: true, - created_by: false, - created_at: true, - status: true, - }); const [sortKey, setSortKey] = useState("created_at"); const [sortDesc, setSortDesc] = useState(true); const [selectedIds, setSelectedIds] = useState>(new Set()); @@ -288,13 +281,6 @@ export function DocumentsSidebar({ open, onOpenChange }: DocumentsSidebarProps) }); }, []); - useEffect(() => { - if (!open) return; - const panelWidth = isMobile ? window.innerWidth : 720; - const isNarrow = panelWidth < 600; - setColumnVisibility((prev) => ({ ...prev, created_by: !isNarrow, created_at: !isNarrow })); - }, [open, isMobile]); - useEffect(() => { const handleEscape = (e: KeyboardEvent) => { if (e.key === "Escape" && open) { @@ -345,7 +331,6 @@ export function DocumentsSidebar({ open, onOpenChange }: DocumentsSidebarProps) error={!!error} selectedIds={selectedIds} setSelectedIds={setSelectedIds} - columnVisibility={columnVisibility} sortKey={sortKey} sortDesc={sortDesc} onSortChange={handleSortChange} diff --git a/surfsense_web/hooks/use-documents.ts b/surfsense_web/hooks/use-documents.ts index c2ce390d7..a8e38a62a 100644 --- a/surfsense_web/hooks/use-documents.ts +++ b/surfsense_web/hooks/use-documents.ts @@ -77,6 +77,7 @@ export function useDocuments( const apiLoadedCountRef = useRef(0); const initialLoadDoneRef = useRef(false); + const prevParamsRef = useRef<{ sortBy: string; sortOrder: string; typeFilterKey: string } | null>(null); // Snapshot of all doc IDs from Electric's first callback after initial load. // Anything appearing in subsequent callbacks NOT in this set is genuinely new. const electricBaselineIdsRef = useRef | null>(null); @@ -156,8 +157,15 @@ export function useDocuments( let cancelled = false; - const isRefresh = initialLoadDoneRef.current; - if (!isRefresh) { + const prev = prevParamsRef.current; + const isSortOnlyChange = + initialLoadDoneRef.current && + prev !== null && + prev.typeFilterKey === typeFilterKey && + (prev.sortBy !== sortBy || prev.sortOrder !== sortOrder); + prevParamsRef.current = { sortBy, sortOrder, typeFilterKey }; + + if (!isSortOnlyChange) { setLoading(true); setDocuments([]); setTotal(0);