mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-26 09:16:22 +02:00
- Updated the HITL edit panel to support multiple email inputs using a tag input component. - Modified the ExtraField type to include "emails" as a valid type. - Enhanced the Gmail draft creation process to utilize the new email input format for "To", "CC", and "BCC" fields.
176 lines
6.5 KiB
TypeScript
176 lines
6.5 KiB
TypeScript
"use client";
|
|
|
|
import { useAtom, useAtomValue, useSetAtom } from "jotai";
|
|
import { PanelRight, PanelRightClose } from "lucide-react";
|
|
import { startTransition, useEffect } from "react";
|
|
import { closeHitlEditPanelAtom, hitlEditPanelAtom } from "@/atoms/chat/hitl-edit-panel.atom";
|
|
import { closeReportPanelAtom, reportPanelAtom } from "@/atoms/chat/report-panel.atom";
|
|
import { documentsSidebarOpenAtom } from "@/atoms/documents/ui.atoms";
|
|
import { closeEditorPanelAtom, editorPanelAtom } from "@/atoms/editor/editor-panel.atom";
|
|
import { rightPanelCollapsedAtom, rightPanelTabAtom } from "@/atoms/layout/right-panel.atom";
|
|
import { EditorPanelContent } from "@/components/editor-panel/editor-panel";
|
|
import { HitlEditPanelContent } from "@/components/hitl-edit-panel/hitl-edit-panel";
|
|
import { ReportPanelContent } from "@/components/report-panel/report-panel";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
|
import { DocumentsSidebar } from "../sidebar";
|
|
|
|
interface RightPanelProps {
|
|
documentsPanel?: {
|
|
open: boolean;
|
|
onOpenChange: (open: boolean) => void;
|
|
};
|
|
}
|
|
|
|
function CollapseButton({ onClick }: { onClick: () => void }) {
|
|
return (
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<Button variant="ghost" size="icon" onClick={onClick} className="h-8 w-8 shrink-0">
|
|
<PanelRightClose className="h-4 w-4" />
|
|
<span className="sr-only">Collapse panel</span>
|
|
</Button>
|
|
</TooltipTrigger>
|
|
<TooltipContent side="left">Collapse panel</TooltipContent>
|
|
</Tooltip>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Absolutely positioned expand button — renders at top-right of the main
|
|
* container so it occupies the same screen position as the collapse button
|
|
* inside the Documents header.
|
|
*/
|
|
export function RightPanelExpandButton() {
|
|
const [collapsed, setCollapsed] = useAtom(rightPanelCollapsedAtom);
|
|
const documentsOpen = useAtomValue(documentsSidebarOpenAtom);
|
|
const reportState = useAtomValue(reportPanelAtom);
|
|
const editorState = useAtomValue(editorPanelAtom);
|
|
const hitlEditState = useAtomValue(hitlEditPanelAtom);
|
|
const reportOpen = reportState.isOpen && !!reportState.reportId;
|
|
const editorOpen = editorState.isOpen && !!editorState.documentId;
|
|
const hitlEditOpen = hitlEditState.isOpen && !!hitlEditState.onSave;
|
|
const hasContent = documentsOpen || reportOpen || editorOpen || hitlEditOpen;
|
|
|
|
if (!collapsed || !hasContent) return null;
|
|
|
|
return (
|
|
<div className="absolute top-4 right-4 z-20">
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
onClick={() => startTransition(() => setCollapsed(false))}
|
|
className="h-8 w-8 shrink-0"
|
|
>
|
|
<PanelRight className="h-4 w-4" />
|
|
<span className="sr-only">Expand panel</span>
|
|
</Button>
|
|
</TooltipTrigger>
|
|
<TooltipContent side="left">Expand panel</TooltipContent>
|
|
</Tooltip>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const PANEL_WIDTHS = { sources: 420, report: 640, editor: 640, "hitl-edit": 640 } as const;
|
|
|
|
export function RightPanel({ documentsPanel }: RightPanelProps) {
|
|
const [activeTab] = useAtom(rightPanelTabAtom);
|
|
const reportState = useAtomValue(reportPanelAtom);
|
|
const closeReport = useSetAtom(closeReportPanelAtom);
|
|
const editorState = useAtomValue(editorPanelAtom);
|
|
const closeEditor = useSetAtom(closeEditorPanelAtom);
|
|
const hitlEditState = useAtomValue(hitlEditPanelAtom);
|
|
const closeHitlEdit = useSetAtom(closeHitlEditPanelAtom);
|
|
const [collapsed, setCollapsed] = useAtom(rightPanelCollapsedAtom);
|
|
|
|
const documentsOpen = documentsPanel?.open ?? false;
|
|
const reportOpen = reportState.isOpen && !!reportState.reportId;
|
|
const editorOpen = editorState.isOpen && !!editorState.documentId;
|
|
const hitlEditOpen = hitlEditState.isOpen && !!hitlEditState.onSave;
|
|
|
|
useEffect(() => {
|
|
if (!reportOpen && !editorOpen && !hitlEditOpen) return;
|
|
const handleKeyDown = (e: KeyboardEvent) => {
|
|
if (e.key === "Escape") {
|
|
if (hitlEditOpen) closeHitlEdit();
|
|
else if (editorOpen) closeEditor();
|
|
else if (reportOpen) closeReport();
|
|
}
|
|
};
|
|
document.addEventListener("keydown", handleKeyDown);
|
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
}, [reportOpen, editorOpen, hitlEditOpen, closeReport, closeEditor, closeHitlEdit]);
|
|
|
|
const isVisible = (documentsOpen || reportOpen || editorOpen || hitlEditOpen) && !collapsed;
|
|
|
|
let effectiveTab = activeTab;
|
|
if (effectiveTab === "hitl-edit" && !hitlEditOpen) {
|
|
effectiveTab = editorOpen ? "editor" : reportOpen ? "report" : "sources";
|
|
} else if (effectiveTab === "editor" && !editorOpen) {
|
|
effectiveTab = reportOpen ? "report" : "sources";
|
|
} else if (effectiveTab === "report" && !reportOpen) {
|
|
effectiveTab = editorOpen ? "editor" : "sources";
|
|
} else if (effectiveTab === "sources" && !documentsOpen) {
|
|
effectiveTab = hitlEditOpen ? "hitl-edit" : editorOpen ? "editor" : reportOpen ? "report" : "sources";
|
|
}
|
|
|
|
const targetWidth = PANEL_WIDTHS[effectiveTab];
|
|
const collapseButton = <CollapseButton onClick={() => setCollapsed(true)} />;
|
|
|
|
if (!isVisible) return null;
|
|
|
|
return (
|
|
<aside
|
|
style={{ width: targetWidth }}
|
|
className="flex h-full shrink-0 flex-col rounded-xl border bg-sidebar text-sidebar-foreground overflow-hidden transition-[width] duration-200 ease-out"
|
|
>
|
|
<div className="relative flex-1 min-h-0 overflow-hidden">
|
|
{effectiveTab === "sources" && documentsOpen && documentsPanel && (
|
|
<div className="h-full">
|
|
<DocumentsSidebar
|
|
open={documentsPanel.open}
|
|
onOpenChange={documentsPanel.onOpenChange}
|
|
embedded
|
|
headerAction={collapseButton}
|
|
/>
|
|
</div>
|
|
)}
|
|
{effectiveTab === "report" && reportOpen && (
|
|
<div className="h-full flex flex-col">
|
|
<ReportPanelContent
|
|
reportId={reportState.reportId as number}
|
|
title={reportState.title || "Report"}
|
|
onClose={closeReport}
|
|
shareToken={reportState.shareToken}
|
|
/>
|
|
</div>
|
|
)}
|
|
{effectiveTab === "editor" && editorOpen && (
|
|
<div className="h-full flex flex-col">
|
|
<EditorPanelContent
|
|
documentId={editorState.documentId as number}
|
|
searchSpaceId={editorState.searchSpaceId as number}
|
|
title={editorState.title}
|
|
onClose={closeEditor}
|
|
/>
|
|
</div>
|
|
)}
|
|
{effectiveTab === "hitl-edit" && hitlEditOpen && hitlEditState.onSave && (
|
|
<div className="h-full flex flex-col">
|
|
<HitlEditPanelContent
|
|
title={hitlEditState.title}
|
|
content={hitlEditState.content}
|
|
toolName={hitlEditState.toolName}
|
|
extraFields={hitlEditState.extraFields}
|
|
onSave={hitlEditState.onSave}
|
|
onClose={closeHitlEdit}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</aside>
|
|
);
|
|
}
|