mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-28 09:23:08 +08:00
feat(terminal-dashboard): add session name (tag) field for grouping
- Add tag/name input field to CliConfigModal with auto-generation
- Auto-generate format: {tool}-{HHmmss} (e.g., gemini-143052)
- Add regenerate button for quick name changes
- Add i18n keys for new fields (en/zh)
Sessions are now grouped by tag in the sidebar for better organization.
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as React from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { FolderOpen } from 'lucide-react';
|
||||
import { FolderOpen, RefreshCw } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Input } from '@/components/ui/Input';
|
||||
@@ -37,6 +37,8 @@ export interface CliSessionConfig {
|
||||
launchMode: LaunchMode;
|
||||
preferredShell: ShellKind;
|
||||
workingDir: string;
|
||||
/** Session tag for grouping (auto-generated if not provided) */
|
||||
tag: string;
|
||||
}
|
||||
|
||||
export interface CliConfigModalProps {
|
||||
@@ -58,6 +60,16 @@ const MODEL_OPTIONS: Record<CliTool, string[]> = {
|
||||
|
||||
const AUTO_MODEL_VALUE = '__auto__';
|
||||
|
||||
/**
|
||||
* Generate a tag name: {tool}-{HHmmss}
|
||||
* Example: gemini-143052
|
||||
*/
|
||||
function generateTag(tool: CliTool): string {
|
||||
const now = new Date();
|
||||
const time = now.toTimeString().slice(0, 8).replace(/:/g, '');
|
||||
return `${tool}-${time}`;
|
||||
}
|
||||
|
||||
export function CliConfigModal({
|
||||
isOpen,
|
||||
onClose,
|
||||
@@ -74,19 +86,34 @@ export function CliConfigModal({
|
||||
typeof navigator !== 'undefined' && navigator.platform.toLowerCase().includes('win') ? 'cmd' : 'bash'
|
||||
);
|
||||
const [workingDir, setWorkingDir] = React.useState<string>(defaultWorkingDir ?? '');
|
||||
const [tag, setTag] = React.useState<string>('');
|
||||
|
||||
const [isSubmitting, setIsSubmitting] = React.useState(false);
|
||||
const [error, setError] = React.useState<string | null>(null);
|
||||
|
||||
const modelOptions = React.useMemo(() => MODEL_OPTIONS[tool] ?? [], [tool]);
|
||||
|
||||
// Generate new tag when modal opens or tool changes
|
||||
const regenerateTag = React.useCallback(() => {
|
||||
setTag(generateTag(tool));
|
||||
}, [tool]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!isOpen) return;
|
||||
// Reset to a safe default each time the modal is opened.
|
||||
const nextWorkingDir = defaultWorkingDir ?? '';
|
||||
setWorkingDir(nextWorkingDir);
|
||||
setError(null);
|
||||
}, [isOpen, defaultWorkingDir]);
|
||||
regenerateTag();
|
||||
}, [isOpen, defaultWorkingDir, regenerateTag]);
|
||||
|
||||
// Update tag prefix when tool changes
|
||||
React.useEffect(() => {
|
||||
if (tag) {
|
||||
const suffix = tag.split('-').pop() || '';
|
||||
setTag(`${tool}-${suffix}`);
|
||||
}
|
||||
}, [tool]);
|
||||
|
||||
const handleToolChange = (nextTool: string) => {
|
||||
const next = nextTool as CliTool;
|
||||
@@ -109,6 +136,8 @@ export function CliConfigModal({
|
||||
return;
|
||||
}
|
||||
|
||||
const finalTag = tag.trim() || generateTag(tool);
|
||||
|
||||
setIsSubmitting(true);
|
||||
setError(null);
|
||||
try {
|
||||
@@ -118,6 +147,7 @@ export function CliConfigModal({
|
||||
launchMode,
|
||||
preferredShell,
|
||||
workingDir: dir,
|
||||
tag: finalTag,
|
||||
});
|
||||
onClose();
|
||||
} catch (err) {
|
||||
@@ -139,6 +169,35 @@ export function CliConfigModal({
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-4 py-4">
|
||||
{/* Tag / Name */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="cli-config-tag">
|
||||
{formatMessage({ id: 'terminalDashboard.cliConfig.tag', defaultMessage: 'Session Name' })}
|
||||
</Label>
|
||||
<div className="flex gap-2">
|
||||
<Input
|
||||
id="cli-config-tag"
|
||||
value={tag}
|
||||
onChange={(e) => setTag(e.target.value)}
|
||||
placeholder={formatMessage({ id: 'terminalDashboard.cliConfig.tagPlaceholder', defaultMessage: 'e.g., gemini-143052' })}
|
||||
disabled={isSubmitting}
|
||||
className="flex-1"
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={regenerateTag}
|
||||
disabled={isSubmitting}
|
||||
title={formatMessage({ id: 'terminalDashboard.cliConfig.regenerateTag', defaultMessage: 'Regenerate name' })}
|
||||
>
|
||||
<RefreshCw className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{formatMessage({ id: 'terminalDashboard.cliConfig.tagHint', defaultMessage: 'Auto-generated as {tool}-{time}. Used for grouping sessions.' })}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
{/* Tool */}
|
||||
<div className="space-y-2">
|
||||
@@ -271,4 +330,3 @@ export function CliConfigModal({
|
||||
}
|
||||
|
||||
export default CliConfigModal;
|
||||
|
||||
|
||||
@@ -90,6 +90,10 @@
|
||||
"cliConfig": {
|
||||
"title": "Create CLI Session",
|
||||
"description": "Configure tool, model, mode, shell, and working directory.",
|
||||
"tag": "Session Name",
|
||||
"tagPlaceholder": "e.g., gemini-143052",
|
||||
"tagHint": "Auto-generated as {tool}-{time}. Used for grouping sessions.",
|
||||
"regenerateTag": "Regenerate name",
|
||||
"tool": "Tool",
|
||||
"model": "Model",
|
||||
"modelAuto": "Auto",
|
||||
|
||||
@@ -90,6 +90,10 @@
|
||||
"cliConfig": {
|
||||
"title": "创建 CLI 会话",
|
||||
"description": "配置工具、模型、模式、Shell 与工作目录。",
|
||||
"tag": "会话名称",
|
||||
"tagPlaceholder": "例如:gemini-143052",
|
||||
"tagHint": "自动生成格式:{工具}-{时间}。用于会话分组显示。",
|
||||
"regenerateTag": "重新生成名称",
|
||||
"tool": "工具",
|
||||
"model": "模型",
|
||||
"modelAuto": "自动",
|
||||
|
||||
Reference in New Issue
Block a user