fix: Neuer Chat Button erstellt Session, Ordner drag&drop im KI-Baum

This commit is contained in:
Agent Zero
2026-07-20 02:20:43 +02:00
parent 29202325a6
commit c3974c2ef9
2 changed files with 39 additions and 4 deletions
+27 -1
View File
@@ -43,7 +43,7 @@ function buildTree(folders: ChatFolder[], sessions: ChatSession[]): TreeNode[] {
} }
function TreeItem({ function TreeItem({
node, activeSessionId, onSelectSession, depth, onContextMenu, onDragSession, onDropToFolder, onDelete, node, activeSessionId, onSelectSession, depth, onContextMenu, onDragSession, onDragFolder, onDropToFolder, onDelete,
}: { }: {
node: TreeNode; node: TreeNode;
activeSessionId: string | null; activeSessionId: string | null;
@@ -51,6 +51,7 @@ function TreeItem({
depth: number; depth: number;
onContextMenu: (e: React.MouseEvent, type: 'session' | 'folder' | 'root', id: string | null) => void; onContextMenu: (e: React.MouseEvent, type: 'session' | 'folder' | 'root', id: string | null) => void;
onDragSession: (sessionId: string) => void; onDragSession: (sessionId: string) => void;
onDragFolder: (folderId: string) => void;
onDropToFolder: (folderId: string | null) => void; onDropToFolder: (folderId: string | null) => void;
onDelete: (id: string, type: 'session' | 'folder') => void; onDelete: (id: string, type: 'session' | 'folder') => void;
}) { }) {
@@ -63,7 +64,15 @@ function TreeItem({
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
setIsDragOver(false); setIsDragOver(false);
const data = e.dataTransfer.getData('text/plain');
if (data.startsWith('folder:')) {
const draggedFolderId = data.slice(7);
if (draggedFolderId !== folderId) {
onDropToFolder(folderId); onDropToFolder(folderId);
}
} else {
onDropToFolder(folderId);
}
}; };
const handleDragOver = (e: React.DragEvent) => { const handleDragOver = (e: React.DragEvent) => {
@@ -77,6 +86,12 @@ function TreeItem({
{/* Folder header - drop target */} {/* Folder header - drop target */}
{!isRoot && ( {!isRoot && (
<div <div
draggable
onDragStart={(e) => {
e.dataTransfer.setData('text/plain', `folder:${node.folder!.id}`);
e.dataTransfer.effectAllowed = 'move';
onDragFolder(node.folder!.id);
}}
onDragOver={handleDragOver} onDragOver={handleDragOver}
onDragLeave={() => setIsDragOver(false)} onDragLeave={() => setIsDragOver(false)}
onDrop={handleDrop} onDrop={handleDrop}
@@ -166,6 +181,7 @@ function TreeItem({
depth={depth + 1} depth={depth + 1}
onContextMenu={onContextMenu} onContextMenu={onContextMenu}
onDragSession={onDragSession} onDragSession={onDragSession}
onDragFolder={onDragFolder}
onDropToFolder={onDropToFolder} onDropToFolder={onDropToFolder}
onDelete={onDelete} onDelete={onDelete}
/> />
@@ -236,6 +252,7 @@ export function SessionList({ activeSessionId, onSelectSession, isSidebar, class
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [dragSessionId, setDragSessionId] = useState<string | null>(null); const [dragSessionId, setDragSessionId] = useState<string | null>(null);
const [dragFolderId, setDragFolderId] = useState<string | null>(null);
const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null); const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null);
const loadData = async () => { const loadData = async () => {
@@ -296,6 +313,14 @@ export function SessionList({ activeSessionId, onSelectSession, isSidebar, class
}; };
const handleDropToFolder = async (folderId: string | null) => { const handleDropToFolder = async (folderId: string | null) => {
if (dragFolderId) {
try {
await updateFolder(dragFolderId, { parent_id: folderId });
setDragFolderId(null);
loadData();
} catch (e) { setError(e instanceof Error ? e.message : 'Failed to move folder'); }
return;
}
if (!dragSessionId) return; if (!dragSessionId) return;
try { try {
await updateSession(dragSessionId, { folder_id: folderId }); await updateSession(dragSessionId, { folder_id: folderId });
@@ -326,6 +351,7 @@ export function SessionList({ activeSessionId, onSelectSession, isSidebar, class
depth={0} depth={0}
onContextMenu={handleContextMenu} onContextMenu={handleContextMenu}
onDragSession={setDragSessionId} onDragSession={setDragSessionId}
onDragFolder={setDragFolderId}
onDropToFolder={handleDropToFolder} onDropToFolder={handleDropToFolder}
onDelete={handleDelete} onDelete={handleDelete}
/> />
+11 -2
View File
@@ -3,7 +3,7 @@ import { SessionList } from '@/components/ai/SessionList';
import { ChatWindow } from '@/components/ai/ChatWindow'; import { ChatWindow } from '@/components/ai/ChatWindow';
import { ResizablePanel } from '@/components/ui/ResizablePanel'; import { ResizablePanel } from '@/components/ui/ResizablePanel';
import { usePluginToolbarStore } from '@/store/pluginToolbarStore'; import { usePluginToolbarStore } from '@/store/pluginToolbarStore';
import { fetchAgents, type AIAgent } from '@/api/ai'; import { fetchAgents, createSession, type AIAgent } from '@/api/ai';
export function AIAssistantPage() { export function AIAssistantPage() {
const [activeSessionId, setActiveSessionId] = useState<string | null>(null); const [activeSessionId, setActiveSessionId] = useState<string | null>(null);
@@ -39,7 +39,16 @@ export function AIAssistantPage() {
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" /> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
</svg> </svg>
), ),
onClick: () => { setActiveSessionId(null); setMobileView('list'); setRefreshKey(k => k + 1); }, onClick: async () => {
try {
const session = await createSession({ is_sidebar: false });
setActiveSessionId(session.id);
setMobileView('chat');
setRefreshKey(k => k + 1);
} catch (e) {
console.error('Failed to create session:', e);
}
},
}, },
{ {
id: 'new-folder', id: 'new-folder',