Spaces:
Sleeping
Sleeping
| import { memo } from "react"; | |
| import type * as React from "react"; | |
| import { useUIStore } from "@/store/uiStore"; | |
| import AnimatedBrain from "@/components/chat/AnimatedBrain"; | |
| import { | |
| IconConnectors, IconSettings as IconSettingsSvg, | |
| } from "@/components/TabIcons"; | |
| import { | |
| FolderOpen, Activity, Bug, GitBranch, Rocket, Database, Lock, } from "lucide-react"; | |
| // S761: estratto da MainWorkspace.tsx (AUDIT P0 — decomposizione MoreTab) | |
| // Tutte le azioni leggono UIStore direttamente — zero prop drilling. | |
| // Unico prop esterno: onNewProject (local useState in MainWorkspace — non in store). | |
| interface WorkspaceMoreMenuProps { | |
| /** Callback per aprire NewProjectPanel (local useState in MainWorkspace) */ | |
| onNewProject: () => void; | |
| } | |
| const WorkspaceMoreMenu = memo(function WorkspaceMoreMenu(_props: WorkspaceMoreMenuProps) { | |
| const tab = useUIStore(s => s.activeTab); | |
| const setShowMemory = useUIStore(s => s.setShowMemory); | |
| const setShowConnectors = useUIStore(s => s.setShowConnectors); | |
| const setShowFileExplorer = useUIStore(s => s.setShowFileExplorer); | |
| const setShowSettings = useUIStore(s => s.setShowSettings); | |
| const toggleTelemetry = useUIStore(s => s.toggleTelemetry); | |
| const toggleWorkspacePicker = useUIStore(s => s.toggleWorkspacePicker); | |
| const toggleGitSync = useUIStore(s => s.toggleGitSync); | |
| const toggleDeployPanel = useUIStore(s => s.toggleDeployPanel); | |
| const toggleProblems = useUIStore(s => s.toggleProblems); | |
| const toggleDbBrowser = useUIStore(s => s.toggleDbBrowser); | |
| const toggleSecretsPanel = useUIStore(s => s.toggleSecretsPanel); | |
| const setShowNewProject = useUIStore(s => s.setShowNewProject); | |
| const items: { icon: React.ReactNode; label: string; desc: string; onClick: () => void }[] = [ | |
| { icon: <AnimatedBrain size={18} />, label: "Memoria Agente", desc: "Ricordi, sessioni, pattern appresi", onClick: () => setShowMemory(true) }, | |
| { icon: <IconConnectors />, label: "Connettori API", desc: "Servizi REST collegati all'agente", onClick: () => setShowConnectors(true) }, | |
| { icon: <FolderOpen size={18} />, label: "File System VFS", desc: "Esplora, carica ed esporta file nel VFS", onClick: () => setShowFileExplorer(true) }, | |
| { icon: <IconSettingsSvg />, label: "Impostazioni", desc: "Token provider, modello AI, routing", onClick: () => setShowSettings(true) }, | |
| { icon: <Activity size={18} />, label: "Statistiche", desc: "TTFT provider, tool usage, success rate", onClick: toggleTelemetry }, | |
| { icon: <FolderOpen size={18} />, label: "Workspace", desc: "Gestisci workspace multipli", onClick: toggleWorkspacePicker }, | |
| { icon: <span style={{ fontSize: "1.1rem" }}>🏗</span>, label: "Nuovo progetto", desc: "Scaffold react/nextjs/fastapi/flask/…", onClick: () => setShowNewProject(true) }, | |
| { icon: <GitBranch size={18} />, label: "Git Sync", desc: "Pull, diff e push VFS ↔ GitHub", onClick: toggleGitSync }, | |
| { icon: <Rocket size={18} />, label: "Deploy", desc: "Publish su Cloudflare Pages — 1 click", onClick: toggleDeployPanel }, | |
| { icon: <Bug size={18} />, label: "Problemi", desc: "Diagnostics, run profiles e stato CI/CD", onClick: toggleProblems }, | |
| { icon: <Database size={18} />, label: "Database", desc: "Esplora tabelle IndexedDB, export, stats", onClick: toggleDbBrowser }, | |
| { icon: <Lock size={18} />, label: "Segreti", desc: "Vault segreti cifrati — Railway", onClick: toggleSecretsPanel }, | |
| ]; | |
| return ( | |
| <div className={tab === "more" ? "tab-pane-active" : undefined} | |
| style={{ display: tab === "more" ? "flex" : "none", flex: 1, overflow: "auto", flexDirection: "column", padding: "1.2rem 1rem" }}> | |
| <p style={{ fontSize: "0.7rem", color: "#3a3a6a", fontFamily: "monospace", letterSpacing: "0.08em", marginBottom: "1rem" }}> | |
| STRUMENTI / TOOLS | |
| </p> | |
| {items.map(item => ( | |
| <button key={item.label} onClick={item.onClick} style={{ | |
| all: "unset", display: "flex", alignItems: "center", gap: 14, cursor: "pointer", | |
| padding: "0.9rem 1rem", borderRadius: 12, marginBottom: 8, | |
| background: "rgba(99,102,241,0.04)", border: "1px solid rgba(99,102,241,0.10)", | |
| transition: "background 0.15s, border-color 0.15s", | |
| }} | |
| onMouseEnter={e => { e.currentTarget.style.background = "rgba(99,102,241,0.09)"; e.currentTarget.style.borderColor = "rgba(99,102,241,0.22)"; }} | |
| onMouseLeave={e => { e.currentTarget.style.background = "rgba(99,102,241,0.04)"; e.currentTarget.style.borderColor = "rgba(99,102,241,0.10)"; }} | |
| > | |
| <span style={{ color: "var(--primary)", flexShrink: 0 }}>{item.icon}</span> | |
| <div style={{ flex: 1, minWidth: 0 }}> | |
| <div style={{ fontSize: "0.88rem", fontWeight: 600, color: "#d0d0f0" }}>{item.label}</div> | |
| <div style={{ fontSize: "0.72rem", color: "#4a4a78", marginTop: 2 }}>{item.desc}</div> | |
| </div> | |
| </button> | |
| ))} | |
| </div> | |
| ); | |
| }); | |
| export default WorkspaceMoreMenu; | |