feat: obsidian-style graph view for wissens-vault
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import { useEffect, useMemo, useState } from "react"
|
||||
import { Library, FileText, Sparkles, Loader2, FolderOpen, Search } from "lucide-react"
|
||||
import { api, type WissenDatei, type WissenFile } from "@/lib/api"
|
||||
import { useWissen } from "@/lib/queries"
|
||||
import { useWissen, useMemoryGraph } from "@/lib/queries"
|
||||
import { GraphView } from "./GraphView"
|
||||
import { GraphErrorBoundary } from "./GraphErrorBoundary"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
// Wissens-Vault: die nächtlichen Traum-Notizen der Box als klickbares Wiki.
|
||||
@@ -23,6 +25,9 @@ export function WissenView() {
|
||||
const [doc, setDoc] = useState<WissenDatei | null>(null)
|
||||
const [docLoading, setDocLoading] = useState(false)
|
||||
const [q, setQ] = useState("")
|
||||
const [showGraph, setShowGraph] = useState(false)
|
||||
|
||||
const { data: graphData, isLoading: graphLoading } = useMemoryGraph(showGraph)
|
||||
|
||||
const files = useMemo(() => data?.files ?? [], [data])
|
||||
|
||||
@@ -74,13 +79,31 @@ export function WissenView() {
|
||||
|
||||
return (
|
||||
<div className="space-y-5">
|
||||
<div>
|
||||
<h1 className="bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text font-space text-2xl font-bold tracking-tight text-transparent">
|
||||
Wissen
|
||||
</h1>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Was sich die Box nachts erschließt — Traum-Notizen, Muster und Skill-Ideen aus dem Wissens-Vault, verlinkt wie ein Wiki.
|
||||
</p>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text font-space text-2xl font-bold tracking-tight text-transparent">
|
||||
Wissen
|
||||
</h1>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Was sich die Box nachts erschließt — Traum-Notizen, Muster und Skill-Ideen aus dem Wissens-Vault, verlinkt wie ein Wiki.
|
||||
</p>
|
||||
</div>
|
||||
{files.length > 0 && (
|
||||
<div className="flex rounded-lg border border-border/60 bg-card p-1">
|
||||
<button
|
||||
onClick={() => setShowGraph(false)}
|
||||
className={cn("rounded-md px-3 py-1.5 text-xs font-medium transition-colors", !showGraph ? "bg-primary text-primary-foreground shadow" : "text-muted-foreground hover:bg-muted")}
|
||||
>
|
||||
Liste
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setShowGraph(true)}
|
||||
className={cn("rounded-md px-3 py-1.5 text-xs font-medium transition-colors", showGraph ? "bg-primary text-primary-foreground shadow" : "text-muted-foreground hover:bg-muted")}
|
||||
>
|
||||
Graph
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{data && !data.available && (
|
||||
@@ -101,7 +124,31 @@ export function WissenView() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{files.length > 0 && (
|
||||
{showGraph ? (
|
||||
<div className="mc-card flex h-[70vh] flex-col overflow-hidden p-0 relative">
|
||||
{graphLoading && (
|
||||
<div className="absolute inset-0 flex items-center justify-center bg-background/50 z-10">
|
||||
<div className="flex items-center gap-2 rounded-2xl border border-border/60 bg-card p-6 text-xs text-muted-foreground">
|
||||
<Loader2 className="h-4 w-4 animate-spin" /> Graph wird berechnet …
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<GraphErrorBoundary>
|
||||
{graphData && (
|
||||
<GraphView
|
||||
data={graphData}
|
||||
selectedNodeId={active}
|
||||
onNodeSelect={(id) => {
|
||||
if (id) {
|
||||
setActive(id)
|
||||
setShowGraph(false)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</GraphErrorBoundary>
|
||||
</div>
|
||||
) : files.length > 0 && (
|
||||
<div className="flex flex-col gap-4 lg:flex-row">
|
||||
{/* Datei-Liste */}
|
||||
<aside className="w-full shrink-0 space-y-3 lg:w-72">
|
||||
|
||||
Reference in New Issue
Block a user