feat(settings): one page per section with a grouped nav and search

Settings moves from a tab bar to /settings/<section>: a left nav grouped
General / Agents / Routing / Git / Projects (a select on narrow screens), a
search box over every section (Ctrl/Cmd+F, Enter opens the first match), and
row primitives. Each AI tool has its page under agents/<id>, the AI Tools
modal becomes the Agents page, Pricing shows every vendor, Git → Worktrees
sets which untracked worktrees the sidebar lists, and each project gets a
page with its own worktree override and Forget all. ?tool= and #ai-tools
links redirect to the path form.
This commit is contained in:
2026-10-01 16:55:44 +07:00
parent ba2c4e1914
commit eb90244182
33 changed files with 2478 additions and 2594 deletions
+92 -9
View File
@@ -463,15 +463,6 @@
"remoteSourceBadgeTitle": "Collected from a remote machine"
},
"cursorPathsNote": "Informational: Cursor sessions count here too — Cursor happens to use the same ~/.claude paths as Claude Code (locally and on synced remotes).",
"tools": {
"label": "Tools",
"dashboard": "Dashboard",
"claudeCode": "Claude Code",
"codex": "Codex",
"antigravity": "Antigravity",
"aiRouter": "AI Router",
"gitCredentials": "Git credentials"
},
"aiRouter": {
"title": "AI Router",
"description": "Endpoints that stand in front of Claude Code and Codex — 9Router, OpenRouter, a self-hosted gateway. Save one here, then pick it when you create a workspace.",
@@ -639,5 +630,97 @@
"save": "Save",
"close": "Close",
"saved": "Saved. Backup: {{backup}}"
},
"settingsNav": {
"label": "Settings sections",
"back": "Back to Workspace",
"group": {
"general": "General",
"agents": "Agents",
"routing": "Routing",
"git": "Git",
"projects": "Projects"
},
"section": {
"general": {
"title": "General",
"description": "Workspace housekeeping, data and about."
},
"appearance": {
"title": "Appearance",
"description": "Colour mode and theme. Saved in this browser only."
},
"notifications": {
"title": "Notifications",
"description": "Browser notifications, alert rules and webhooks."
},
"agents": {
"title": "AI tools",
"description": "The AI coding CLIs AgentHub can run: enable, set the default, install and update."
},
"claudeCode": {
"title": "Claude Code",
"description": "Claude Code's own configuration, and what AgentHub reads from it."
},
"codex": {
"title": "Codex",
"description": "Codex's own configuration, and what AgentHub reads from it."
},
"tool": {
"description": "{{tool}}: path, usage, default model and config files."
},
"aiRouter": {
"title": "AI Router",
"description": "Endpoints that stand in front of Claude Code and Codex."
},
"pricing": {
"title": "Pricing",
"description": "Model prices for every vendor, used to estimate cost."
},
"gitCredentials": {
"title": "Git credentials",
"description": "Logins AgentHub gives git for a dashboard fetch, pull or push."
},
"worktrees": {
"title": "Worktrees",
"description": "Which git worktrees the sidebar lists under each project."
},
"project": {
"description": "This project's workspaces and worktree settings."
}
}
},
"search": {
"placeholder": "Search settings",
"noMatch": "No setting matches “{{query}}”."
},
"worktrees": {
"title": "Untracked worktrees",
"description": "A worktree with no workspace on it is listed under its project with an Adopt button. Saved in this browser only.",
"showUntracked": "Show untracked worktrees",
"showUntrackedDesc": "List a repository's worktrees that have no workspace yet.",
"claude": "Claude Code worktrees",
"claudeDesc": "Worktrees under <repo>/.claude/worktrees/, made by Claude Code's own agents.",
"agenthub": "AgentHub-managed worktrees",
"agenthubDesc": "Worktrees AgentHub created under its workspaces root."
},
"project": {
"notFound": "No such project.",
"facts": "Project",
"root": "Root",
"mainBranch": "Main branch",
"worktreeCount": "Worktrees",
"workspaces": "Workspaces",
"noWorkspaces": "No workspace in this project yet.",
"sources": "Worktree sources",
"sourcesDesc": "Override the Worktrees page for this project only.",
"override": "Use this project's own setting",
"forget": "Forget workspaces",
"forgetDesc": "Remove every workspace of this project from AgentHub. Working trees, branches and data on disk are left alone.",
"forgetAll": "Forget all workspaces…",
"forgetTitle": "Forget {{count}} workspaces?",
"forgetBody": "AgentHub drops its record of each one and stops its runs. Nothing on disk is deleted.",
"forgetConfirm": "Forget all",
"forgetFailed": "Could not forget {{lane}}: {{message}}"
}
}
+92 -9
View File
@@ -463,15 +463,6 @@
"remoteSourceBadgeTitle": "Được thu thập từ một máy từ xa"
},
"cursorPathsNote": "Chỉ mang tính thông tin: phiên Cursor cũng được tính — Cursor tình cờ dùng cùng đường dẫn ~/.claude với Claude Code (cục bộ và trên máy từ xa đã đồng bộ).",
"tools": {
"label": "Công cụ",
"dashboard": "Dashboard",
"claudeCode": "Claude Code",
"codex": "Codex",
"antigravity": "Antigravity",
"aiRouter": "AI Router",
"gitCredentials": "Git credentials"
},
"aiRouter": {
"title": "AI Router",
"description": "Các endpoint đứng trước Claude Code và Codex — 9Router, OpenRouter, hoặc gateway tự dựng. Lưu ở đây rồi chọn lúc tạo workspace.",
@@ -639,5 +630,97 @@
"save": "Lưu",
"close": "Đóng",
"saved": "Đã lưu. Bản sao lưu: {{backup}}"
},
"settingsNav": {
"label": "Các mục cài đặt",
"back": "Quay lại Không gian làm việc",
"group": {
"general": "Chung",
"agents": "Tác tử",
"routing": "Định tuyến",
"git": "Git",
"projects": "Dự án"
},
"section": {
"general": {
"title": "Chung",
"description": "Dọn dẹp workspace, dữ liệu và thông tin."
},
"appearance": {
"title": "Giao diện",
"description": "Chế độ màu và theme. Chỉ lưu trong trình duyệt này."
},
"notifications": {
"title": "Thông báo",
"description": "Thông báo trình duyệt, quy tắc cảnh báo và webhook."
},
"agents": {
"title": "AI tools",
"description": "Các CLI lập trình AI mà AgentHub chạy được: bật, đặt mặc định, cài và cập nhật."
},
"claudeCode": {
"title": "Claude Code",
"description": "Cấu hình của Claude Code và những gì AgentHub đọc từ đó."
},
"codex": {
"title": "Codex",
"description": "Cấu hình của Codex và những gì AgentHub đọc từ đó."
},
"tool": {
"description": "{{tool}}: đường dẫn, mức dùng, mô hình mặc định và file cấu hình."
},
"aiRouter": {
"title": "AI Router",
"description": "Các endpoint đứng trước Claude Code và Codex."
},
"pricing": {
"title": "Định giá",
"description": "Giá mô hình của mọi nhà cung cấp, dùng để ước tính chi phí."
},
"gitCredentials": {
"title": "Git credentials",
"description": "Thông tin đăng nhập AgentHub đưa cho git khi fetch, pull hoặc push từ dashboard."
},
"worktrees": {
"title": "Worktree",
"description": "Những git worktree mà sidebar liệt kê dưới mỗi dự án."
},
"project": {
"description": "Các workspace và cài đặt worktree của dự án này."
}
}
},
"search": {
"placeholder": "Tìm cài đặt",
"noMatch": "Không có cài đặt nào khớp “{{query}}”."
},
"worktrees": {
"title": "Worktree chưa theo dõi",
"description": "Worktree chưa có workspace được liệt kê dưới dự án của nó kèm nút Nhận. Chỉ lưu trong trình duyệt này.",
"showUntracked": "Hiện worktree chưa theo dõi",
"showUntrackedDesc": "Liệt kê các worktree của repo chưa có workspace.",
"claude": "Worktree của Claude Code",
"claudeDesc": "Worktree dưới <repo>/.claude/worktrees/, do agent của Claude Code tạo.",
"agenthub": "Worktree do AgentHub quản lý",
"agenthubDesc": "Worktree AgentHub tạo dưới thư mục gốc workspace của nó."
},
"project": {
"notFound": "Không có dự án này.",
"facts": "Dự án",
"root": "Thư mục gốc",
"mainBranch": "Nhánh chính",
"worktreeCount": "Worktree",
"workspaces": "Workspace",
"noWorkspaces": "Dự án này chưa có workspace.",
"sources": "Nguồn worktree",
"sourcesDesc": "Ghi đè trang Worktree cho riêng dự án này.",
"override": "Dùng cài đặt riêng của dự án",
"forget": "Quên workspace",
"forgetDesc": "Gỡ mọi workspace của dự án này khỏi AgentHub. Thư mục làm việc, nhánh và dữ liệu trên đĩa được giữ nguyên.",
"forgetAll": "Quên tất cả workspace…",
"forgetTitle": "Quên {{count}} workspace?",
"forgetBody": "AgentHub xoá bản ghi của từng workspace và dừng các lượt chạy. Không có gì trên đĩa bị xoá.",
"forgetConfirm": "Quên tất cả",
"forgetFailed": "Không quên được {{lane}}: {{message}}"
}
}