mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-28 09:23:08 +08:00
154 lines
6.1 KiB
TypeScript
154 lines
6.1 KiB
TypeScript
// ========================================
|
|
// Terminal Dashboard Page (V2)
|
|
// ========================================
|
|
// Terminal-first layout with fixed session sidebar + floating panels + right file sidebar.
|
|
// Left sidebar: SessionGroupTree (always visible)
|
|
// Main area: TerminalGrid (tmux-style split panes)
|
|
// Right sidebar: FileSidebarPanel (file tree, resizable)
|
|
// Top: DashboardToolbar with panel toggles and layout presets
|
|
// Floating panels: Issues, Queue, Inspector, Execution Monitor (overlay, mutually exclusive)
|
|
// Fullscreen mode: Uses global isImmersiveMode to hide app chrome (Header + Sidebar)
|
|
|
|
import { useState, useCallback } from 'react';
|
|
import { useIntl } from 'react-intl';
|
|
import { Allotment } from 'allotment';
|
|
import 'allotment/dist/style.css';
|
|
import { AssociationHighlightProvider } from '@/components/terminal-dashboard/AssociationHighlight';
|
|
import { DashboardToolbar, type PanelId } from '@/components/terminal-dashboard/DashboardToolbar';
|
|
import { TerminalGrid } from '@/components/terminal-dashboard/TerminalGrid';
|
|
import { FloatingPanel } from '@/components/terminal-dashboard/FloatingPanel';
|
|
import { SessionGroupTree } from '@/components/terminal-dashboard/SessionGroupTree';
|
|
import { IssuePanel } from '@/components/terminal-dashboard/IssuePanel';
|
|
import { QueuePanel } from '@/components/terminal-dashboard/QueuePanel';
|
|
import { InspectorContent } from '@/components/terminal-dashboard/BottomInspector';
|
|
import { ExecutionMonitorPanel } from '@/components/terminal-dashboard/ExecutionMonitorPanel';
|
|
import { FileSidebarPanel } from '@/components/terminal-dashboard/FileSidebarPanel';
|
|
import { useWorkflowStore, selectProjectPath } from '@/stores/workflowStore';
|
|
import { useAppStore, selectIsImmersiveMode } from '@/stores/appStore';
|
|
import { useConfigStore } from '@/stores/configStore';
|
|
|
|
// ========== Main Page Component ==========
|
|
|
|
export function TerminalDashboardPage() {
|
|
const { formatMessage } = useIntl();
|
|
const [activePanel, setActivePanel] = useState<PanelId | null>(null);
|
|
const [isFileSidebarOpen, setIsFileSidebarOpen] = useState(true);
|
|
const [isSessionSidebarOpen, setIsSessionSidebarOpen] = useState(true);
|
|
|
|
const projectPath = useWorkflowStore(selectProjectPath);
|
|
|
|
// Feature flags for panel visibility
|
|
const featureFlags = useConfigStore((s) => s.featureFlags);
|
|
|
|
// Use global immersive mode state (only affects AppShell chrome)
|
|
const isImmersiveMode = useAppStore(selectIsImmersiveMode);
|
|
const toggleImmersiveMode = useAppStore((s) => s.toggleImmersiveMode);
|
|
|
|
const togglePanel = useCallback((panelId: PanelId) => {
|
|
setActivePanel((prev) => (prev === panelId ? null : panelId));
|
|
}, []);
|
|
|
|
const closePanel = useCallback(() => {
|
|
setActivePanel(null);
|
|
}, []);
|
|
|
|
return (
|
|
<div className={`flex flex-col overflow-hidden ${isImmersiveMode ? 'h-screen' : 'h-[calc(100vh-56px)]'}`}>
|
|
<AssociationHighlightProvider>
|
|
{/* Global toolbar */}
|
|
<DashboardToolbar
|
|
activePanel={activePanel}
|
|
onTogglePanel={togglePanel}
|
|
isFileSidebarOpen={isFileSidebarOpen}
|
|
onToggleFileSidebar={() => setIsFileSidebarOpen((prev) => !prev)}
|
|
isSessionSidebarOpen={isSessionSidebarOpen}
|
|
onToggleSessionSidebar={() => setIsSessionSidebarOpen((prev) => !prev)}
|
|
isFullscreen={isImmersiveMode}
|
|
onToggleFullscreen={toggleImmersiveMode}
|
|
/>
|
|
|
|
{/* Main content with three-column layout */}
|
|
<div className="flex-1 min-h-0">
|
|
<Allotment className="h-full">
|
|
{/* Session sidebar (controlled by local state, not immersive mode) */}
|
|
{isSessionSidebarOpen && (
|
|
<Allotment.Pane preferredSize={240} minSize={180} maxSize={320}>
|
|
<div className="h-full flex flex-col border-r border-border">
|
|
<div className="flex-1 min-h-0 overflow-y-auto">
|
|
<SessionGroupTree />
|
|
</div>
|
|
</div>
|
|
</Allotment.Pane>
|
|
)}
|
|
|
|
{/* Terminal grid (flexible) */}
|
|
<Allotment.Pane preferredSize={-1} minSize={300}>
|
|
<TerminalGrid />
|
|
</Allotment.Pane>
|
|
|
|
{/* File sidebar (controlled by local state, not immersive mode) */}
|
|
{isFileSidebarOpen && (
|
|
<Allotment.Pane preferredSize={280} minSize={200} maxSize={400}>
|
|
<FileSidebarPanel
|
|
rootPath={projectPath ?? '/'}
|
|
enabled={!!projectPath}
|
|
onCollapse={() => setIsFileSidebarOpen(false)}
|
|
/>
|
|
</Allotment.Pane>
|
|
)}
|
|
</Allotment>
|
|
</div>
|
|
|
|
{/* Floating panels (always available) */}
|
|
<FloatingPanel
|
|
isOpen={activePanel === 'issues'}
|
|
onClose={closePanel}
|
|
title={formatMessage({ id: 'terminalDashboard.toolbar.issues' })}
|
|
side="left"
|
|
width={380}
|
|
>
|
|
<IssuePanel />
|
|
</FloatingPanel>
|
|
|
|
{featureFlags.dashboardQueuePanelEnabled && (
|
|
<FloatingPanel
|
|
isOpen={activePanel === 'queue'}
|
|
onClose={closePanel}
|
|
title={formatMessage({ id: 'terminalDashboard.toolbar.queue' })}
|
|
side="right"
|
|
width={400}
|
|
>
|
|
<QueuePanel />
|
|
</FloatingPanel>
|
|
)}
|
|
|
|
{featureFlags.dashboardInspectorEnabled && (
|
|
<FloatingPanel
|
|
isOpen={activePanel === 'inspector'}
|
|
onClose={closePanel}
|
|
title={formatMessage({ id: 'terminalDashboard.toolbar.inspector' })}
|
|
side="right"
|
|
width={360}
|
|
>
|
|
<InspectorContent />
|
|
</FloatingPanel>
|
|
)}
|
|
|
|
{featureFlags.dashboardExecutionMonitorEnabled && (
|
|
<FloatingPanel
|
|
isOpen={activePanel === 'execution'}
|
|
onClose={closePanel}
|
|
title={formatMessage({ id: 'terminalDashboard.toolbar.executionMonitor', defaultMessage: 'Execution Monitor' })}
|
|
side="right"
|
|
width={380}
|
|
>
|
|
<ExecutionMonitorPanel />
|
|
</FloatingPanel>
|
|
)}
|
|
</AssociationHighlightProvider>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default TerminalDashboardPage;
|