diff --git a/ccw/frontend/src/components/shared/CommandCreateDialog.tsx b/ccw/frontend/src/components/shared/CommandCreateDialog.tsx index 38a3688d..5c92dedd 100644 --- a/ccw/frontend/src/components/shared/CommandCreateDialog.tsx +++ b/ccw/frontend/src/components/shared/CommandCreateDialog.tsx @@ -16,6 +16,7 @@ import { XCircle, Loader2, Info, + FolderOpen, } from 'lucide-react'; import { Dialog, @@ -31,6 +32,7 @@ import { Textarea } from '@/components/ui/Textarea'; import { Label } from '@/components/ui/Label'; import { validateCommandImport, createCommand } from '@/lib/api'; import { useWorkflowStore, selectProjectPath } from '@/stores/workflowStore'; +import { FloatingFileBrowser } from '@/components/terminal-dashboard/FloatingFileBrowser'; import { cn } from '@/lib/utils'; export interface CommandCreateDialogProps { @@ -68,6 +70,9 @@ export function CommandCreateDialog({ open, onOpenChange, onCreated, cliType = ' const [isCreating, setIsCreating] = useState(false); + // File browser state + const [isFileBrowserOpen, setIsFileBrowserOpen] = useState(false); + const resetState = useCallback(() => { setMode('import'); setLocation('project'); @@ -78,6 +83,7 @@ export function CommandCreateDialog({ open, onOpenChange, onCreated, cliType = ' setCommandName(''); setDescription(''); setIsCreating(false); + setIsFileBrowserOpen(false); }, []); const handleOpenChange = useCallback((open: boolean) => { @@ -250,16 +256,27 @@ export function CommandCreateDialog({ open, onOpenChange, onCreated, cliType = '
- { - setSourcePath(e.target.value); - setValidationResult(null); - }} - placeholder={formatMessage({ id: 'commands.create.sourcePathPlaceholder' })} - className="font-mono text-sm" - /> +
+ { + setSourcePath(e.target.value); + setValidationResult(null); + }} + placeholder={formatMessage({ id: 'commands.create.sourcePathPlaceholder' })} + className="font-mono text-sm flex-1" + /> + +

{formatMessage({ id: 'commands.create.sourcePathHint' })}

@@ -401,6 +418,19 @@ export function CommandCreateDialog({ open, onOpenChange, onCreated, cliType = ' + + {/* File Browser for selecting source file */} + setIsFileBrowserOpen(false)} + rootPath={projectPath} + onInsertPath={(path) => { + setSourcePath(path); + setValidationResult(null); + setIsFileBrowserOpen(false); + }} + initialSelectedPath={sourcePath || null} + /> ); } diff --git a/ccw/frontend/src/locales/en/commands.json b/ccw/frontend/src/locales/en/commands.json index a6cf8f87..dabcf05b 100644 --- a/ccw/frontend/src/locales/en/commands.json +++ b/ccw/frontend/src/locales/en/commands.json @@ -74,6 +74,7 @@ "sourcePath": "Source File Path", "sourcePathPlaceholder": "Enter absolute path to command file", "sourcePathHint": "File must be a valid command markdown file", + "browseFile": "Browse files", "customName": "Custom Name", "customNamePlaceholder": "Leave empty to use original name", "customNameHint": "Optional, overrides default command name", diff --git a/ccw/frontend/src/locales/zh/commands.json b/ccw/frontend/src/locales/zh/commands.json index 29c8039d..9a59007e 100644 --- a/ccw/frontend/src/locales/zh/commands.json +++ b/ccw/frontend/src/locales/zh/commands.json @@ -74,6 +74,7 @@ "sourcePath": "源文件路径", "sourcePathPlaceholder": "输入命令文件的绝对路径", "sourcePathHint": "文件必须是有效的命令 Markdown 文件", + "browseFile": "浏览文件", "customName": "自定义名称", "customNamePlaceholder": "留空则使用原始名称", "customNameHint": "可选,覆盖默认命令名称", diff --git a/ccw/frontend/src/pages/CommandsManagerPage.tsx b/ccw/frontend/src/pages/CommandsManagerPage.tsx index efc47260..bf8aae22 100644 --- a/ccw/frontend/src/pages/CommandsManagerPage.tsx +++ b/ccw/frontend/src/pages/CommandsManagerPage.tsx @@ -18,6 +18,7 @@ import { AlertCircle, Maximize2, Minimize2, + Plus, } from 'lucide-react'; import { useAppStore, selectIsImmersiveMode } from '@/stores/appStore'; import { Card } from '@/components/ui/Card'; @@ -27,6 +28,7 @@ import { Badge } from '@/components/ui/Badge'; import { TabsNavigation } from '@/components/ui/TabsNavigation'; import { useCommands, useCommandMutations } from '@/hooks'; import { CommandGroupAccordion } from '@/components/commands/CommandGroupAccordion'; +import { CommandCreateDialog } from '@/components/shared/CommandCreateDialog'; import { cn } from '@/lib/utils'; // ========== Main Page Component ========== @@ -42,6 +44,8 @@ export function CommandsManagerPage() { const [expandedGroups, setExpandedGroups] = useState>(new Set(['cli', 'workflow'])); // Search state const [searchQuery, setSearchQuery] = useState(''); + // Create dialog state + const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false); // Immersive mode state const isImmersiveMode = useAppStore(selectIsImmersiveMode); @@ -117,6 +121,10 @@ export function CommandsManagerPage() {

+
); }