This commit consolidates OAuth2 client management components and
enhances the overall user experience with improved UI consistency.
### Major Changes:
**Component Consolidation:**
- Merge CreateOAuth2ClientModal.jsx and EditOAuth2ClientModal.jsx into OAuth2ClientModal.jsx
- Extract inline Modal.info into dedicated ClientInfoModal.jsx component
- Adopt consistent SideSheet + Card layout following EditTokenModal.jsx style
**UI/UX Improvements:**
- Replace custom client type selection with SemiUI RadioGroup component
- Use 'card' type RadioGroup with descriptive 'extra' prop for better UX
- Remove all Row/Col components in favor of flexbox and margin-based layouts
- Refactor redirect URI section to mimic JSONEditor.jsx visual style
- Add responsive design support for mobile devices
**Form Enhancements:**
- Add 'required' attributes to all mandatory form fields
- Implement placeholders for grant types, scopes, and redirect URI inputs
- Set grant types and scopes to default empty arrays
- Add dynamic validation and conditional rendering for client types
- Improve redirect URI management with template filling functionality
**Bug Fixes:**
- Fix SideSheet closing direction consistency between create/edit modes
- Resolve client_type submission issue (object vs string)
- Prevent "Client Credentials" selection for public clients
- Fix grant type filtering when switching between client types
- Resolve i18n issues for API scope options (api:read, api:write)
**Code Quality:**
- Extract RedirectUriCard as reusable sub-component
- Add comprehensive internationalization support
- Implement proper state management and form validation
- Follow single responsibility principle for component separation
**Files Modified:**
- web/src/components/settings/oauth2/modals/OAuth2ClientModal.jsx
- web/src/components/settings/oauth2/modals/ClientInfoModal.jsx (new)
- web/src/components/settings/oauth2/OAuth2ClientSettings.jsx
- web/src/i18n/locales/en.json
**Files Removed:**
- web/src/components/settings/oauth2/modals/CreateOAuth2ClientModal.jsx
- web/src/components/settings/oauth2/modals/EditOAuth2ClientModal.jsx
This refactoring significantly improves code maintainability, reduces
duplication, and provides a more consistent and intuitive user interface
for OAuth2 client management.
- Refactor JWKSManagerModal with tab-based navigation using Card components
- Add comprehensive i18n support with English translations for all text
- Optimize header actions: refresh button only appears in key list tab
- Improve responsive design using ResponsiveModal component
- Move cautionary text from bottom to Card titles for better visibility
- Update button styles: danger type for delete, circle shape for status tags
- Standardize code formatting (single quotes, multiline formatting)
- Enhance user workflow: separate Import PEM and Generate PEM operations
- Remove redundant cancel buttons as modal already has close icon
Breaking changes: None
Affects: JWKS key management, OAuth2 settings UI
- **Empty Component Enhancement:**
- Replace custom User icon with professional IllustrationNoResult from Semi Design
- Add dark mode support with IllustrationNoResultDark component
- Standardize illustration size to 150x150px for consistency
- Add proper padding (30px) to match design system standards
- **Style Modernization:**
- Convert inline styles to Tailwind CSS classes where appropriate
- Replace `style={{ marginBottom: 16 }}` with `className='mb-4'`
- Remove redundant `style={{ marginTop: 8 }}` from Table component
- Remove custom `style={{ marginTop: 16 }}` from pagination and button
- **Pagination Simplification:**
- Simplify showTotal configuration from custom function to boolean `true`
- Remove unnecessary `size='small'` property from pagination
- Clean up pagination styling for better consistency
- **Design System Alignment:**
- Ensure Empty component matches UsersTable styling patterns
- Improve visual consistency across OAuth2 management interfaces
- Follow Semi Design illustration guidelines for empty states
- **Code Quality:**
- Reduce inline style usage in favor of utility classes
- Simplify component props where default behavior is sufficient
- Maintain functionality while improving maintainability
This update enhances visual consistency and follows modern React styling practices while maintaining all existing functionality.
- **Table Layout Optimization:**
- Remove description column from OAuth2 client table to save space
- Add tooltip on client name hover to display full description
- Adjust table scroll width from 1200px to 1000px for better layout
- Improve client name column width to 180px for better readability
- **Action Button Simplification:**
- Replace icon-only buttons with text labels for better accessibility
- Simplify Popconfirm content by removing complex styled layouts
- Remove unnecessary Tooltip wrappers around action buttons
- Clean up unused Lucide icon imports (Edit, Key, Trash2)
- **Code Display Enhancement:**
- Replace basic <pre> tags with CodeViewer component in modal dialogs
- Add syntax highlighting for JSON content in ServerInfoModal and JWKSInfoModal
- Implement copy-to-clipboard functionality for server info and JWKS data
- Add performance optimization for large content display
- Provide expandable/collapsible interface for better UX
- **Component Architecture:**
- Import and integrate CodeViewer component in both modal components
- Set appropriate props: content, title, and language='json'
- Maintain loading states and error handling functionality
- **Internationalization:**
- Add English translations for new UI elements:
* '暂无描述': 'No description'
* 'OAuth2 服务器配置': 'OAuth2 Server Configuration'
* 'JWKS 密钥集': 'JWKS Key Set'
- **User Experience Improvements:**
- Enhanced tooltip interaction for description display
- Better visual feedback with cursor-help styling
- Improved code readability with professional dark theme
- Consistent styling across all OAuth2 management interfaces
This update focuses on UI/UX improvements while maintaining full functionality and adding modern code viewing capabilities to the OAuth2 management system.
- **UI Restructuring:**
- Separate client info into individual table columns (name, ID, description)
- Replace icon-only action buttons with text labels for better UX
- Adjust table scroll width from 1000px to 1200px for new column layout
- Remove unnecessary Tooltip wrappers and Lucide icons (Edit, Key, Trash2)
- **Component Architecture:**
- Extract all modal dialogs into separate reusable components:
* SecretDisplayModal.jsx - for displaying regenerated client secrets
* ServerInfoModal.jsx - for OAuth2 server configuration info
* JWKSInfoModal.jsx - for JWKS key set information
- Simplify main component by removing ~60 lines of inline modal code
- Implement proper state management for each modal component
- **Code Quality:**
- Remove unused imports and clean up component dependencies
- Consolidate modal logic into dedicated components with error handling
- Improve code maintainability and reusability across the application
- **Internationalization:**
- Add English translation for '客户端名称': 'Client Name'
- Remove duplicate translation keys to fix linter warnings
- Ensure all new components support full i18n functionality
- **User Experience:**
- Enhance table readability with dedicated columns for each data type
- Maintain copyable client ID functionality in separate column
- Improve action button accessibility with clear text labels
- Add loading states and proper error handling in modal components
This refactoring improves code organization, enhances user experience, and follows React best practices for component composition and separation of concerns.
- Add responsive layout for user info section with flex-col on mobile
- Optimize button layout: vertical stack on mobile, horizontal on desktop
- Implement mobile-first approach with sm: breakpoints throughout
- Adjust container width: max-w-sm on mobile, max-w-lg on desktop
- Enhance touch targets with larger buttons (size='large') on mobile
- Improve content hierarchy with primary action button on top for mobile
- Add responsive padding and spacing: px-3 sm:px-4, py-6 sm:py-8
- Optimize text sizing: text-sm sm:text-base for better mobile readability
- Implement responsive gaps: gap-4 sm:gap-6 for icon spacing
- Add break-all class for long URL text wrapping
- Adjust meta info card spacing and dot separator sizing
- Ensure consistent responsive padding across all content sections
This update significantly improves the mobile user experience while
maintaining the desktop layout, following mobile-first design principles
with Tailwind CSS responsive utilities.
- Redesign OAuth consent page layout with centered card design
- Implement GitHub-style authorization flow presentation
- Add application popover with detailed information on hover
- Replace generic icons with scope-specific icons (email, profile, admin, etc.)
- Integrate i18n support for all hardcoded strings
- Optimize permission display with encapsulated ScopeItem component
- Improve visual hierarchy with Semi UI Divider components
- Unify avatar sizes and implement dynamic color generation
- Move action buttons and redirect info to card footer
- Add separate meta information card for technical details
- Remove redundant color styles to rely on Semi UI theming
- Enhance user account section with clearer GitHub-style messaging
- Replace dot separators with Lucide icons for better visual consistency
- Add site logo with fallback mechanism for branding
- Implement responsive design with Tailwind CSS utilities
This redesign significantly improves the OAuth consent experience by following
modern UI patterns and providing clearer information hierarchy for users.
Context:
Clicking a vendor tab triggered “setActivePage is not a function” from ModelsTabs.jsx:43.
Root cause:
ModelsTabs expects `setActivePage` via props (spread from `useModelsData`), but the hook did not expose it in its return object, so the prop resolved to `undefined`.
Fix:
Export `setActivePage` from `useModelsData`’s return object so `ModelsTabs` receives a valid function.
Result:
Tab switching now correctly resets pagination to page 1 and reloads models without runtime errors.
Files:
- web/src/hooks/models/useModelsData.jsx
Test plan:
- Open the Models page
- Click different vendor tabs
- Verify no crash occurs and the list reloads with page reset to 1
Refs: web/src/components/table/models/ModelsTabs.jsx:43
When syncing official models, clicking "Apply overwrite" with zero selected
conflict fields resulted in no request being sent and the modal simply closing.
This blocked creation of missing models/vendors even though the backend
supports an empty `overwrite` array and will still create missing items.
Changes:
- Remove the early-return guard in `UpstreamConflictModal.handleOk`
- Always call `onSubmit(payload)` even when `payload` is empty
- Keep closing behavior when the request succeeds
Behavior:
- Users can now proceed with upstream sync without selecting any conflict fields
- Missing models/vendors are created as expected
- Existing models are not overwritten unless fields are explicitly selected
Affected:
- web/src/components/table/models/modals/UpstreamConflictModal.jsx
Quality:
- Lint passes
- No breaking changes
- No visual/UI changes beyond the intended behavior
Test plan:
1) Open official models sync and trigger a conflicts preview
2) Click "Apply overwrite" without selecting any fields
3) Expect the sync to proceed and a success toast indicating created models
4) Re-try with some fields selected to confirm overwrites still work
Ensure UpstreamConflictModal submits { overwrite: payload, locale } instead of spreading an array into an object
Remove numeric-key fallback from applyUpstreamOverwrite for simpler and explicit logic
Effect: selected fields are now actually updated; success message shows updated model count
Refs: backend SyncUpstreamModels expects overwrite: overwriteField[]
Frontend (web)
- ModelsActions.jsx
- Replace “Sync Official” with “Sync” and open a new two-step SyncWizard.
- Pass selected locale through to preview, sync, and overwrite flows.
- Keep conflict resolution flow; inject locale into overwrite submission.
- New: models/modals/SyncWizardModal.jsx
- Two-step wizard: (1) method selection (config-sync disabled for now), (2) language selection (en/zh/ja).
- Horizontal, centered Radio cards; returns { option, locale } via onConfirm.
- UpstreamConflictModal.jsx
- Add search input (model fuzzy search) and native pagination.
- Column header checkbox now only applies to rows in the current filtered result.
- Fix “Cannot access ‘filteredDataSource’ before initialization”.
- Refactor with useMemo/useCallback; extract helpers to remove duplicated logic:
- getPresentRowsForField, getHeaderState, applyHeaderChange
- Minor code cleanups and stability improvements.
- i18n (en.json)
- Add strings for the sync wizard and related actions (Sync, Sync Wizard, Select method/source/language, etc.).
- Adjust minor translations.
Hooks
- useModelsData.jsx
- Extend previewUpstreamDiff, syncUpstream, applyUpstreamOverwrite to accept options with locale.
- Send locale via query/body accordingly.
Backend (Go)
- controller/model_sync.go
- Accept locale from query/body and resolve i18n upstream URLs.
- Add SYNC_UPSTREAM_BASE for upstream base override (default: https://basellm.github.io/llm-metadata).
- Make HTTP timeouts/retries/limits configurable:
- SYNC_HTTP_TIMEOUT_SECONDS, SYNC_HTTP_RETRY, SYNC_HTTP_MAX_MB
- Add ETag-based caching and support both envelope and pure array JSON formats.
- Concurrently fetch vendors and models; improve error responses with locale and source URLs.
- Include source meta (locale, models_url, vendors_url) in success payloads.
Notes
- No breaking changes expected.
- Lint passes for touched files.
- Set sidebar skeleton background to use theme variable (--semi-color-bg-0) instead of hardcoded white for better dark mode compatibility
- Apply consistent background to both collapsed and expanded skeleton states
- Ensure sidebar container uses theme background when skeleton is loading
- Remove duplicate margin-right classes from skeleton wrapper components that conflicted with CSS definitions
- Simplify navigation text structure by removing unnecessary div wrappers to improve text truncation
- Add proper text layout styles for better truncation handling when menu items have long names
- Standardize icon-to-text spacing across all sidebar navigation items
The Linux/Vite build failed with:
“Could not resolve "./headerbar" from "src/components/layout/PageLayout.jsx"”
On Linux and with stricter ESM/rollup resolution, directory index files (index.jsx)
may not be auto-resolved reliably. Explicitly importing the index file ensures
cross-platform stability.
Changes:
- Update PageLayout import from "./headerbar" to "./headerbar/index.jsx"
Impact:
- Fixes build on Linux
- No runtime behavior changes
Verification:
- Linter passes for web/src/components/layout/PageLayout.jsx
Notes:
- Prefer explicit index file imports (and extensions) to avoid platform differences.
Backend (controller/ratio_sync.go):
- Add built‑in official upstream to GetSyncableChannels (ID: -100, BaseURL: https://basellm.github.io)
- Support absolute endpoint URLs; otherwise join BaseURL + endpoint (defaults to /api/ratio_config)
- Harden HTTP client:
- IPv4‑first with IPv6 fallback for github.io
- Add ResponseHeaderTimeout
- 3 attempts with exponential backoff (200/400/800ms)
- Validate Content-Type and limit response body to 10MB (safe decode via io.LimitReader)
- Robust parsing: support type1 ratio_config map and type2 pricing list
- Use net.SplitHostPort for host parsing
- Use float tolerance in differences comparison to avoid false mismatches
- Remove unused code (tryDirect) and improve warnings
Frontend:
- UpstreamRatioSync.jsx: auto-assign official endpoint to /llm-metadata/api/newapi/ratio_config-v1-base.json
- ChannelSelectorModal.jsx:
- Pin the official source at the top of the list
- Show a green “官方” tag next to the status
- Refactor status renderer to accept the full record
Notes:
- Backward compatible; no API surface changes
- Official ratio_config reference: https://basellm.github.io/llm-metadata/api/newapi/ratio_config-v1-base.json
- Ran: bun run eslint:fix && bun run lint:fix
- Inserted AGPL license header via eslint-plugin-header
- Enforced no-multiple-empty-lines and other lint rules
- Formatted code using Prettier v3 (@so1ve/prettier-config)
- No functional changes; formatting-only baseline across JS/JSX files
- Replace copy button icon from semi-ui IconCopy to lucide-react Copy in PricingCardView
- Add conditional tooltip functionality to SelectableButtonGroup that only shows when text overflows
- Implement responsive table column behavior in PricingTableColumns with mobile-aware fixed positioning
- Use DOM-based overflow detection (scrollWidth vs clientWidth) for better performance
- Apply useIsMobile hook to conditionally set fixed: 'right' only on desktop devices
These changes improve user experience across different screen sizes and provide more consistent iconography throughout the pricing interface.
This commit updates the default pagination settings across the model pricing
components to improve user experience by reducing the need for frequent
page navigation when browsing large model catalogs.
Changes made:
- Update initial pageSize state from 10 to 100 in useModelPricingData hook
- Set defaultPageSize to 100 in PricingTable pagination configuration
- Increase default skeletonCount from 10 to 100 in PricingCardSkeleton
Files modified:
- web/src/hooks/model-pricing/useModelPricingData.jsx
- web/src/components/table/model-pricing/view/table/PricingTable.jsx
- web/src/components/table/model-pricing/view/card/PricingCardSkeleton.jsx
This change affects both card and table view modes of the model pricing page,
ensuring consistent pagination behavior across different display formats.
This commit introduces a comprehensive responsive design system for the SelectableButtonGroup component that adapts to container width changes, particularly optimized for dynamic sidebar layouts.
## Key Features
### 1. Container Width Detection
- Added `useContainerWidth` hook using ResizeObserver API
- Real-time container width monitoring for responsive calculations
- Automatic layout adjustments based on available space
### 2. Intelligent Column Layout
Implements a 4-tier responsive system:
- **≤280px**: 1 column + tags (mobile portrait)
- **281-380px**: 2 columns + tags (narrow screens)
- **381-460px**: 3 columns - tags (general case, prioritizes readability)
- **>460px**: 3 columns + tags (wide screens, full feature display)
### 3. Dynamic Tag Visibility
- Tags automatically hide in medium-width containers (381-460px) to improve text readability
- Tags show in narrow and wide containers where space allows for optimal UX
- Responsive threshold ensures content clarity across all viewport sizes
### 4. Adaptive Grid Spacing
- Compact spacing `[4,4]` for containers ≤400px
- Standard spacing `[6,6]` for larger containers
- Additional `.sbg-compact` CSS class for fine-tuned styling in narrow layouts
### 5. Sidebar Integration
- Perfectly compatible with dynamic sidebar width: `clamp(280px, 24vw, 520px)`
- Automatically adjusts as sidebar scales with viewport changes
- Maintains optimal button density and information display at all sizes
## Technical Implementation
- **Hook**: `useContainerWidth.js` - ResizeObserver-based width detection
- **Component**: Enhanced `SelectableButtonGroup.jsx` with responsive logic
- **Styling**: Added `.sbg-compact` mode in `index.css`
- **Performance**: Efficient span calculation using `Math.floor(24 / perRow)`
## Benefits
- Improved UX across all screen sizes and sidebar configurations
- Better text readability through intelligent tag hiding
- Seamless integration with existing responsive sidebar system
- Maintains component functionality while optimizing space utilization
Closes: Responsive design implementation for model marketplace sidebar components
- Add `filter={selectFilter}` to enable search filtering in group Select component
- Add `autoClearSearchValue={false}` to preserve search input value
- Maintain consistency with existing model selector search behavior
- Improve user experience by allowing quick filtering of group options
Files modified:
- web/src/components/playground/SettingsPanel.jsx
- Update error-state rendering to use white text in the playground chat
- Remove Typography.Text `type="danger"` and the red background for consistency with official behavior
- Preserve layout and other message states (loading/success/system) unchanged
- No linter issues introduced
Files touched:
- web/src/components/playground/MessageContent.jsx