feat: Spark Workbench everywhere, autonomous Hadoop offload & LLM masking-aware
- Data Hub with Hadoop tab (HDFS/Iceberg browser, Spark, pipeline) - Databricks-style Lakehouse Workbench (Trino engine, live exec matrix, materialize to Iceberg/S3); reused & embedded in every source-DB UI - HDFS -> Kafka -> Spark -> Iceberg/S3 pipeline; WebHDFS hostname resolver - Data Flow master pulse switch (Run/Pause/Stop) gating animated edges - Data Custodian autonomous Hadoop offload loop (batch counterpart to CDC), pulsing source -> HDFS edges; toggle in Data Flow - LLM now autonomously aware of all latest platform changes (live platform context) and enforces masking policy: never reveals masked PII, still answers helpfully with aggregates/explanations
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
import { useState } from 'react'
|
||||
import { LayoutDashboard, Presentation } from 'lucide-react'
|
||||
import { PlatformTopology } from './PlatformTopology'
|
||||
import { PresentationView } from './PresentationView'
|
||||
import type { AgentAnim, WorkloadData } from '../../types'
|
||||
import { cn } from '../../lib/utils'
|
||||
import { subTabActive, subTabIdle } from '../../lib/tabActive'
|
||||
|
||||
type PlatformTab = 'topology' | 'presentation'
|
||||
|
||||
type Props = {
|
||||
workload: WorkloadData | null
|
||||
animations: Record<string, AgentAnim>
|
||||
selectedNodeId: string | null
|
||||
onNodeClick: (nodeId: string) => void
|
||||
pulse: boolean
|
||||
}
|
||||
|
||||
const TABS: { id: PlatformTab; label: string; icon: typeof LayoutDashboard }[] = [
|
||||
{ id: 'topology', label: 'Topology', icon: LayoutDashboard },
|
||||
{ id: 'presentation', label: 'Presentation', icon: Presentation },
|
||||
]
|
||||
|
||||
export function PlatformView({ workload, animations, selectedNodeId, onNodeClick, pulse }: Props) {
|
||||
const [tab, setTab] = useState<PlatformTab>('topology')
|
||||
|
||||
return (
|
||||
<div className="flex min-h-0 flex-1 flex-col overflow-hidden">
|
||||
<div className="panel flex shrink-0 items-center gap-1 px-2 py-1.5">
|
||||
{TABS.map(({ id, label, icon: Icon }) => (
|
||||
<button
|
||||
key={id}
|
||||
type="button"
|
||||
onClick={() => setTab(id)}
|
||||
className={cn(
|
||||
'inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-[10px] font-medium transition-all',
|
||||
tab === id ? subTabActive : subTabIdle,
|
||||
)}
|
||||
>
|
||||
<Icon className="h-3.5 w-3.5" />
|
||||
{label}
|
||||
</button>
|
||||
))}
|
||||
{tab === 'presentation' && (
|
||||
<span className="ml-auto text-[9px] text-foreground-muted">
|
||||
Live cluster deck · all running services
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="min-h-0 flex-1 overflow-hidden pt-1">
|
||||
{tab === 'topology' ? (
|
||||
<PlatformTopology
|
||||
workload={workload}
|
||||
animations={animations}
|
||||
selectedNodeId={selectedNodeId}
|
||||
onNodeClick={onNodeClick}
|
||||
pulse={pulse}
|
||||
/>
|
||||
) : (
|
||||
<PresentationView embedded />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user