feat: update knowledge and agent UI
This commit is contained in:
1 parent
bebe4feccf
commit
7efd811e75
27 files changed
+2949
-782
No files matched your search
@@ -17,13 +17,11 @@ import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { EmptyDocumentState } from "@/components/wiki/EmptyDocumentState";
|
||||
import { KnowledgeSidebar } from "@/components/wiki/KnowledgeSidebar";
|
||||
import { TocPanel } from "@/components/wiki/TocPanel";
|
||||
import { WikiContent } from "@/components/wiki/WikiContent";
|
||||
import { WikiHeader } from "@/components/wiki/WikiHeader";
|
||||
import {
|
||||
buildKnowledgeTree,
|
||||
downloadMarkdown,
|
||||
extractToc,
|
||||
findAncestorFolderIds,
|
||||
} from "@/components/wiki/wikiUtils";
|
||||
import { ModelNameSelect } from "@/components/workspace/model-name-select";
|
||||
@@ -41,6 +39,16 @@ import MarkdownRenderer, {
|
||||
type WikiLinkTarget,
|
||||
} from "@/strategy-components/MarkdownRenderer";
|
||||
|
||||
const SIDEBAR_COLLAPSED_KEY = "wiki.sidebar.collapsed";
|
||||
|
||||
function readSidebarCollapsed(): boolean {
|
||||
try {
|
||||
return window.localStorage.getItem(SIDEBAR_COLLAPSED_KEY) === "1";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function useDebounced<T>(value: T, delay = 350): T {
|
||||
const [debounced, setDebounced] = useState(value);
|
||||
useEffect(() => {
|
||||
@@ -461,6 +469,7 @@ export default function KnowledgeBasePage() {
|
||||
const [expandedIds, setExpandedIds] = useState<Set<string>>(new Set());
|
||||
const treeInitializedRef = useRef(false);
|
||||
const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
|
||||
const [sidebarCollapsed, setSidebarCollapsed] = useState(readSidebarCollapsed);
|
||||
|
||||
// --- dialogs ---
|
||||
const [createOpen, setCreateOpen] = useState(false);
|
||||
@@ -469,9 +478,6 @@ export default function KnowledgeBasePage() {
|
||||
const [dedupOpen, setDedupOpen] = useState(false);
|
||||
const [vaultPath, setVaultPath] = useState<string | null>(null);
|
||||
|
||||
// --- reading state ---
|
||||
const [activeHeadingId, setActiveHeadingId] = useState<string | null>(null);
|
||||
|
||||
const params = useMemo(
|
||||
() => ({
|
||||
keyword: debouncedKeyword || undefined,
|
||||
@@ -488,10 +494,6 @@ export default function KnowledgeBasePage() {
|
||||
|
||||
const { data: note, isLoading: noteLoading } = useKnowledgeNote(noteId);
|
||||
const { data: wikiLinks } = useNoteWikilinks(noteId);
|
||||
const tocItems = useMemo(
|
||||
() => (note ? extractToc(note.content_md) : []),
|
||||
[note],
|
||||
);
|
||||
|
||||
// First load: expand the root-level folders so the tree reads as a directory.
|
||||
useEffect(() => {
|
||||
@@ -529,11 +531,16 @@ export default function KnowledgeBasePage() {
|
||||
navigate(`/page/workspace/knowledge/${item.id}`);
|
||||
};
|
||||
|
||||
const handleTocClick = (id: string) => {
|
||||
setActiveHeadingId(id);
|
||||
document
|
||||
.getElementById(id)
|
||||
?.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
const handleToggleSidebarCollapse = () => {
|
||||
setSidebarCollapsed((prev) => {
|
||||
const next = !prev;
|
||||
try {
|
||||
window.localStorage.setItem(SIDEBAR_COLLAPSED_KEY, next ? "1" : "0");
|
||||
} catch {
|
||||
// localStorage unavailable (private mode) — state stays session-only.
|
||||
}
|
||||
return next;
|
||||
});
|
||||
};
|
||||
|
||||
const handleWikiLink = (link: WikiLinkTarget) => {
|
||||
@@ -555,7 +562,14 @@ export default function KnowledgeBasePage() {
|
||||
onCreate={() => setCreateOpen(true)}
|
||||
/>
|
||||
|
||||
<div className="grid min-h-0 flex-1 grid-cols-1 md:grid-cols-[300px_minmax(0,1fr)] xl:grid-cols-[300px_minmax(0,1fr)_280px]">
|
||||
<div
|
||||
className={cn(
|
||||
"grid min-h-0 flex-1 grid-cols-1",
|
||||
sidebarCollapsed && !mobileSidebarOpen
|
||||
? "md:grid-cols-[44px_minmax(0,1fr)]"
|
||||
: "md:grid-cols-[288px_minmax(0,1fr)]",
|
||||
)}
|
||||
>
|
||||
{mobileSidebarOpen ? (
|
||||
<div
|
||||
className="fixed inset-0 z-40 bg-black/30 md:hidden"
|
||||
@@ -578,6 +592,8 @@ export default function KnowledgeBasePage() {
|
||||
onExportNote={downloadMarkdown}
|
||||
total={data?.total ?? 0}
|
||||
isLoading={isLoading}
|
||||
collapsed={sidebarCollapsed && !mobileSidebarOpen}
|
||||
onToggleCollapse={handleToggleSidebarCollapse}
|
||||
className={cn(
|
||||
"max-md:fixed max-md:inset-y-0 max-md:left-0 max-md:z-50 max-md:w-[300px] max-md:shadow-xl max-md:transition-transform max-md:duration-200",
|
||||
mobileSidebarOpen ? "max-md:translate-x-0" : "max-md:-translate-x-full",
|
||||
@@ -599,19 +615,10 @@ export default function KnowledgeBasePage() {
|
||||
) : (
|
||||
<WikiContent
|
||||
note={note}
|
||||
toc={tocItems}
|
||||
wikiLinks={wikiLinks}
|
||||
onWikiLinkClick={handleWikiLink}
|
||||
onActiveHeadingChange={setActiveHeadingId}
|
||||
/>
|
||||
)}
|
||||
|
||||
<TocPanel
|
||||
items={tocItems}
|
||||
activeId={activeHeadingId}
|
||||
onItemClick={handleTocClick}
|
||||
className="hidden xl:block"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<CreateNoteDialog open={createOpen} onOpenChange={setCreateOpen} />
|
||||
|
||||
Reference in new issue
Block a user