-
Notifications
You must be signed in to change notification settings - Fork 5
feat: modularize web ui and harden local workflows #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b4bf006
6f7c6ff
8399f66
ef83cae
20a49c5
e9f3b19
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,8 +49,10 @@ test('config template keeps expected config tabs in top and side navigation', () | |
| assert.match(html, /class="codex-config-grid"/); | ||
| assert.match(html, /onSettingsTabClick\('backup'\)/); | ||
| assert.match(html, /onSettingsTabClick\('trash'\)/); | ||
| assert.match(html, /onSettingsTabClick\('device'\)/); | ||
| assert.match(html, /settingsTab === 'backup'/); | ||
| assert.match(html, /settingsTab === 'trash'/); | ||
| assert.match(html, /settingsTab === 'device'/); | ||
| assert.match(html, /sessionTrashCount/); | ||
| assert.match(html, /id="side-tab-market"/); | ||
| assert.match(html, /id="tab-market"/); | ||
|
|
@@ -107,17 +109,29 @@ test('config template keeps expected config tabs in top and side navigation', () | |
| assert.doesNotMatch(html, /class="market-ecosystem-grid"/); | ||
| assert.match(html, /id="settings-tab-backup"/); | ||
| assert.match(html, /id="settings-tab-trash"/); | ||
| assert.match(html, /id="settings-tab-device"/); | ||
| assert.match(html, /role="tab"/); | ||
| assert.match(html, /aria-controls="settings-panel-backup"/); | ||
| assert.match(html, /aria-controls="settings-panel-trash"/); | ||
| assert.match(html, /aria-controls="settings-panel-device"/); | ||
| assert.match(html, /:aria-selected="settingsTab === 'backup'"/); | ||
| assert.match(html, /:aria-selected="settingsTab === 'trash'"/); | ||
| assert.match(html, /:aria-selected="settingsTab === 'device'"/); | ||
| assert.match(html, /id="settings-tab-backup"[\s\S]*:tabindex="settingsTab === 'backup' \? 0 : -1"/); | ||
| assert.match(html, /id="settings-tab-trash"[\s\S]*:tabindex="settingsTab === 'trash' \? 0 : -1"/); | ||
| assert.match(html, /id="settings-tab-device"[\s\S]*:tabindex="settingsTab === 'device' \? 0 : -1"/); | ||
| assert.match(html, /id="settings-panel-backup"/); | ||
| assert.match(html, /id="settings-panel-trash"/); | ||
| assert.match(html, /id="settings-panel-device"/); | ||
| assert.match(html, /<div[\s\S]*v-show="settingsTab === 'backup'"[\s\S]*id="settings-panel-backup"[\s\S]*aria-labelledby="settings-tab-backup">/); | ||
| assert.match(html, /<div[\s\S]*v-show="settingsTab === 'trash'"[\s\S]*id="settings-panel-trash"[\s\S]*aria-labelledby="settings-tab-trash">/); | ||
| assert.match(html, /<div[\s\S]*v-show="settingsTab === 'device'"[\s\S]*id="settings-panel-device"[\s\S]*aria-labelledby="settings-tab-device">/); | ||
| assert.match(html, /id="settings-panel-device"[\s\S]*?<span class="selector-title">配置重置<\/span>/); | ||
| assert.match(html, /id="settings-panel-device"[\s\S]*?@click="resetConfig"/); | ||
| assert.doesNotMatch( | ||
| html.match(/id="panel-config-provider"[\s\S]*?<\/template>/)?.[0] || '', | ||
| /<span class="selector-title">配置重置<\/span>/ | ||
| ); | ||
| assert.match(html, /class="settings-tab-actions trash-header-actions"/); | ||
| assert.match(html, /<button class="btn-tool btn-tool-compact" @click="loadSessionTrash\(\{ forceRefresh: true \}\)"/); | ||
| assert.match(html, /<button class="btn-tool btn-tool-compact" @click="clearSessionTrash"/); | ||
|
|
@@ -209,7 +223,7 @@ test('config template keeps expected config tabs in top and side navigation', () | |
| assert.match(templateAgentModals, /<div class="modal modal-wide" role="dialog" aria-modal="true" aria-labelledby="config-template-modal-title">/); | ||
| assert.match(templateAgentModals, /<div class="modal-title" id="config-template-modal-title">Config 模板编辑器(手动确认应用)<\/div>/); | ||
| assert.match(templateAgentModals, /<div v-if="showAgentsModal" class="modal-overlay" @click\.self="closeAgentsModal">/); | ||
| assert.match(templateAgentModals, /<div class="modal modal-wide modal-editor" role="dialog" aria-modal="true" aria-labelledby="agents-modal-title">/); | ||
| assert.match(templateAgentModals, /<div class="modal modal-wide modal-editor agents-modal" role="dialog" aria-modal="true" aria-labelledby="agents-modal-title">/); | ||
| assert.match(templateAgentModals, /<div class="modal-title" id="agents-modal-title">{{ agentsModalTitle }}<\/div>/); | ||
| assert.match(modalsBasic, /<button type="button" class="btn-remove-model" @click="removeModel\(model\)">删除<\/button>/); | ||
| assert.doesNotMatch(modalsBasic, /<span class="btn-remove-model" @click="removeModel\(model\)">删除<\/span>/); | ||
|
|
@@ -326,6 +340,7 @@ test('web ui script defines provider mode metadata for codex only', () => { | |
| assert.match(appScript, /sessionTrashHasMoreItems\(\)/); | ||
| assert.match(appScript, /sessionTrashHiddenCount\(\)/); | ||
| assert.match(appScript, /normalizeSettingsTab\(tab\)/); | ||
| assert.match(appScript, /tab === 'trash' \|\| tab === 'device'/); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Scope the Line 343 only proves that this snippet exists somewhere in the bundle. Another method could satisfy it while 🔧 Suggested change- assert.match(appScript, /normalizeSettingsTab\(tab\)/);
- assert.match(appScript, /tab === 'trash' \|\| tab === 'device'/);
+ assert.match(
+ appScript,
+ /normalizeSettingsTab\(tab\)[\s\S]*tab === 'trash' \|\| tab === 'device'/
+ );🤖 Prompt for AI Agents |
||
| assert.match(appScript, /switchSettingsTab\(tab,\s*options = \{\}\)/); | ||
| assert.match(appScript, /loadSessionTrash\(options = \{\}\)/); | ||
| assert.match(appScript, /loadMoreSessionTrashItems\(\)/); | ||
|
|
@@ -413,7 +428,7 @@ test('trash item styles stay aligned with session card layout and keep mobile us | |
| styles, | ||
| /@media \(max-width: 540px\)\s*\{[\s\S]*\.session-item-copy\.session-item-pin svg,\s*[\s\S]*width:\s*16px;/ | ||
| ); | ||
| assert.match(styles, /@media \(max-width: 540px\)\s*\{[\s\S]*\.session-item-copy\s*\{[\s\S]*width:\s*44px;[\s\S]*height:\s*44px;[\s\S]*min-width:\s*44px;[\s\S]*min-height:\s*44px;/); | ||
| assert.match(styles, /@media \(max-width: 540px\)\s*\{[\s\S]*\.session-item-copy\s*\{[\s\S]*width:\s*36px;[\s\S]*height:\s*36px;[\s\S]*min-width:\s*36px;[\s\S]*min-height:\s*36px;/); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The mobile size check no longer proves the pin action was shrunk. Line 431 now matches a generic 🤖 Prompt for AI Agents |
||
| assert.match(styles, /\.codex-config-grid\s*\{/); | ||
| assert.match(styles, /\.codex-config-grid\s*\{[\s\S]*grid-template-columns:\s*repeat\(auto-fit,\s*minmax\(min\(240px,\s*100%\),\s*1fr\)\);/); | ||
| assert.match(styles, /\.codex-config-field\s*\{/); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,16 @@ | |
| 回收站 | ||
| <span class="settings-tab-badge">{{ sessionTrashCount }}</span> | ||
| </button> | ||
| <button | ||
| id="settings-tab-device" | ||
| role="tab" | ||
| aria-controls="settings-panel-device" | ||
| :aria-selected="settingsTab === 'device'" | ||
| :tabindex="settingsTab === 'device' ? 0 : -1" | ||
| :class="['config-subtab', { active: settingsTab === 'device' }]" | ||
| @click="onSettingsTabClick('device')"> | ||
| 设备 | ||
| </button> | ||
| </div> | ||
|
|
||
| <div | ||
|
|
@@ -137,4 +147,20 @@ | |
| </div> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div | ||
| v-show="settingsTab === 'device'" | ||
| id="settings-panel-device" | ||
| role="tabpanel" | ||
| aria-labelledby="settings-tab-device"> | ||
| <div class="selector-section"> | ||
| <div class="selector-header"> | ||
| <span class="selector-title">配置重置</span> | ||
| </div> | ||
| <div class="config-template-hint">先备份 config.toml,再写默认配置。</div> | ||
| <button class="btn-tool" @click="resetConfig" :disabled="resetConfigLoading || loading || !!initError"> | ||
| {{ resetConfigLoading ? '重装中...' : '重装配置' }} | ||
| </button> | ||
|
Comment on lines
+161
to
+163
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a confirmation step before config reset. Line 161 triggers Suggested guard pattern-<button class="btn-tool" `@click`="resetConfig" :disabled="resetConfigLoading || loading || !!initError">
+<button class="btn-tool" `@click`="confirmAndResetConfig" :disabled="resetConfigLoading || loading || !!initError">// In web-ui/modules/app.methods.providers.mjs
async confirmAndResetConfig() {
const confirmed = await this.requestConfirmDialog({
title: '重装配置',
message: '该操作会重写本地配置文件。请确认已完成备份。',
confirmText: '继续重装',
cancelText: '取消',
danger: true
});
if (!confirmed) return;
await this.resetConfig();
}🤖 Prompt for AI Agents |
||
| </div> | ||
| </div> | ||
| </div> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -314,8 +314,8 @@ | |
| border: 1px solid rgba(70, 86, 110, 0.35); | ||
| background: rgba(70, 86, 110, 0.08); | ||
| color: var(--color-text-secondary); | ||
| width: 28px; | ||
| height: 28px; | ||
| width: 22px; | ||
| height: 22px; | ||
|
Comment on lines
+317
to
+318
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Increase session action hit targets to at least 24px. Line 317 and Line 318 set the action button to Proposed CSS adjustment .session-item-copy {
- width: 22px;
- height: 22px;
+ width: 24px;
+ height: 24px;
+ min-width: 24px;
+ min-height: 24px;
}
.session-item-copy svg {
- width: 10px;
- height: 10px;
+ width: 12px;
+ height: 12px;
}
.session-item-pin .pin-icon,
.session-item-pin svg {
- width: 9px;
- height: 9px;
+ width: 10px;
+ height: 10px;
}Also applies to: 342-344, 350-354 🤖 Prompt for AI Agents |
||
| border-radius: 8px; | ||
| display: inline-flex; | ||
| align-items: center; | ||
|
|
@@ -339,8 +339,8 @@ | |
| } | ||
|
|
||
| .session-item-copy svg { | ||
| width: 16px; | ||
| height: 16px; | ||
| width: 10px; | ||
| height: 10px; | ||
| } | ||
|
|
||
| .session-item-pin { | ||
|
|
@@ -349,6 +349,8 @@ | |
|
|
||
| .session-item-pin .pin-icon, | ||
| .session-item-pin svg { | ||
| width: 9px; | ||
| height: 9px; | ||
| color: rgba(208, 88, 58, 0.78); | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assert the provider panel exists before the negative check.
Line 132 falls back to
'', so this passes ifpanel-config-providerdisappears or the regex stops before the moved reset block. That weakens the regression this block is trying to add.🔧 Suggested change
📝 Committable suggestion
🤖 Prompt for AI Agents