MCPcopy
hub / github.com/stravu/crystal / ProjectTreeView

Function ProjectTreeView

frontend/src/components/ProjectTreeView.tsx:19–613  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

17}
18
19export function ProjectTreeView() {
20 const [projectsWithSessions, setProjectsWithSessions] = useState<ProjectWithSessions[]>([]);
21 const [expandedProjects, setExpandedProjects] = useState<Set<number>>(new Set());
22 const storesSessions = useSessionStore(state => state.sessions);
23 const [isLoading, setIsLoading] = useState(true);
24 const [showCreateDialog, setShowCreateDialog] = useState(false);
25 const [selectedProjectForCreate, setSelectedProjectForCreate] = useState<Project | null>(null);
26 const [showProjectSettings, setShowProjectSettings] = useState(false);
27 const [selectedProjectForSettings, setSelectedProjectForSettings] = useState<Project | null>(null);
28 const [showAddProjectDialog, setShowAddProjectDialog] = useState(false);
29 const [newProject, setNewProject] = useState<CreateProjectRequest>({ name: '', path: '', buildScript: '', runScript: '' });
30 const [hasPendingUpdates, setHasPendingUpdates] = useState(false);
31 const activeSessionId = useSessionStore((state) => state.activeSessionId);
32 const [showMainBranchWarning, setShowMainBranchWarning] = useState(false);
33 const [pendingMainBranchProject, setPendingMainBranchProject] = useState<Project | null>(null);
34 const [detectedMainBranch, setDetectedMainBranch] = useState<string>('main');
35 const [detectedBranchForNewProject, setDetectedBranchForNewProject] = useState<string | null>(null);
36 const { showError } = useErrorStore();
37
38 useEffect(() => {
39 loadProjectsWithSessions();
40
41 // Set up event listeners for session updates
42 const handleSessionCreated = (newSession: Session) => {
43 console.log('[ProjectTreeView] Session created:', newSession.id, 'projectId:', newSession.projectId);
44
45 // Add the new session to the appropriate project without reloading everything
46 setProjectsWithSessions(prevProjects => {
47 const updatedProjects = prevProjects.map(project => {
48 if (project.id === newSession.projectId) {
49 console.log('[ProjectTreeView] Adding session to project:', project.id, project.name);
50 // Add the new session to this project
51 return {
52 ...project,
53 sessions: [...project.sessions, newSession]
54 };
55 }
56 return project;
57 });
58
59 // If no project was found, log a warning
60 if (!updatedProjects.some(p => p.id === newSession.projectId)) {
61 console.warn('[ProjectTreeView] No matching project found for session projectId:', newSession.projectId);
62 console.log('[ProjectTreeView] Available projects:', prevProjects.map(p => ({ id: p.id, name: p.name })));
63 }
64
65 return updatedProjects;
66 });
67
68 // Auto-expand the project that contains the new session
69 if (newSession.projectId) {
70 setExpandedProjects(prev => new Set([...prev, newSession.projectId!]));
71 }
72 };
73
74 const handleSessionUpdated = (updatedSession: Session) => {
75 // Only reload if the create dialog is not open
76 // This prevents the dialog from losing state during session updates

Callers

nothing calls this directly

Calls 7

toggleProjectFunction · 0.85
openMainRepoSessionFunction · 0.85
openDirectoryMethod · 0.80
loadProjectsWithSessionsFunction · 0.70
handleProjectClickFunction · 0.70
handleCreateSessionFunction · 0.70
detectCurrentBranchFunction · 0.70

Tested by

no test coverage detected