Skip to content

Comments

feat: Fixed WebUI#70

Merged
lich0821 merged 1 commit intolich0821:masterfrom
ANIIAN91:master
Dec 17, 2025
Merged

feat: Fixed WebUI#70
lich0821 merged 1 commit intolich0821:masterfrom
ANIIAN91:master

Conversation

@ANIIAN91
Copy link
Contributor

  • Fix Dashboard statistics display (stats API now returns proper data structure)
  • Add endpoint drag-and-drop reordering functionality
  • Add current endpoint display and manual switching
  • Add model fetching from API endpoints
  • Add test status persistence (localStorage)
  • Update docker-compose configuration
  • Add CSS styles for new features (badges, copy buttons, drag-drop)

🤖 Generated with Claude Code

- Fix Dashboard statistics display (stats API now returns proper data structure)
- Add endpoint drag-and-drop reordering functionality
- Add current endpoint display and manual switching
- Add model fetching from API endpoints
- Add test status persistence (localStorage)
- Add copy buttons for API URLs
- Add WebUI authentication (HTTP Basic Auth via env vars)
- Update docker-compose with authentication configuration
- Add CSS styles for new features (badges, copy buttons, drag-drop)

🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings December 17, 2025 08:18
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds significant WebUI enhancements to the ccNexus admin interface, focusing on improving endpoint management capabilities and fixing dashboard statistics display.

Key Changes:

  • Implemented drag-and-drop functionality for endpoint reordering with visual feedback
  • Added current endpoint tracking and manual switching capabilities
  • Introduced model fetching from API endpoints with an interactive selection modal
  • Implemented test status persistence using localStorage with visual indicators

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 15 comments.

File Description
cmd/server/webui/ui/js/components/endpoints.js Core functionality additions including drag-and-drop reordering, endpoint switching, model fetching, copy-to-clipboard, and test status persistence
cmd/server/webui/ui/css/components.css Added styling for new UI components including badge-primary class, copy button icons, and drag-and-drop visual states
cmd/server/webui/api/stats.go Fixed dashboard statistics API to return proper data structure with aggregated totals (TotalRequests, TotalErrors, tokens) instead of raw stats object
cmd/server/docker-compose.yml Updated build context path to reference parent directory structure correctly (../../ instead of .) and removed deprecated version field

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


getTestStatus(endpointName) {
try {
const statusMap = JSON.parse(localStorage.getItem('ccNexus_endpointTestStatus') || '{}');
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable name 'ccNexus_endpointTestStatus' uses inconsistent casing (camelCase after underscore). For better consistency with JavaScript naming conventions, consider using either 'ccnexus_endpoint_test_status' (snake_case) or 'ccNexusEndpointTestStatus' (camelCase) throughout.

Copilot uses AI. Check for mistakes.
Comment on lines +439 to +454
document.querySelectorAll('.model-item').forEach(item => {
item.addEventListener('click', () => {
const selectedModel = item.dataset.model;
modelInput.value = selectedModel;
notifications.success(`Model selected: ${selectedModel}`);
modelModal.remove();
});

item.addEventListener('mouseenter', () => {
item.style.backgroundColor = '#f3f4f6';
});

item.addEventListener('mouseleave', () => {
item.style.backgroundColor = '';
});
});
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memory leak potential: Event listeners are added to model items but the modal is never properly cleaned up. When the modal is removed with modelModal.remove(), the event listeners should be explicitly removed first to prevent potential memory leaks, especially if this operation is performed frequently.

Copilot uses AI. Check for mistakes.
Comment on lines +121 to +123
<button class="btn-icon copy-btn" data-copy="${this.escapeHtml(ep.apiUrl)}" title="Copy URL">
📋
</button>
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accessibility issue: The copy button uses only an emoji (📋) without any text alternative. Screen readers will announce this as "clipboard emoji" which is not descriptive. Add an aria-label attribute with descriptive text like "Copy API URL to clipboard" for better accessibility.

Copilot uses AI. Check for mistakes.
Comment on lines +26 to +27
totalInputTokens += int64(stats.InputTokens)
totalOutputTokens += int64(stats.OutputTokens)
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential type conversion issue: InputTokens and OutputTokens are being cast to int64, but if the source type is already int64 or larger, this is redundant. If they are smaller types (like int or int32), the conversion is correct, but without seeing the stats structure definition, this could indicate a type mismatch. Consider verifying that the source types match the target types to avoid unnecessary conversions or potential overflow issues.

Copilot uses AI. Check for mistakes.
saveTestStatus(endpointName, success) {
try {
const statusMap = JSON.parse(localStorage.getItem('ccNexus_endpointTestStatus') || '{}');
statusMap[endpointName] = success;
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable name 'ccNexus_endpointTestStatus' uses inconsistent casing (camelCase after underscore). For better consistency with JavaScript naming conventions, consider using either 'ccnexus_endpoint_test_status' (snake_case) or 'ccNexusEndpointTestStatus' (camelCase) throughout.

Copilot uses AI. Check for mistakes.
Comment on lines +112 to +124
<tr data-endpoint="${this.escapeHtml(ep.name)}" data-index="${index}" draggable="true" style="cursor: move;">
<td style="cursor: grab; text-align: center;">⋮⋮</td>
<td>
<strong>${this.escapeHtml(ep.name)}</strong>
<span title="${testStatusTitle}" style="margin-left: 5px;">${testStatusIcon}</span>
${isCurrentEndpoint ? '<span class="badge badge-primary" style="margin-left: 5px;">Current</span>' : ''}
</td>
<td>
<code style="font-size: 12px;">${this.escapeHtml(ep.apiUrl)}</code>
<button class="btn-icon copy-btn" data-copy="${this.escapeHtml(ep.apiUrl)}" title="Copy URL">
📋
</button>
</td>
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inline styles are used throughout the endpoint row rendering instead of CSS classes. This mixing of inline styles with class-based styling makes the code harder to maintain and violates separation of concerns. Consider defining proper CSS classes for these elements (e.g., .endpoint-row-drag-handle, .endpoint-api-url, .endpoint-name-cell) to improve maintainability and consistency.

Copilot uses AI. Check for mistakes.
<td><strong>${this.escapeHtml(ep.name)}</strong></td>
<td><code>${this.escapeHtml(ep.apiUrl)}</code></td>
<tr data-endpoint="${this.escapeHtml(ep.name)}" data-index="${index}" draggable="true" style="cursor: move;">
<td style="cursor: grab; text-align: center;">⋮⋮</td>
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accessibility issue: The drag handle uses only a visual indicator (⋮⋮) without proper ARIA attributes. Screen reader users won't understand that rows are draggable or how to reorder them. Consider adding aria-label="Drag to reorder" to the drag handle cell and role="button" with appropriate keyboard handlers (arrow keys) for accessibility compliance.

Copilot uses AI. Check for mistakes.
Comment on lines +415 to +419
${models.map(model => `
<div class="model-item" style="padding: 10px; border-bottom: 1px solid #e5e7eb; cursor: pointer;" data-model="${this.escapeHtml(model)}">
<strong>${this.escapeHtml(model)}</strong>
</div>
`).join('')}
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The model selection modal doesn't handle empty model names or special characters that could break the HTML structure. If the API returns models with names containing quotes or HTML special characters, the escapeHtml call will protect against XSS but the data-model attribute could still break. Consider using JSON encoding for the data-model attribute or accessing the model name from the text content instead.

Copilot uses AI. Check for mistakes.
Comment on lines +119 to +122
.badge-primary {
background-color: #dbeafe;
color: #1e40af;
}
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The badge-primary class is duplicated with identical styling to the existing badge-info class (lines 114-117). This creates unnecessary code duplication. Consider reusing the existing badge-info class or creating a shared base class if different badge types are needed in the future.

Copilot uses AI. Check for mistakes.

showModelSelectionModal(models, modelInput) {
const modalContainer = document.getElementById('modal-container');
const currentModal = modalContainer.querySelector('.modal');
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable currentModal.

Copilot uses AI. Check for mistakes.
@lich0821 lich0821 merged commit b98a567 into lich0821:master Dec 17, 2025
13 checks passed
lich0821 added a commit that referenced this pull request Dec 30, 2025
* refactor: split app.go

* refactor: reorganize project to standard Go layout with cmd/desktop and cmd/server

* fix: use full path for macOS terminals (Ghostty, Alacritty, etc.)

macOS GUI apps have limited PATH, causing "executable not found" errors.
Now uses detected .app bundle paths instead of relying on PATH lookup.

* feat: Add WebUI enhancements and authentication (#70)

- Fix Dashboard statistics display (stats API now returns proper data structure)
- Add endpoint drag-and-drop reordering functionality
- Add current endpoint display and manual switching
- Add model fetching from API endpoints
- Add test status persistence (localStorage)
- Add copy buttons for API URLs
- Add WebUI authentication (HTTP Basic Auth via env vars)
- Update docker-compose with authentication configuration
- Add CSS styles for new features (badges, copy buttons, drag-drop)

🤖 Generated with Claude Code

Co-authored-by: root <root@ser960574800116.local>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>

* feat: add configurable proxy. close #37 close #69

* v4.6.0

* Feature:新增列表视图模式 (#71)

* resolve merge conflict in main.go, keep remote version

* 简单视图模式合并02

* 简单视图模式03

* 顺序调整

---------

Co-authored-by: hea7en <hea7enn@qq.com>

* v4.7.0

* fix:修复已知问题 (#72)

* resolve merge conflict in main.go, keep remote version

* 已知问题修复

---------

Co-authored-by: hea7en <hea7enn@qq.com>

* v4.7.1

* feat: use proxy for update if configured

* v4.8.0

* chore: fix qr code path

* fix:修复已知问题 (#74)

* resolve merge conflict in main.go, keep remote version

* 界面样式优化

* 样式优化

* 修复已知问题

* pic

* message

---------

Co-authored-by: hea7en <hea7enn@qq.com>

* v4.8.1

* Feature:新增节日氛围效果 (#79)

* resolve merge conflict in main.go, keep remote version

* 新增节日氛围效果

---------

Co-authored-by: hea7en <hea7enn@qq.com>

* v4.8.2

* feature:新增更多节日氛围效果 (#81)

* resolve merge conflict in main.go, keep remote version

* feature:新增更多节日氛围效果

* 优化

* 优化

* tip

* top

* ON

* config

---------

Co-authored-by: hea7en <hea7enn@qq.com>

* v4.8.3

* fix: use login shell for third-party terminals to load PATH correctly

---------

Co-authored-by: Changhua <lichanghua0821@gmail.com>
Co-authored-by: flyingcoding <wbq1724593655@gmail.com>
Co-authored-by: 杨鑫亮 <50096523+ANIIAN91@users.noreply.github.com>
Co-authored-by: root <root@ser960574800116.local>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: hea7en <46583161+hea7enn@users.noreply.github.com>
Co-authored-by: hea7en <hea7enn@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants