diff --git a/frontend/src/components/layout/CommandPalette.tsx b/frontend/src/components/layout/CommandPalette.tsx index 1bcc0332..fd768cb2 100644 --- a/frontend/src/components/layout/CommandPalette.tsx +++ b/frontend/src/components/layout/CommandPalette.tsx @@ -55,6 +55,7 @@ const ADMIN_PAGES: PaletteItem[] = [ const QUICK_ACTIONS: PaletteItem[] = [ { id: 'action-new-flow', group: 'quick-actions', title: 'Create New Flow', subtitle: 'Start from scratch or use AI', path: '/trees', icon: 'action' }, + { id: 'action-new-project', group: 'quick-actions', title: 'New Project', subtitle: 'Create a step-by-step project', path: '/flows/new', icon: 'action' }, { id: 'action-kb', group: 'quick-actions', title: 'Import from KB', subtitle: 'KB Accelerator', path: '/kb-accelerator', icon: 'action' }, { id: 'action-scripts', group: 'quick-actions', title: 'Open Script Generator', subtitle: 'Generate automation scripts', path: '/scripts', icon: 'action' }, ] diff --git a/frontend/src/components/layout/QuickLaunch.tsx b/frontend/src/components/layout/QuickLaunch.tsx deleted file mode 100644 index da4feb3f..00000000 --- a/frontend/src/components/layout/QuickLaunch.tsx +++ /dev/null @@ -1,158 +0,0 @@ -import { useState, useEffect, useRef } from 'react' -import { useNavigate } from 'react-router-dom' -import { Plus, Play, FileText, Bookmark, Users, X } from 'lucide-react' -import { treesApi } from '@/api/trees' -import type { TreeListItem } from '@/types' -import { getTreeNavigatePath } from '@/lib/routing' -import { cn } from '@/lib/utils' - -interface QuickLaunchProps { - open: boolean - onClose: () => void -} - -interface QuickAction { - id: string - icon: typeof Plus - label: string - description: string - path: string - color: string -} - -const ACTIONS: QuickAction[] = [ - { id: 'new-tree', icon: Plus, label: 'New Troubleshooting Flow', description: 'Create a branching decision tree', path: '/trees/new', color: '#3b82f6' }, - { id: 'new-project', icon: Plus, label: 'New Project', description: 'Create a step-by-step project', path: '/flows/new', color: '#8b5cf6' }, - { id: 'sessions', icon: Play, label: 'View Sessions', description: 'See active and recent sessions', path: '/sessions', color: '#f59e0b' }, - { id: 'step-library', icon: Bookmark, label: 'Solutions Library', description: 'Browse team solutions', path: '/step-library', color: '#10b981' }, - { id: 'exports', icon: FileText, label: 'Exports & Shares', description: 'View shared session exports', path: '/shares', color: '#06b6d4' }, - { id: 'team', icon: Users, label: 'Team Settings', description: 'Manage team members and roles', path: '/account', color: '#ec4899' }, -] - -export function QuickLaunch({ open, onClose }: QuickLaunchProps) { - const navigate = useNavigate() - const [recentTrees, setRecentTrees] = useState([]) - const [selectedIndex, setSelectedIndex] = useState(0) - const containerRef = useRef(null) - - const allItems = [...ACTIONS.map(a => ({ type: 'action' as const, ...a })), ...recentTrees.slice(0, 4).map(t => ({ type: 'tree' as const, ...t }))] - const totalItems = allItems.length - - useEffect(() => { - if (open) { - // eslint-disable-next-line react-hooks/set-state-in-effect - setSelectedIndex(0) - treesApi.list({ sort_by: 'updated_at' }) - .then(trees => setRecentTrees(trees.slice(0, 4))) - .catch(() => {}) - } - }, [open]) - - useEffect(() => { - if (!open) return - const handler = (e: KeyboardEvent) => { - if (e.key === 'Escape') onClose() - if (e.key === 'ArrowDown') { e.preventDefault(); setSelectedIndex(i => Math.min(i + 1, totalItems - 1)) } - if (e.key === 'ArrowUp') { e.preventDefault(); setSelectedIndex(i => Math.max(i - 1, 0)) } - if (e.key === 'Enter') { - e.preventDefault() - const item = allItems[selectedIndex] - if (!item) return - onClose() - if (item.type === 'action') navigate(item.path) - else navigate(getTreeNavigatePath(item.id, item.tree_type)) - } - } - document.addEventListener('keydown', handler) - return () => document.removeEventListener('keydown', handler) - }, [open, selectedIndex, totalItems, allItems, navigate, onClose]) - - if (!open) return null - - return ( -
-
-
-
-

Quick Launch

- -
- -
- {/* Actions */} -

Actions

- {ACTIONS.map((action, i) => { - const Icon = action.icon - return ( - - ) - })} - - {/* Recent flows */} - {recentTrees.length > 0 && ( - <> -

Recent Flows

- {recentTrees.slice(0, 4).map((tree, ti) => { - const idx = ACTIONS.length + ti - return ( - - ) - })} - - )} -
- -
- - โ†‘โ†“ - Navigate - - - โ†ต - Open - -
-
-
- ) -} diff --git a/frontend/src/components/layout/Sidebar.tsx b/frontend/src/components/layout/Sidebar.tsx index 99d8677e..2499c486 100644 --- a/frontend/src/components/layout/Sidebar.tsx +++ b/frontend/src/components/layout/Sidebar.tsx @@ -367,7 +367,7 @@ export function Sidebar() {
New Session @@ -424,7 +424,7 @@ export function Sidebar() {
diff --git a/frontend/src/components/layout/TopBar.tsx b/frontend/src/components/layout/TopBar.tsx index cc365cf9..9dd66c00 100644 --- a/frontend/src/components/layout/TopBar.tsx +++ b/frontend/src/components/layout/TopBar.tsx @@ -1,11 +1,10 @@ import { useState, useRef, useEffect, useCallback } from 'react' import { Link, useNavigate } from 'react-router-dom' -import { Search, Zap, LogOut, Shield, Settings, HelpCircle } from 'lucide-react' +import { Search, LogOut, Shield, Settings, HelpCircle } from 'lucide-react' import { useAuthStore } from '@/store/authStore' import { usePermissions } from '@/hooks/usePermissions' import { BrandLogo } from '@/components/common/BrandLogo' import { CommandPalette } from './CommandPalette' -import { QuickLaunch } from './QuickLaunch' import { NotificationsPanel } from './NotificationsPanel' import { cn } from '@/lib/utils' @@ -16,7 +15,7 @@ export function TopBar() { const [userMenuOpen, setUserMenuOpen] = useState(false) const [commandPaletteOpen, setCommandPaletteOpen] = useState(false) - const [quickLaunchOpen, setQuickLaunchOpen] = useState(false) + const menuRef = useRef(null) const handleLogout = async () => { @@ -113,13 +112,6 @@ export function TopBar() { {/* Action buttons */}
- setCommandPaletteOpen(false)} /> - setQuickLaunchOpen(false)} /> ) }