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 = '
@@ -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() {
+
);
}