fix(ui): admin panel UI improvements#538
Conversation
- Validate provider group tags total length (max 50 chars) - Add DialogDescription for screen reader accessibility - Fix URL preview for empty results 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When the last circuit-broken provider is reset, the filter toggle disappears but the filter state remains true, causing an empty list. Add useEffect to automatically disable the filter when circuitBrokenCount becomes 0. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 📝 WalkthroughWalkthrough向五个locale的settings.json文件添加国际化文本(dialogDescription和groupTagTooLong错误消息),同时在provider表单中实现group tag长度验证,并对多个UI组件进行小幅优化。 Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
Summary of ChangesHello @miraserver, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request focuses on a series of UI improvements and bug fixes across the admin panel. It enhances the user experience by adding crucial validation to provider forms, improving accessibility, and making the URL preview more robust. Furthermore, it resolves dashboard layout inconsistencies and introduces an intelligent auto-reset feature for the circuit breaker filter, contributing to a more stable and user-friendly interface. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a nice set of UI improvements and bug fixes to the admin panel, enhancing both functionality and user experience. Key changes include improved form validation for provider group tags, accessibility enhancements with DialogDescription, and fixes for layout glitches in the dashboard. The auto-resetting circuit breaker filter is also a thoughtful UX improvement. The code is well-structured, but I've pointed out one instance of duplicated validation logic in the provider form that could be refactored for better maintainability. Overall, this is a solid contribution that refines the admin interface.
| // group_tag 在 DB/schema 中限制为 varchar(50),并且后端按整串校验 max(50) | ||
| // 这里限制逗号拼接后的总长度,避免“UI 看似可选多标签,但保存必失败”的体验 | ||
| const serializedGroupTag = groupTag.join(","); | ||
| if (serializedGroupTag.length > GROUP_TAG_MAX_TOTAL_LENGTH) { | ||
| toast.error(t("errors.groupTagTooLong", { max: GROUP_TAG_MAX_TOTAL_LENGTH })); | ||
| return; | ||
| } |
There was a problem hiding this comment.
This validation for the total length of groupTag is redundant. The handleGroupTagChange function, which is called on every change to the tags, already performs this validation and prevents the state from being updated if the length is invalid. Removing this duplicated check from handleSubmit will make the code cleaner and rely on a single source of truth for this validation.
There was a problem hiding this comment.
Code Review Summary
No significant issues identified in this PR. The changes are well-implemented and improve admin panel UI/UX.
PR Size: XS
- Lines changed: 63 (50 additions, 13 deletions)
- Files changed: 10
Changes Reviewed
| File | Analysis |
|---|---|
provider-form.tsx |
✅ Group tag validation matches DB schema (varchar(50)). DialogDescription improves accessibility. |
url-preview.tsx |
✅ Empty result handling prevents rendering empty preview card. |
user-management-table.tsx |
✅ Simplified scroll reset using virtualizer API. |
chart.tsx |
✅ initialDimension prevents layout shift during chart render. |
provider-manager.tsx |
✅ Auto-reset filter when no providers are broken prevents stale UI state. |
messages/*.json |
✅ Translations added for all 5 locales. |
Validation Details
-
Group Tag Validation (
provider-form.tsx):- Confirmed DB schema has
varchar('group_tag', { length: 50 })atsrc/drizzle/schema.ts:141 - Client-side validation with
GROUP_TAG_MAX_TOTAL_LENGTH = 50correctly matches backend constraint - Dual validation (onChange + onSubmit) provides good UX feedback
- Confirmed DB schema has
-
URL Preview Fix (
url-preview.tsx):previewProxyUrls()returns empty object{}for invalid URLs or unknown provider types- The fix correctly treats empty results as
nullto show the error card
-
Scroll Reset Simplification (
user-management-table.tsx):- Using
rowVirtualizer.scrollToOffset(0)is cleaner than manualparentRef.scrollTo()+requestAnimationFrame - The virtualizer handles both scroll position and measurement internally
- Using
-
Circuit Breaker Filter Auto-Reset (
provider-manager.tsx):- Prevents showing empty filtered list when circuit breakers recover
- Effect dependencies are correct:
[circuitBrokenCount, circuitBrokenFilter]
Review Coverage
- Logic and correctness - Clean
- Security (OWASP Top 10) - Clean
- Error handling - Clean
- Type safety - Clean
- Documentation accuracy - Clean
- Test coverage - Manual testing noted in PR
- Code clarity - Good
Automated review by Claude AI
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
messages/ja/settings.json (1)
1045-1048: dialogDescription 日文翻译自然、语义与英文保持一致
providers.form.dialogDescription的日文表述清楚说明“配置提供者详情和高级设置”,与其他 locale 对齐。如希望与同文件中其它句式完全统一,也可以考虑将「構成します」微调为「設定します」,但当前版本已可接受。
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to Reviews > Disable Cache setting
📒 Files selected for processing (10)
messages/en/settings.jsonmessages/ja/settings.jsonmessages/ru/settings.jsonmessages/zh-CN/settings.jsonmessages/zh-TW/settings.jsonsrc/app/[locale]/dashboard/_components/user/user-management-table.tsxsrc/app/[locale]/settings/providers/_components/forms/provider-form.tsxsrc/app/[locale]/settings/providers/_components/forms/url-preview.tsxsrc/app/[locale]/settings/providers/_components/provider-manager.tsxsrc/components/ui/chart.tsx
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx,js,jsx,json}
📄 CodeRabbit inference engine (CLAUDE.md)
Use 2-space indentation in all code files
Files:
src/app/[locale]/dashboard/_components/user/user-management-table.tsxmessages/ru/settings.jsonsrc/components/ui/chart.tsxmessages/ja/settings.jsonmessages/zh-TW/settings.jsonmessages/zh-CN/settings.jsonsrc/app/[locale]/settings/providers/_components/provider-manager.tsxmessages/en/settings.jsonsrc/app/[locale]/settings/providers/_components/forms/url-preview.tsxsrc/app/[locale]/settings/providers/_components/forms/provider-form.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,js,jsx}: Use double quotes for strings instead of single quotes
Use trailing commas in multi-line structures
Enforce maximum line length of 100 characters
Use path alias@/*to reference files from./src/*directory
**/*.{ts,tsx,js,jsx}: Use Biome for linting and formatting with 2-space indent, double quotes, trailing commas, and 100 character max line length
Use path alias@/*to reference files in./src/*directory
Files:
src/app/[locale]/dashboard/_components/user/user-management-table.tsxsrc/components/ui/chart.tsxsrc/app/[locale]/settings/providers/_components/provider-manager.tsxsrc/app/[locale]/settings/providers/_components/forms/url-preview.tsxsrc/app/[locale]/settings/providers/_components/forms/provider-form.tsx
src/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{tsx,jsx}: Uselucide-reactfor icons, no custom SVGs
Use React's automatic escaping to prevent XSS vulnerabilities
Files:
src/app/[locale]/dashboard/_components/user/user-management-table.tsxsrc/components/ui/chart.tsxsrc/app/[locale]/settings/providers/_components/provider-manager.tsxsrc/app/[locale]/settings/providers/_components/forms/url-preview.tsxsrc/app/[locale]/settings/providers/_components/forms/provider-form.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use TypeScript strict mode for type safety
Use readonly or const assertions for immutable data structures
Files:
src/app/[locale]/dashboard/_components/user/user-management-table.tsxsrc/components/ui/chart.tsxsrc/app/[locale]/settings/providers/_components/provider-manager.tsxsrc/app/[locale]/settings/providers/_components/forms/url-preview.tsxsrc/app/[locale]/settings/providers/_components/forms/provider-form.tsx
**/*.{tsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Use next-intl for internationalization with 5 locales: en, ja, ru, zh-CN, zh-TW
Files:
src/app/[locale]/dashboard/_components/user/user-management-table.tsxmessages/ru/settings.jsonsrc/components/ui/chart.tsxmessages/ja/settings.jsonmessages/zh-TW/settings.jsonmessages/zh-CN/settings.jsonsrc/app/[locale]/settings/providers/_components/provider-manager.tsxmessages/en/settings.jsonsrc/app/[locale]/settings/providers/_components/forms/url-preview.tsxsrc/app/[locale]/settings/providers/_components/forms/provider-form.tsx
messages/**/*.json
📄 CodeRabbit inference engine (CLAUDE.md)
Support 5 locales via next-intl: en, ja, ru, zh-CN, zh-TW with messages in
messages/{locale}/*.jsonStore message translations in
messages/{locale}/*.jsonfiles
Files:
messages/ru/settings.jsonmessages/ja/settings.jsonmessages/zh-TW/settings.jsonmessages/zh-CN/settings.jsonmessages/en/settings.json
src/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use
lucide-reactfor icons instead of custom SVGs
Files:
src/components/ui/chart.tsx
src/components/ui/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Place UI components in
src/components/ui/directory (excluded from typecheck)
Files:
src/components/ui/chart.tsx
src/components/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/components/**/*.{tsx,jsx}: Use Tailwind CSS for styling, place utility classes close to JSX
Use shadcn/ui component library for high-quality, accessible UI components
Files:
src/components/ui/chart.tsx
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to messages/**/*.json : Support 5 locales via next-intl: en, ja, ru, zh-CN, zh-TW with messages in `messages/{locale}/*.json`
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to **/*.{tsx,json} : Use next-intl for internationalization with 5 locales: en, ja, ru, zh-CN, zh-TW
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to messages/**/*.json : Support 5 locales via next-intl: en, ja, ru, zh-CN, zh-TW with messages in `messages/{locale}/*.json`
Applied to files:
messages/zh-CN/settings.json
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to src/**/*provider*.ts : Set provider circuit breaker failure threshold, open duration, and half-open success threshold in configuration
Applied to files:
src/app/[locale]/settings/providers/_components/provider-manager.tsx
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to src/lib/circuit-breaker.ts : Circuit Breaker must implement state machine: CLOSED -> OPEN -> HALF_OPEN -> CLOSED with per-provider isolation and Redis persistence
Applied to files:
src/app/[locale]/settings/providers/_components/provider-manager.tsx
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to src/components/**/*.{ts,tsx} : Use `lucide-react` for icons instead of custom SVGs
Applied to files:
src/app/[locale]/settings/providers/_components/provider-manager.tsx
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to src/**/*.{tsx,jsx} : Use `lucide-react` for icons, no custom SVGs
Applied to files:
src/app/[locale]/settings/providers/_components/provider-manager.tsx
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to src/components/**/*.{tsx,jsx} : Use shadcn/ui component library for high-quality, accessible UI components
Applied to files:
src/app/[locale]/settings/providers/_components/provider-manager.tsxsrc/app/[locale]/settings/providers/_components/forms/provider-form.tsx
🧬 Code graph analysis (2)
src/app/[locale]/settings/providers/_components/forms/url-preview.tsx (1)
src/app/v1/_lib/url.ts (1)
previewProxyUrls(95-179)
src/app/[locale]/settings/providers/_components/forms/provider-form.tsx (1)
src/components/ui/dialog.tsx (1)
DialogDescription(122-122)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: pr-review
- GitHub Check: Greptile Review
- GitHub Check: pr-description
- GitHub Check: 🌐 API Tests
- GitHub Check: Docker Build Test
🔇 Additional comments (19)
src/app/[locale]/dashboard/_components/user/user-management-table.tsx (1)
262-265: 代码简化得很好!使用
rowVirtualizer.scrollToOffset(0)替代之前的 DOM 操作和requestAnimationFrame是一个很好的改进。这种方式更简洁、更易维护,并且直接使用虚拟化器的原生 API 更符合最佳实践。src/app/[locale]/settings/providers/_components/provider-manager.tsx (2)
4-4: 导入更改看起来正确。添加
useEffect导入用于下方新增的 effect,符合 React 使用规范。
73-78: 自动重置熔断器过滤器的实现正确。当没有处于熔断状态的供应商时(
circuitBrokenCount === 0),自动清除熔断器过滤器,避免显示空列表。依赖数组完整且正确,逻辑清晰。messages/zh-TW/settings.json (1)
1048-1048: 国际化文本添加正确。新增的
dialogDescription和groupTagTooLong字符串符合 next-intl 格式要求,占位符{max}的使用方式正确。根据 PR 上下文,这些消息支持供应商表单中的新验证逻辑(最大总长度 50 字符)和无障碍改进。基于 learnings:该项目通过 next-intl 支持 5 种语言环境(en, ja, ru, zh-CN, zh-TW)。
Also applies to: 1350-1350
src/app/[locale]/settings/providers/_components/forms/url-preview.tsx (1)
42-43: 空预览结果处理改进正确。新增的空对象检查(
Object.keys(result).length > 0)确保当previewProxyUrls返回空对象时,组件返回null而不是渲染空的预览 UI。这改善了边缘情况的处理,与 PR 目标中提到的"修复空结果的 URL 预览处理"一致。src/components/ui/chart.tsx (1)
63-67: 添加初始尺寸以防止布局偏移。在
ResponsiveContainer中添加initialDimension={{ width: 0, height: 1 }}是 recharts 的已知模式,用于在初始渲染时提供最小尺寸,避免布局闪烁和偏移。这与 PR 目标中提到的"防止仪表板布局故障"一致。messages/ru/settings.json (1)
1048-1048: 俄语国际化文本添加正确。新增的
dialogDescription和groupTagTooLong俄语翻译字符串格式正确,占位符使用方式符合 next-intl 规范。这些消息与其他语言环境文件(如 zh-TW)保持一致,共同支持供应商表单的验证和无障碍功能。基于 learnings:项目支持 5 种语言环境,所有语言环境文件应保持一致的键结构。
Also applies to: 1344-1344
messages/zh-CN/settings.json (2)
658-662: Provider 表单 dialogDescription 文案与英文语义一致,可以直接使用放在
providers.form下、紧挨着标题键,结构合理,简短说明“配置供应商信息及高级设置”,与 UI 中 DialogDescription 的用途吻合,无占位符风险。
980-987: groupTagTooLong 错误文案正确表达了总长度限制键路径
providers.form.errors.groupTagTooLong与前端验证逻辑匹配,文案“分组标签总长度不能超过 {max} 个字符”清晰准确,{max}占位符也与代码中的上限常量相符。messages/en/settings.json (2)
1150-1153: Provider 对话框描述英文文案清晰且位置正确作为
providers.form.dialogDescription紧跟 title,简洁说明对话框用途,符合无障碍/可读性预期,无占位符,风险很小。
1471-1477: groupTagTooLong 错误消息与前端约束语义一致错误键新增在
providers.form.errors下,提示“max {max} chars total”明确且与“按逗号拼接后的总长度限制”为 50 的实现契合,占位符{max}书写无误。messages/ja/settings.json (1)
1341-1347: groupTagTooLong 日文错误消息占位符与语义均正确错误键位于
providers.form.errors下,提示「プロバイダーグループが長すぎます(合計{max}文字まで)」准确表达“总长度不超过 {max} 字符”,{max}占位符与前端逻辑一致,无需调整。src/app/[locale]/settings/providers/_components/forms/provider-form.tsx (7)
22-22: 正确引入 DialogDescription 组件。此导入用于改善可访问性,符合使用 shadcn/ui 组件库的编码规范。
44-44: 良好实践:使用命名常量。定义
GROUP_TAG_MAX_TOTAL_LENGTH常量提高了代码可维护性,并与数据库 schema 中的 varchar(50) 约束保持一致。
300-306: 提交前验证逻辑正确。在提交前验证 group tags 的序列化总长度(逗号分隔),避免后端验证失败,提升用户体验。错误提示正确使用了国际化。
319-327: 实时验证提升用户体验。
handleGroupTagChange函数在用户添加标签时进行实时验证,防止超出长度限制,与提交时的验证逻辑保持一致。
541-541: 提升可访问性。添加
DialogDescription组件并使用sr-only类,为屏幕阅读器用户提供对话框描述,符合 WCAG 可访问性指南。
715-715: 正确应用新的验证处理器。将
onChange更新为使用handleGroupTagChange,确保在用户输入时进行实时验证。
724-724: 保持错误消息的一致性。使用
GROUP_TAG_MAX_TOTAL_LENGTH常量替换硬编码值,确保错误消息与验证逻辑保持一致。注意:如果onInvalidTag的too_long原因是针对单个标签长度的验证,这里的最大值可能需要调整。
| placeholder={t("sections.routing.scheduleParams.group.placeholder")} | ||
| disabled={isPending} | ||
| maxTagLength={50} | ||
| maxTagLength={GROUP_TAG_MAX_TOTAL_LENGTH} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find the provider-form.tsx file and relevant constants/components
find . -name "provider-form.tsx" -type f | head -5Repository: ding113/claude-code-hub
Length of output: 140
🏁 Script executed:
# Search for GROUP_TAG_MAX_TOTAL_LENGTH constant definition
rg -n "GROUP_TAG_MAX_TOTAL_LENGTH" --type=ts --type=tsx -B 2 -A 2Repository: ding113/claude-code-hub
Length of output: 94
🏁 Script executed:
# Find TagInput component
fd -name "*tag-input*" -type fRepository: ding113/claude-code-hub
Length of output: 297
🏁 Script executed:
# Search for GROUP_TAG_MAX_TOTAL_LENGTH constant definition
rg "GROUP_TAG_MAX_TOTAL_LENGTH" -B 2 -A 2Repository: ding113/claude-code-hub
Length of output: 3269
🏁 Script executed:
# Find TagInput component
fd "tag-input" -type fRepository: ding113/claude-code-hub
Length of output: 237
🏁 Script executed:
# Check the provider-form.tsx file for imports and relevant code around line 718
head -750 ./src/app/[locale]/settings/providers/_components/forms/provider-form.tsx | tail -100Repository: ding113/claude-code-hub
Length of output: 5234
🏁 Script executed:
# Find TagInput component
find . -name "*" -type f | xargs grep -l "export.*TagInput" | head -10Repository: ding113/claude-code-hub
Length of output: 137
🏁 Script executed:
# Search for TagInput prop definition or component
rg "maxTagLength" -B 5 -A 5 --max-count=20Repository: ding113/claude-code-hub
Length of output: 17009
🏁 Script executed:
# Look for TagInput component more broadly
rg "component.*TagInput|export.*function.*TagInput|const.*TagInput.*=" -A 20Repository: ding113/claude-code-hub
Length of output: 5866
🏁 Script executed:
# Get the complete TagInput component implementation
cat ./src/components/ui/tag-input.tsx | head -200Repository: ding113/claude-code-hub
Length of output: 6074
🏁 Script executed:
# Check how handleGroupTagChange is implemented in context
rg -B 10 "const handleGroupTagChange" src/app/[locale]/settings/providers/_components/forms/provider-form.tsxRepository: ding113/claude-code-hub
Length of output: 318
纠正 maxTagLength 属性的语义用途。
maxTagLength 属性在 TagInput 组件中用于验证单个标签的长度(见 validateBaseTag 中 if (tag.length > maxTagLength)),但此处被设置为 GROUP_TAG_MAX_TOTAL_LENGTH(用于限制所有标签逗号拼接后的总长度)。
这会导致语义混乱:maxTagLength={50} 表示每个单个标签可长达 50 字符,而不是所有标签的总长度为 50。如果 GROUP_TAG_MAX_TOTAL_LENGTH 在未来被修改(例如改为 200),则单个标签验证和总长度验证的含义将完全不符。
虽然 handleGroupTagChange 作为安全网能防止问题发生,但建议为 maxTagLength 设置更合理的值(如 25-30),使其在语义上与 GROUP_TAG_MAX_TOTAL_LENGTH 的限制条件相适配。
🤖 Prompt for AI Agents
In src/app/[locale]/settings/providers/_components/forms/provider-form.tsx
around line 718, maxTagLength is incorrectly set to GROUP_TAG_MAX_TOTAL_LENGTH
(which represents the total length of all tags combined) but TagInput uses
maxTagLength to validate each individual tag; change the prop to a sensible
per-tag limit (e.g. 25–30) by introducing or using a per-tag constant like
GROUP_SINGLE_TAG_MAX_LENGTH (or a literal such as 30) and keep
GROUP_TAG_MAX_TOTAL_LENGTH for the combined-length checks in
handleGroupTagChange so single-tag validation semantics and total-length
validation remain consistent.
Response to Code Review CommentsRe: Duplicate validation in
|
Summary
Admin panel UI improvements addressing provider form validation, dashboard layout stability, and circuit breaker filter UX.
Problem
Related Issues:
This PR addresses three categories of admin panel issues:
Solution
1. Provider Form Validation Enhancement
2. Dashboard Layout Stability
rowVirtualizer.scrollToOffset(0)instead of manual scroll + requestAnimationFrame (improves on fix(ui): improve admin dialogs UX and fix i18n issues #514's fix)initialDimension={{ width: 0, height: 1 }}to ResponsiveContainer to prevent layout shift on first render3. Circuit Breaker Filter Auto-Reset
circuitBrokenCountreaches 0Changes
Core Changes
provider-form.tsx(src/app/[locale]/settings/providers/_components/forms/provider-form.tsx:297-309, 319-325):handleGroupTagChange()DialogDescriptionfor WCAG complianceuser-management-table.tsx(src/app/[locale]/dashboard/_components/user/user-management-table.tsx:262-264):chart.tsx(src/components/ui/chart.tsx:63-66):initialDimensionprop to prevent layout shiftprovider-manager.tsx(src/app/[locale]/settings/providers/_components/provider-manager.tsx:73-79):url-preview.tsx(src/app/[locale]/settings/providers/_components/forms/url-preview.tsx:42-43):Supporting Changes
groupTagTooLonganddialogDescriptioni18n keys across 5 locales (en, ja, ru, zh-CN, zh-TW)Breaking Changes
None
Testing
Automated Tests
Manual Testing Checklist
Checklist
Description enhanced by Claude AI