import { RefreshCw, Camera, FileDown, Network, SlidersHorizontal, Send, KeyRound, ArrowLeftRight, Wrench, Workflow, } from 'lucide-react'; import { FleetMasthead } from './fleet/FleetMasthead'; import { ReconnectingOverlay } from './FleetView/ReconnectingOverlay'; import { NodeUpdatesSheet } from './FleetView/NodeUpdatesSheet'; import { LocalUpdateConfirmDialog } from './FleetView/LocalUpdateConfirmDialog'; import { OverviewTab } from './FleetView/OverviewTab'; import { useFleetPreferences } from './FleetView/hooks/useFleetPreferences'; import { useFleetUpdateStatus } from './FleetView/hooks/useFleetUpdateStatus'; import { useFleetPolling } from './FleetView/hooks/useFleetPolling'; import { useFleetOverview } from './FleetView/hooks/useFleetOverview'; import { useFleetDossierExport } from './FleetView/hooks/useFleetDossierExport'; import { useTopologyPreferences } from '@/hooks/useTopologyPreferences'; import { Button } from '@/components/ui/button'; import { Tabs, TabsContent, TabsList, TabsTrigger, TabsHighlight, TabsHighlightItem } from '@/components/ui/tabs'; import { springs } from '@/lib/motion'; import { useLicense } from '@/context/LicenseContext'; import { useAuth } from '@/context/AuthContext'; import { PaidGate } from './PaidGate'; import FleetSnapshots from './FleetSnapshots'; import { FleetConfiguration } from './fleet/FleetConfiguration'; import { RoutingTab } from './fleet/RoutingTab'; import { FederationTab } from './fleet/FederationTab'; import { DeploymentsTab } from './blueprints/DeploymentsTab'; import { FleetActionsTab } from './fleet/FleetActions/FleetActionsTab'; import { SecretsTab } from './fleet/secrets/SecretsTab'; import { DependencyMapTab } from './fleet/DependencyMapTab'; import { useNodeActions } from './nodes/useNodeActions'; interface FleetViewProps { onNavigateToNode: (nodeId: number, stackName: string) => void; } export function FleetView({ onNavigateToNode }: FleetViewProps) { const { isPaid } = useLicense(); const { isAdmin } = useAuth(); const { prefs, updatePrefs } = useFleetPreferences(); const updateStatus = useFleetUpdateStatus(); const overview = useFleetOverview({ prefs, updatePrefs, updateStatuses: updateStatus.updateStatuses }); const topology = useTopologyPreferences(); const { exporting, exportDossier } = useFleetDossierExport(); useFleetPolling({ fetchOverview: overview.fetchOverview, fetchUpdateStatus: updateStatus.fetchUpdateStatus, updateStatuses: updateStatus.updateStatuses, }); const { mastheadStats, lastSyncAt, loading, refreshing } = overview; const { openCreate, openEdit, openDelete, NodeActionModals } = useNodeActions({ onNodeChange: () => { void overview.fetchOverview(true); }, }); return (
Overview {isAdmin && ( Snapshots )} Status Map {isPaid && ( Deployments )} {isPaid && ( Routing )} {isPaid && ( Federation )} Actions {isPaid && isAdmin && ( Secrets )}
{isAdmin && ( )}
{ void overview.fetchOverview(true); }} onEditNode={isAdmin ? openEdit : undefined} onDeleteNode={isAdmin ? openDelete : undefined} onAddNode={isAdmin ? openCreate : undefined} onCheckUpdates={updateStatus.checkUpdates} checkingUpdates={updateStatus.checkingUpdates} topologyMode={topology.prefs.mode} onTopologyModeChange={topology.setMode} topologyPositions={topology.prefs.positions} onTopologyPositionsChange={topology.setPositions} /> {isAdmin && ( )} {isPaid && ( )} {isPaid && ( )} {isPaid && ( )} {/* Fleet Actions runs against the whole fleet, so it takes the unfiltered node list rather than the overview-filtered view. */} {isPaid && isAdmin && ( )}
{updateStatus.reconnecting && ( )} { if (!open) updateStatus.setLocalUpdateConfirm(null); }} onConfirm={updateStatus.confirmLocalUpdate} /> {NodeActionModals}
); }