diff --git a/surfsense_web/components/editor-panel/editor-panel.tsx b/surfsense_web/components/editor-panel/editor-panel.tsx index 0170d13da..50ee158c4 100644 --- a/surfsense_web/components/editor-panel/editor-panel.tsx +++ b/surfsense_web/components/editor-panel/editor-panel.tsx @@ -7,7 +7,6 @@ import { Download, FileQuestionMark, FileText, - Loader2, Pencil, RefreshCw, XIcon, @@ -22,6 +21,7 @@ import { MarkdownViewer } from "@/components/markdown-viewer"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { Button } from "@/components/ui/button"; import { Drawer, DrawerContent, DrawerHandle, DrawerTitle } from "@/components/ui/drawer"; +import { Spinner } from "@/components/ui/spinner"; import { useMediaQuery } from "@/hooks/use-media-query"; import { useElectronAPI } from "@/hooks/use-platform"; import { authenticatedFetch, getBearerToken, redirectToLogin } from "@/lib/auth-utils"; @@ -346,8 +346,8 @@ export function EditorPanelContent({ }} disabled={saving || !hasUnsavedChanges} > - Save - {saving && } + Save + {saving && } > ) : ( @@ -416,8 +416,8 @@ export function EditorPanelContent({ }} disabled={saving || !hasUnsavedChanges} > - Save - {saving && } + Save + {saving && } > ) : ( @@ -534,7 +534,7 @@ export function EditorPanelContent({ }} > {downloading ? ( - + ) : ( )} diff --git a/surfsense_web/components/report-panel/report-panel.tsx b/surfsense_web/components/report-panel/report-panel.tsx index 591155757..709b10467 100644 --- a/surfsense_web/components/report-panel/report-panel.tsx +++ b/surfsense_web/components/report-panel/report-panel.tsx @@ -1,7 +1,7 @@ "use client"; import { useAtomValue, useSetAtom } from "jotai"; -import { ChevronDownIcon, XIcon } from "lucide-react"; +import { ChevronDownIcon, Pencil, XIcon } from "lucide-react"; import dynamic from "next/dynamic"; import { useCallback, useEffect, useRef, useState } from "react"; import { toast } from "sonner"; @@ -125,6 +125,7 @@ export function ReportPanelContent({ // Editor state — tracks the latest markdown from the Plate editor const [editedMarkdown, setEditedMarkdown] = useState(null); + const [isEditing, setIsEditing] = useState(false); // Read-only when public (shareToken) OR shared (SEARCH_SPACE visibility) const currentThreadState = useAtomValue(currentThreadAtom); @@ -188,6 +189,7 @@ export function ReportPanelContent({ // Reset edited markdown when switching versions or reports useEffect(() => { setEditedMarkdown(null); + setIsEditing(false); }, [activeReportId]); // Copy markdown content (uses latest editor content) @@ -257,7 +259,7 @@ export function ReportPanelContent({ // Save edited report content const handleSave = useCallback(async () => { - if (!currentMarkdown || !activeReportId) return; + if (!currentMarkdown || !activeReportId) return false; setSaving(true); try { const response = await authenticatedFetch( @@ -278,9 +280,11 @@ export function ReportPanelContent({ setReportContent((prev) => (prev ? { ...prev, content: currentMarkdown } : prev)); setEditedMarkdown(null); toast.success("Report saved successfully"); + return true; } catch (err) { console.error("Error saving report:", err); toast.error(err instanceof Error ? err.message : "Failed to save report"); + return false; } finally { setSaving(false); } @@ -289,6 +293,14 @@ export function ReportPanelContent({ const activeVersionIndex = versions.findIndex((v) => v.id === activeReportId); const isPublic = !!shareToken; const btnBg = isPublic ? "bg-main-panel" : "bg-sidebar"; + const isResume = reportContent?.content_type === "typst"; + const showReportEditingTier = !isResume; + const hasUnsavedChanges = editedMarkdown !== null; + + const handleCancelEditing = useCallback(() => { + setEditedMarkdown(null); + setIsEditing(false); + }, []); return ( <> @@ -383,6 +395,58 @@ export function ReportPanelContent({ )} + {showReportEditingTier && ( + + + + {reportContent?.title || title} + + + + {!isReadOnly && + (isEditing ? ( + <> + + Cancel + + { + const saveSucceeded = await handleSave(); + if (saveSucceeded) setIsEditing(false); + }} + disabled={saving || !hasUnsavedChanges} + > + Save + {saving && } + + > + ) : ( + { + setEditedMarkdown(null); + setIsEditing(true); + }} + > + + Edit report + + ))} + + + )} + {/* Report content — skeleton/error/viewer/editor shown only in this area */} {isLoading ? ( @@ -406,15 +470,15 @@ export function ReportPanelContent({ ) : ( )
+ {reportContent?.title || title} +