diff --git a/surfsense_backend/app/routes/editor_routes.py b/surfsense_backend/app/routes/editor_routes.py index 606a52ec5..1baf52e85 100644 --- a/surfsense_backend/app/routes/editor_routes.py +++ b/surfsense_backend/app/routes/editor_routes.py @@ -172,6 +172,10 @@ async def save_document( blocknote_document = data.get("blocknote_document") if not blocknote_document: raise HTTPException(status_code=400, detail="blocknote_document is required") + + # Add type validation + if not isinstance(blocknote_document, list): + raise HTTPException(status_code=400, detail="blocknote_document must be a list") # For NOTE type documents, extract title from first block (heading) if ( diff --git a/surfsense_web/app/dashboard/page.tsx b/surfsense_web/app/dashboard/page.tsx index b1525a9db..b747f4c21 100644 --- a/surfsense_web/app/dashboard/page.tsx +++ b/surfsense_web/app/dashboard/page.tsx @@ -156,7 +156,12 @@ const DashboardPage = () => { }, }; - const { data: searchSpaces = [], isLoading: loading, error, refetch: refreshSearchSpaces } = useAtomValue(searchSpacesAtom); + const { + data: searchSpaces = [], + isLoading: loading, + error, + refetch: refreshSearchSpaces, + } = useAtomValue(searchSpacesAtom); const { mutateAsync: deleteSearchSpace } = useAtomValue(deleteSearchSpaceMutationAtom); // Fetch user details @@ -172,7 +177,7 @@ const DashboardPage = () => { }; if (loading) return ; - if (error) return ; + if (error) return ; const handleDeleteSearchSpace = async (id: number) => { await deleteSearchSpace({ id }); diff --git a/surfsense_web/components/BlockNoteEditor.tsx b/surfsense_web/components/BlockNoteEditor.tsx index 04a54fd3e..dc033bc5a 100644 --- a/surfsense_web/components/BlockNoteEditor.tsx +++ b/surfsense_web/components/BlockNoteEditor.tsx @@ -66,7 +66,11 @@ function ensureTitleBlock(content: any[] | undefined): any[] { return content; } -export default function BlockNoteEditor({ initialContent, onChange, useTitleBlock = false }: BlockNoteEditorProps) { +export default function BlockNoteEditor({ + initialContent, + onChange, + useTitleBlock = false, +}: BlockNoteEditorProps) { const { resolvedTheme } = useTheme(); // Track the initial content to prevent re-initialization diff --git a/surfsense_web/components/sidebar/AppSidebarProvider.tsx b/surfsense_web/components/sidebar/AppSidebarProvider.tsx index ce9911641..043f54840 100644 --- a/surfsense_web/components/sidebar/AppSidebarProvider.tsx +++ b/surfsense_web/components/sidebar/AppSidebarProvider.tsx @@ -187,8 +187,12 @@ export function AppSidebarProvider({ // Sort notes by updated_at (most recent first), fallback to created_at if updated_at is null const sortedNotes = [...notesData.items].sort((a, b) => { - const dateA = a.updated_at ? new Date(a.updated_at).getTime() : new Date(a.created_at).getTime(); - const dateB = b.updated_at ? new Date(b.updated_at).getTime() : new Date(b.created_at).getTime(); + const dateA = a.updated_at + ? new Date(a.updated_at).getTime() + : new Date(a.created_at).getTime(); + const dateB = b.updated_at + ? new Date(b.updated_at).getTime() + : new Date(b.created_at).getTime(); return dateB - dateA; // Descending order (most recent first) }); diff --git a/surfsense_web/components/sidebar/all-notes-sidebar.tsx b/surfsense_web/components/sidebar/all-notes-sidebar.tsx index a0e8f0072..f2065edef 100644 --- a/surfsense_web/components/sidebar/all-notes-sidebar.tsx +++ b/surfsense_web/components/sidebar/all-notes-sidebar.tsx @@ -1,13 +1,6 @@ "use client"; -import { - FileText, - type LucideIcon, - MoreHorizontal, - Plus, - RefreshCw, - Trash2, -} from "lucide-react"; +import { FileText, type LucideIcon, MoreHorizontal, Plus, RefreshCw, Trash2 } from "lucide-react"; import { useRouter } from "next/navigation"; import { useTranslations } from "next-intl"; import { useCallback, useMemo, useState } from "react"; @@ -86,7 +79,7 @@ export function AllNotesSidebar({ const sidebarElement = document.querySelector( '[data-slot="sidebar"][data-sidebar="sidebar"]' ) as HTMLElement; - + if (sidebarElement) { const rect = sidebarElement.getBoundingClientRect(); // Set the left position to be the right edge of the sidebar @@ -116,7 +109,7 @@ export function AllNotesSidebar({ // Update on window resize and scroll window.addEventListener("resize", updatePosition); window.addEventListener("scroll", updatePosition, true); - + // Use MutationObserver to watch for sidebar state changes const observer = new MutationObserver(updatePosition); const sidebarWrapper = document.querySelector('[data-slot="sidebar-wrapper"]'); @@ -234,7 +227,6 @@ export function AllNotesSidebar({ }} disabled={isDeletingNote} className={cn("group/item relative", isDeletingNote && "opacity-50")} - size="sm" > {note.name} @@ -270,9 +262,7 @@ export function AllNotesSidebar({ className={isDeleteAction ? "text-destructive" : ""} > - - {isDeletingNote && isDeleteAction ? "Deleting..." : action.name} - + {isDeletingNote && isDeleteAction ? "Deleting..." : action.name} ); })} @@ -290,7 +280,7 @@ export function AllNotesSidebar({ ref={sidebarRef} aria-label="All notes sidebar" className={cn( - "fixed top-16 bottom-0 z-[100] w-80 bg-sidebar text-sidebar-foreground shadow-xl", + "fixed top-0 bottom-0 z-[100] w-80 bg-sidebar text-sidebar-foreground shadow-xl", "transition-all duration-300 ease-out", !open && "pointer-events-none" )} @@ -319,84 +309,83 @@ export function AllNotesSidebar({ } }} > -
- {/* Header */} -
-

{t("all_notes") || "All Notes"}

-
- - {/* Content */} - -
- - - {isLoadingNotes ? ( - - - - {t("loading") || "Loading..."} - - - - ) : notesError ? ( - - - - {t("error_loading_notes") || "Error loading notes"} - - - - ) : allNotes.length > 0 ? ( - - {allNotes.map((note) => ( - - ))} - - ) : ( - - {onAddNote ? ( - { - onAddNote(); - onOpenChange(false); - }} - className="text-muted-foreground hover:text-sidebar-foreground text-xs" - size="sm" - > - - {t("create_new_note") || "Create a new note"} - - ) : ( - - - {t("no_notes") || "No notes yet"} - - )} - - )} - - -
-
- - {/* Footer with Add Note button */} - {onAddNote && ( -
- -
- )} +
+ {/* Header */} +
+

{t("all_notes") || "All Notes"}

- + + {/* Content */} + +
+ + + {isLoadingNotes ? ( + + + + {t("loading") || "Loading..."} + + + + ) : notesError ? ( + + + + {t("error_loading_notes") || "Error loading notes"} + + + + ) : allNotes.length > 0 ? ( + + {allNotes.map((note) => ( + + ))} + + ) : ( + + {onAddNote ? ( + { + onAddNote(); + onOpenChange(false); + }} + className="text-muted-foreground hover:text-sidebar-foreground text-xs" + > + + {t("create_new_note") || "Create a new note"} + + ) : ( + + + {t("no_notes") || "No notes yet"} + + )} + + )} + + +
+
+ + {/* Footer with Add Note button */} + {onAddNote && ( +
+ +
+ )} +
+ ); // Render sidebar via portal to avoid stacking context issues @@ -406,4 +395,3 @@ export function AllNotesSidebar({ return createPortal(sidebarContent, document.body); } - diff --git a/surfsense_web/components/sidebar/nav-notes.tsx b/surfsense_web/components/sidebar/nav-notes.tsx index 29a078357..60e5d9c12 100644 --- a/surfsense_web/components/sidebar/nav-notes.tsx +++ b/surfsense_web/components/sidebar/nav-notes.tsx @@ -15,11 +15,7 @@ import { import { useRouter } from "next/navigation"; import { useTranslations } from "next-intl"; import { useCallback, useState, useRef } from "react"; -import { - Collapsible, - CollapsibleContent, - CollapsibleTrigger, -} from "@/components/ui/collapsible"; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; import { DropdownMenu, DropdownMenuContent, @@ -100,7 +96,6 @@ export function NavNotes({ notes, onAddNote, defaultOpen = true, searchSpaceId } onClick={() => router.push(note.url)} disabled={isDeletingNote} className={`group/item relative ${isDeletingNote ? "opacity-50" : ""}`} - size="sm" > {note.name} @@ -164,9 +159,7 @@ export function NavNotes({ notes, onAddNote, defaultOpen = true, searchSpaceId } isOpen ? "rotate-90" : "" }`} /> - - {t("notes") || "Notes"} - + {t("notes") || "Notes"}
@@ -223,13 +216,12 @@ export function NavNotes({ notes, onAddNote, defaultOpen = true, searchSpaceId } {t("create_new_note") || "Create a new note"} ) : ( - + {t("no_notes") || "No notes yet"} @@ -252,4 +244,3 @@ export function NavNotes({ notes, onAddNote, defaultOpen = true, searchSpaceId } ); } -