feat(settings): add advanced settings navigation tabs
This commit is contained in:
1 parent
c121e46056
commit
97b6f82e76
5 files changed
+83
-8
No files matched your search
+4
-1
@@ -11,7 +11,7 @@ export const jaOverrides = {
|
||||
'app.nav.home': 'ホーム',
|
||||
'app.nav.versions': 'バージョン管理',
|
||||
'app.nav.kernel': 'コア',
|
||||
'app.nav.config': '設定',
|
||||
'app.nav.config': '詳細設定',
|
||||
'app.nav.thinkingAliases': 'モデルエイリアス',
|
||||
'app.nav.oauth': 'OAuth',
|
||||
'app.nav.api': 'API 接続',
|
||||
@@ -241,6 +241,9 @@ export const jaOverrides = {
|
||||
'aliases.delete': '{alias} を削除',
|
||||
'config.routing.roundRobin': 'ラウンドロビン',
|
||||
'config.routing.fillFirst': '優先充填',
|
||||
'config.tabs.label': '詳細設定ページ',
|
||||
'config.tabs.general': '基本設定',
|
||||
'config.tabs.network': 'ネットワークとルーティング',
|
||||
'config.error.emptyKey': '認証キーを入力してください',
|
||||
'config.error.invalidKey': '空白を含まない表示可能な ASCII 文字のみ使用できます',
|
||||
'config.error.duplicateKey': '同じ認証キーがすでに存在します',
|
||||
|
||||
@@ -14,7 +14,7 @@ export const zhCN = {
|
||||
'app.nav.home': '首页',
|
||||
'app.nav.versions': '版本管理',
|
||||
'app.nav.kernel': '内核',
|
||||
'app.nav.config': '配置',
|
||||
'app.nav.config': '高级设置',
|
||||
'app.nav.thinkingAliases': '模型别名',
|
||||
'app.nav.oauth': 'OAuth',
|
||||
'app.nav.api': 'API 接入',
|
||||
@@ -244,6 +244,9 @@ export const zhCN = {
|
||||
'aliases.delete': '删除 {alias}',
|
||||
'config.routing.roundRobin': '轮询',
|
||||
'config.routing.fillFirst': '优先填充',
|
||||
'config.tabs.label': '高级设置子页面',
|
||||
'config.tabs.general': '基础设置',
|
||||
'config.tabs.network': '网络与路由',
|
||||
'config.error.emptyKey': '鉴权密钥不能为空',
|
||||
'config.error.invalidKey': '只能使用 ASCII 可见字符,且不能包含空格',
|
||||
'config.error.duplicateKey': '该鉴权密钥已经存在',
|
||||
@@ -861,7 +864,7 @@ export const en: Record<MessageKey, string> = {
|
||||
'app.nav.home': 'Home',
|
||||
'app.nav.versions': 'Version Management',
|
||||
'app.nav.kernel': 'Core',
|
||||
'app.nav.config': 'Settings',
|
||||
'app.nav.config': 'Advanced Settings',
|
||||
'app.nav.thinkingAliases': 'Model Aliases',
|
||||
'app.nav.oauth': 'OAuth',
|
||||
'app.nav.api': 'API Access',
|
||||
@@ -1091,6 +1094,9 @@ export const en: Record<MessageKey, string> = {
|
||||
'aliases.delete': 'Delete {alias}',
|
||||
'config.routing.roundRobin': 'Round Robin',
|
||||
'config.routing.fillFirst': 'Fill First',
|
||||
'config.tabs.label': 'Advanced settings sections',
|
||||
'config.tabs.general': 'General Settings',
|
||||
'config.tabs.network': 'Network & Routing',
|
||||
'config.error.emptyKey': 'The authentication key cannot be empty',
|
||||
'config.error.invalidKey': 'Use visible ASCII characters only, without spaces',
|
||||
'config.error.duplicateKey': 'This authentication key already exists',
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const phraseReplacements: ReadonlyArray<readonly [string, string]> = [
|
||||
['高级设置', '進階設定'],
|
||||
['繁体中文', '繁體中文'],
|
||||
['简体中文', '簡體中文'],
|
||||
['智能体', '智慧代理'],
|
||||
|
||||
@@ -48,6 +48,7 @@ type ConfigAction =
|
||||
| 'network'
|
||||
| null;
|
||||
type NoticeTone = 'success' | 'error';
|
||||
type ConfigSubpage = 'general' | 'network';
|
||||
|
||||
const ROUTING_OPTIONS = [
|
||||
{ value: 'round-robin', labelKey: 'config.routing.roundRobin' },
|
||||
@@ -70,6 +71,7 @@ export function ConfigPanelPage() {
|
||||
const [formError, setFormError] = useState('');
|
||||
const [copiedIndex, setCopiedIndex] = useState<number | null>(null);
|
||||
const [notice, setNotice] = useState<{ message: string; tone: NoticeTone } | null>(null);
|
||||
const [activeSubpage, setActiveSubpage] = useState<ConfigSubpage>('general');
|
||||
const [portDraft, setPortDraft] = useState('8317');
|
||||
const [allowLanDraft, setAllowLanDraft] = useState(false);
|
||||
const [proxyUrlDraft, setProxyUrlDraft] = useState('');
|
||||
@@ -351,7 +353,41 @@ export function ConfigPanelPage() {
|
||||
|
||||
return (
|
||||
<section className="page config-page">
|
||||
<div className="config-workspace-grid">
|
||||
<div className="agent-subpage-tabs config-subpage-tabs" role="tablist" aria-label={t('config.tabs.label')}>
|
||||
<button
|
||||
type="button"
|
||||
id="config-subpage-tab-general"
|
||||
role="tab"
|
||||
className={activeSubpage === 'general' ? 'active' : ''}
|
||||
aria-selected={activeSubpage === 'general'}
|
||||
aria-controls="config-subpage-panel-general"
|
||||
tabIndex={activeSubpage === 'general' ? 0 : -1}
|
||||
onClick={() => setActiveSubpage('general')}
|
||||
>
|
||||
{t('config.tabs.general')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="config-subpage-tab-network"
|
||||
role="tab"
|
||||
className={activeSubpage === 'network' ? 'active' : ''}
|
||||
aria-selected={activeSubpage === 'network'}
|
||||
aria-controls="config-subpage-panel-network"
|
||||
tabIndex={activeSubpage === 'network' ? 0 : -1}
|
||||
onClick={() => setActiveSubpage('network')}
|
||||
>
|
||||
{t('config.tabs.network')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{activeSubpage === 'general' ? (
|
||||
<div
|
||||
className="config-subpage-panel"
|
||||
id="config-subpage-panel-general"
|
||||
role="tabpanel"
|
||||
aria-labelledby="config-subpage-tab-general"
|
||||
>
|
||||
<div className="config-workspace-grid">
|
||||
<section className="panel config-keys-panel">
|
||||
<div className="config-panel-heading">
|
||||
<div className="config-heading-title">
|
||||
@@ -454,7 +490,7 @@ export function ConfigPanelPage() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="config-side-stack">
|
||||
<div className="config-side-stack single">
|
||||
<section className="panel config-setting-panel">
|
||||
<div className="config-panel-heading">
|
||||
<div className="config-heading-title">
|
||||
@@ -485,7 +521,16 @@ export function ConfigPanelPage() {
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className="config-subpage-panel config-network-subpage"
|
||||
id="config-subpage-panel-network"
|
||||
role="tabpanel"
|
||||
aria-labelledby="config-subpage-tab-network"
|
||||
>
|
||||
<section className="panel config-setting-panel">
|
||||
<div className="config-panel-heading">
|
||||
<div className="config-heading-title">
|
||||
@@ -516,8 +561,6 @@ export function ConfigPanelPage() {
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section className="panel config-network-panel">
|
||||
<div className="config-panel-heading">
|
||||
@@ -658,6 +701,8 @@ export function ConfigPanelPage() {
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{addDialogOpen ? (
|
||||
<div className="config-dialog-backdrop" onMouseDown={(event) => {
|
||||
|
||||
@@ -861,6 +861,16 @@ input:focus-visible {
|
||||
height: 350px;
|
||||
}
|
||||
|
||||
.config-subpage-panel {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.config-network-subpage > .config-setting-panel {
|
||||
width: min(420px, 100%);
|
||||
}
|
||||
|
||||
.control-panel {
|
||||
grid-column: auto;
|
||||
}
|
||||
@@ -1503,6 +1513,12 @@ input:focus-visible {
|
||||
height: 350px;
|
||||
}
|
||||
|
||||
.config-side-stack.single {
|
||||
grid-template-rows: 166px;
|
||||
align-content: start;
|
||||
height: 166px;
|
||||
}
|
||||
|
||||
.config-setting-panel {
|
||||
grid-template-rows: 42px minmax(0, 1fr);
|
||||
gap: 16px;
|
||||
@@ -6725,6 +6741,10 @@ input:focus-visible {
|
||||
height: 166px;
|
||||
}
|
||||
|
||||
.config-side-stack.single {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.control-panel,
|
||||
.version-panel {
|
||||
grid-column: auto;
|
||||
|
||||
Reference in new issue
Block a user