♻️ refactor(channels): rebuild channel create/edit drawer with modular sections and improved form UX

Restructure the default-theme channel create/edit experience to align with
classic frontend behavior, modern form UX patterns, and the project's Base UI
design system.

Channel editor architecture:
- Split the monolithic channel mutate drawer into focused section components
  (basic, API access, auth, models, advanced) with shared drawer layout
  primitives
- Extract submission, toast handling, and react-query cache invalidation into
  `useChannelMutateForm`
- Add a dedicated loading skeleton for channel detail fetch during edit mode
- Remove the top-level configuration summary block per UX feedback

Form validation and data handling:
- Strengthen `channel-form` Zod schema with JSON, model mapping, status code
  mapping, Codex credential, and Vertex AI key refinements
- Move type-specific conditional validation into `superRefine`
- Normalize base URL formatting and tighten model mapping value validation

Model mapping editor:
- Add Visual/JSON tabbed editing with inline JSON and duplicate-key feedback
- Improve accessibility for icon-only actions and add model suggestion datalists

MultiSelect component:
- Replace the custom cmdk-based implementation with Base UI Combobox chips
- Align focus, border, ring, disabled, and invalid states with standard Input
  styling via `ComboboxChips`
- Preserve existing API (`options`, `selected`, `onChange`, `allowCreate`,
  `createLabel`) for all current callers
- Support inline custom value creation, comma/newline batch input, searchable
  options, portal-based dropdown positioning, and chip removal

Models & groups UX:
- Integrate manual custom model entry directly into the model MultiSelect
- Remove the separate manual model input/button block
- Keep selected-model count and existing model-mapping guardrail behavior

i18n:
- Add and sync translation keys for new editor sections, validation messages,
  model mapping UI, and MultiSelect empty/create labels across en, zh, fr, ja,
  ru, and vi
- Remove obsolete keys tied to the deprecated summary and manual model entry UI

Affected areas:
- `web/default/src/features/channels/components/drawers/`
- `web/default/src/features/channels/hooks/use-channel-mutate-form.ts`
- `web/default/src/features/channels/lib/channel-form.ts`
- `web/default/src/features/channels/lib/model-mapping-validation.ts`
- `web/default/src/features/channels/components/model-mapping-editor.tsx`
- `web/default/src/components/multi-select.tsx`
- `web/default/src/i18n/locales/*.json`
This commit is contained in:
t0ng7u
2026-05-26 01:22:49 +08:00
parent 583da45296
commit 3d850d38b6
19 changed files with 3465 additions and 2478 deletions
+33 -12
View File
@@ -37,7 +37,6 @@
"{{count}} IP(s)": "{{count}} IP(s)",
"{{count}} log entries removed.": "{{count}} log entries removed.",
"{{count}} minutes ago": "{{count}} minutes ago",
"{{count}} model(s)": "{{count}} model(s)",
"{{count}} models": "{{count}} models",
"{{count}} months ago": "{{count}} months ago",
"{{count}} override": "{{count}} override",
@@ -135,6 +134,7 @@
"Actual Model": "Actual Model",
"Actual Model:": "Actual Model:",
"Add": "Add",
"Add \"{{value}}\"": "Add \"{{value}}\"",
"Add {{title}}": "Add {{title}}",
"Add a group identifier to the auto assignment list.": "Add a group identifier to the auto assignment list.",
"Add a new API key by providing necessary info.": "Add a new API key by providing necessary info.",
@@ -152,7 +152,7 @@
"Add condition": "Add condition",
"Add Condition": "Add Condition",
"Add credits": "Add credits",
"Add custom model(s), comma-separated": "Add custom model(s), comma-separated",
"Add custom model \"{{value}}\"": "Add custom model \"{{value}}\"",
"Add discount tier": "Add discount tier",
"Add each model or tag you want to include.": "Add each model or tag you want to include.",
"Add FAQ": "Add FAQ",
@@ -164,6 +164,7 @@
"Add group rules": "Add group rules",
"Add Mapping": "Add Mapping",
"Add method": "Add method",
"Add missing models": "Add missing models",
"Add Mode": "Add Mode",
"Add model": "Add model",
"Add Model": "Add Model",
@@ -192,7 +193,6 @@
"Add User": "Add User",
"Add user group": "Add user group",
"Add your API keys, set up channels and configure access permissions": "Add your API keys, set up channels and configure access permissions",
"Added {{count}} custom model(s)": "Added {{count}} custom model(s)",
"Added {{count}} model(s)": "Added {{count}} model(s)",
"Added successfully": "Added successfully",
"Additional Conditions": "Additional Conditions",
@@ -201,8 +201,8 @@
"Additional Limit": "Additional Limit",
"Additional Limits": "Additional Limits",
"Additional metered capability": "Additional metered capability",
"Adjust Quota": "Adjust Quota",
"Adjust filters, then search to refresh the logs.": "Adjust filters, then search to refresh the logs.",
"Adjust Quota": "Adjust Quota",
"Adjust response formatting, prompt behavior, proxy, and upstream automation.": "Adjust response formatting, prompt behavior, proxy, and upstream automation.",
"Adjust the appearance and layout to suit your preferences.": "Adjust the appearance and layout to suit your preferences.",
"Admin": "Admin",
@@ -424,6 +424,11 @@
"Audio Tokens": "Audio Tokens",
"Auth configured": "Auth configured",
"Auth Style": "Auth Style",
"auth.resetPasswordConfirm.backToLogin": "Return to login",
"auth.resetPasswordConfirm.confirm": "Confirm reset password",
"auth.resetPasswordConfirm.description": "Confirm the reset request to generate a new password.",
"auth.resetPasswordConfirm.retry": "Retry ({{seconds}}s)",
"auth.resetPasswordConfirm.success": "Your password has been reset successfully",
"Authentication": "Authentication",
"Authenticator code": "Authenticator code",
"Authorization Endpoint": "Authorization Endpoint",
@@ -502,6 +507,7 @@
"Base Price": "Base Price",
"Base rate limit windows for this account.": "Base rate limit windows for this account.",
"Base URL": "Base URL",
"Base URL is required for this channel type": "Base URL is required for this channel type",
"Base URL of your Uptime Kuma instance": "Base URL of your Uptime Kuma instance",
"Basic Authentication": "Basic Authentication",
"Basic Configuration": "Basic Configuration",
@@ -759,8 +765,10 @@
"Codex": "Codex",
"Codex Account & Usage": "Codex Account & Usage",
"Codex Authorization": "Codex Authorization",
"Codex channels do not support batch creation": "Codex channels do not support batch creation",
"Codex channels use an OAuth JSON credential as the key.": "Codex channels use an OAuth JSON credential as the key.",
"Codex CLI Header Passthrough": "Codex CLI Header Passthrough",
"Codex credential must be a JSON object with access_token and account_id": "Codex credential must be a JSON object with access_token and account_id",
"Cohere": "Cohere",
"Collapse": "Collapse",
"Collapse All": "Collapse All",
@@ -867,8 +875,6 @@
"Confirm New Password": "Confirm New Password",
"Confirm password": "Confirm password",
"Confirm Payment": "Confirm Payment",
"auth.resetPasswordConfirm.confirm": "Confirm reset password",
"auth.resetPasswordConfirm.description": "Confirm the reset request to generate a new password.",
"Confirm Selection": "Confirm Selection",
"Confirm settings and finish setup": "Confirm settings and finish setup",
"confirm that I bear legal responsibility arising from deployment": "confirm that I bear legal responsibility arising from deployment",
@@ -999,6 +1005,7 @@
"Create, revoke, and audit API tokens.": "Create, revoke, and audit API tokens.",
"Created": "Created",
"Created At": "Created At",
"Creates a Pancake product in the saved store using this plans title and price. Requires Waffo Pancake to be fully configured in Payment settings first.": "Creates a Pancake product in the saved store using this plans title and price. Requires Waffo Pancake to be fully configured in Payment settings first.",
"Creating...": "Creating...",
"Creation failed": "Creation failed",
"Credential generated": "Credential generated",
@@ -1122,6 +1129,7 @@
"Delete invalid redemption codes": "Delete invalid redemption codes",
"Delete Invalid Redemption Codes?": "Delete Invalid Redemption Codes?",
"Delete logs": "Delete logs",
"Delete mapping": "Delete mapping",
"Delete Model": "Delete Model",
"Delete Models?": "Delete Models?",
"Delete Provider": "Delete Provider",
@@ -1249,6 +1257,8 @@
"Drawing task records": "Drawing task records",
"Duplicate": "Duplicate",
"Duplicate group names: {{names}}": "Duplicate group names: {{names}}",
"Duplicate source model mappings are not allowed": "Duplicate source model mappings are not allowed",
"Duplicate source model(s): {{models}}": "Duplicate source model(s): {{models}}",
"Duration": "Duration",
"Duration (hours)": "Duration (hours)",
"Duration Settings": "Duration Settings",
@@ -2177,6 +2187,7 @@
"Load template...": "Load template...",
"Loader": "Loader",
"Loading": "Loading",
"Loading channel details": "Loading channel details",
"Loading configuration": "Loading configuration",
"Loading content settings...": "Loading content settings...",
"Loading current models...": "Loading current models...",
@@ -2293,7 +2304,6 @@
"Minimum:": "Minimum:",
"Minor blips in the last 30 days": "Minor blips in the last 30 days",
"Mint a fresh pair below — or pick an existing one further down. Click Save when ready.": "Mint a fresh pair below — or pick an existing one further down. Click Save when ready.",
"Creates a Pancake product in the saved store using this plans title and price. Requires Waffo Pancake to be fully configured in Payment settings first.": "Creates a Pancake product in the saved store using this plans title and price. Requires Waffo Pancake to be fully configured in Payment settings first.",
"Minute": "Minute",
"minutes": "minutes",
"Missing code": "Missing code",
@@ -2324,7 +2334,9 @@
"Model Mapping": "Model Mapping",
"Model Mapping (JSON)": "Model Mapping (JSON)",
"Model Mapping must be a JSON object like": "Model Mapping must be a JSON object like",
"Model mapping must be a JSON object with string values": "Model mapping must be a JSON object with string values",
"Model mapping must be valid JSON": "Model mapping must be valid JSON",
"Model mapping values must be strings": "Model mapping values must be strings",
"Model name": "Model name",
"Model Name": "Model Name",
"Model Name *": "Model Name *",
@@ -2333,8 +2345,8 @@
"Model not found": "Model not found",
"Model performance metrics": "Model performance metrics",
"Model Price": "Model Price",
"Model Price Not Configured": "Model Price Not Configured",
"Model price is not configured. Please complete model pricing in settings.": "Model price is not configured. Please complete model pricing in settings.",
"Model Price Not Configured": "Model Price Not Configured",
"Model prices": "Model prices",
"Model prices reset successfully": "Model prices reset successfully",
"Model Pricing": "Model Pricing",
@@ -2532,6 +2544,7 @@
"No Logs Found": "No Logs Found",
"No mappings configured. Click \"Add Row\" to get started.": "No mappings configured. Click \"Add Row\" to get started.",
"No matches found": "No matches found",
"No matching items": "No matching items",
"No matching results": "No matching results",
"No matching rules": "No matching rules",
"No messages yet": "No messages yet",
@@ -2950,6 +2963,7 @@
"Please upload key file(s)": "Please upload key file(s)",
"Please wait a moment before trying again.": "Please wait a moment before trying again.",
"Please wait a moment, human check is initializing...": "Please wait a moment, human check is initializing...",
"Please wait before editing to avoid overwriting saved values.": "Please wait before editing to avoid overwriting saved values.",
"Policy JSON": "Policy JSON",
"Polling": "Polling",
"Polling mode requires Redis and memory cache, otherwise performance will be significantly degraded": "Polling mode requires Redis and memory cache, otherwise performance will be significantly degraded",
@@ -2983,6 +2997,7 @@
"Prepend to Start": "Prepend to Start",
"Prepend value to array / string / object start": "Prepend value to array / string / object start",
"Preserve the original field when applying this rule": "Preserve the original field when applying this rule",
"Preset groups": "Preset groups",
"Preset recharge amounts (JSON array)": "Preset recharge amounts (JSON array)",
"Preset recharge amounts displayed to users": "Preset recharge amounts displayed to users",
"Preset Template": "Preset Template",
@@ -3098,6 +3113,7 @@
"Querying...": "Querying...",
"Question": "Question",
"Queued": "Queued",
"Quick actions": "Quick actions",
"Quick insert common payment methods": "Quick insert common payment methods",
"Quick Range": "Quick Range",
"Quick Setup from Preset": "Quick Setup from Preset",
@@ -3219,6 +3235,7 @@
"Remaining:": "Remaining:",
"Remark": "Remark",
"Remove": "Remove",
"Remove {{value}}": "Remove {{value}}",
"Remove ${{amount}}": "Remove ${{amount}}",
"Remove all log entries created before the selected timestamp.": "Remove all log entries created before the selected timestamp.",
"Remove attachment": "Remove attachment",
@@ -3226,6 +3243,7 @@
"Remove Duplicates": "Remove Duplicates",
"Remove filter": "Remove filter",
"Remove functionResponse.id field": "Remove functionResponse.id field",
"Remove mapped targets": "Remove mapped targets",
"Remove Models": "Remove Models",
"Remove Passkey": "Remove Passkey",
"Remove Passkey?": "Remove Passkey?",
@@ -3329,7 +3347,6 @@
"Retain last N files": "Retain last N files",
"Retention days": "Retention days",
"Retry": "Retry",
"auth.resetPasswordConfirm.retry": "Retry ({{seconds}}s)",
"Retry Chain": "Retry Chain",
"Retry Suggestion": "Retry Suggestion",
"Retry Times": "Retry Times",
@@ -3339,7 +3356,6 @@
"Return Error": "Return Error",
"Return per-token log probabilities": "Return per-token log probabilities",
"Return to dashboard": "Return to dashboard",
"auth.resetPasswordConfirm.backToLogin": "Return to login",
"Return vector embeddings for inputs": "Return vector embeddings for inputs",
"Reveal API key": "Reveal API key",
"Reveal key": "Reveal key",
@@ -3491,7 +3507,6 @@
"Select all (filtered)": "Select all (filtered)",
"Select all models": "Select all models",
"Select All Visible": "Select All Visible",
"Select model {{model}}": "Select model {{model}}",
"Select an operation mode and enter the amount": "Select an operation mode and enter the amount",
"Select announcement type": "Select announcement type",
"Select at least one field to overwrite.": "Select at least one field to overwrite.",
@@ -3518,6 +3533,7 @@
"Select layout style": "Select layout style",
"Select locations": "Select locations",
"Select Model": "Select Model",
"Select model {{model}}": "Select model {{model}}",
"Select models (empty for allow all)": "Select models (empty for allow all)",
"Select models and apply to channel models list.": "Select models and apply to channel models list.",
"Select models or add custom ones": "Select models or add custom ones",
@@ -3547,6 +3563,7 @@
"Select vendor": "Select vendor",
"Selectable groups": "Selectable groups",
"selected": "selected",
"Selected {{count}}": "Selected {{count}}",
"selected channel(s). Leave empty to remove tag.": "selected channel(s). Leave empty to remove tag.",
"Selected conflicts were overwritten successfully.": "Selected conflicts were overwritten successfully.",
"Selected when creating a token and used as the default billing group for API calls.": "Selected when creating a token and used as the default billing group for API calls.",
@@ -3690,6 +3707,7 @@
"Status & Sync": "Status & Sync",
"Status Code": "Status Code",
"Status Code Mapping": "Status Code Mapping",
"Status code mapping must use valid HTTP status codes": "Status code mapping must use valid HTTP status codes",
"Status Page Slug": "Status Page Slug",
"Status short": "Status",
"Status:": "Status:",
@@ -3897,6 +3915,7 @@
"This action will permanently remove 2FA protection from your account.": "This action will permanently remove 2FA protection from your account.",
"This channel is not an Ollama channel.": "This channel is not an Ollama channel.",
"This channel type does not support fetching models": "This channel type does not support fetching models",
"This channel type requires additional configuration": "This channel type requires additional configuration",
"This confirmation unlocks payment, redemption code, subscription plan, and invitation reward features. Please read the statements carefully.": "This confirmation unlocks payment, redemption code, subscription plan, and invitation reward features. Please read the statements carefully.",
"This controls model request rate limiting. Web/API route throttling is configured by environment variables and may still return 429.": "This controls model request rate limiting. Web/API route throttling is configured by environment variables and may still return 429.",
"This data may be unreliable, use with caution": "This data may be unreliable, use with caution",
@@ -4215,6 +4234,7 @@
"Use external tools to extend capabilities": "Use external tools to extend capabilities",
"Use our unified OpenAI-compatible endpoint in your applications": "Use our unified OpenAI-compatible endpoint in your applications",
"Use Passkey to sign in without entering your password.": "Use Passkey to sign in without entering your password.",
"Use presets or upstream discovery to populate the model list faster.": "Use presets or upstream discovery to populate the model list faster.",
"Use secure connection when sending emails": "Use secure connection when sending emails",
"Use sidebar shortcut": "Use sidebar shortcut",
"Use the full-width table to scan prices, then select a row to edit it here.": "Use the full-width table to scan prices, then select a row to edit it here.",
@@ -4302,8 +4322,10 @@
"Verifying credentials and pulling stores from your Pancake account...": "Verifying credentials and pulling stores from your Pancake account...",
"Version Overrides": "Version Overrides",
"Vertex AI": "Vertex AI",
"Vertex AI API Key mode does not support batch creation": "Vertex AI API Key mode does not support batch creation",
"Vertex AI does not support functionResponse.id. Enable this to remove the field automatically.": "Vertex AI does not support functionResponse.id. Enable this to remove the field automatically.",
"Vertex AI Key Format": "Vertex AI Key Format",
"Vertex AI service account key must be valid JSON": "Vertex AI service account key must be valid JSON",
"Video": "Video",
"Video length in seconds": "Video length in seconds",
"Video Remix": "Video Remix",
@@ -4466,7 +4488,6 @@
"Your GitHub OAuth Client ID": "Your GitHub OAuth Client ID",
"Your GitHub OAuth Client Secret": "Your GitHub OAuth Client Secret",
"Your new backup codes are ready": "Your new backup codes are ready",
"auth.resetPasswordConfirm.success": "Your password has been reset successfully",
"Your Referral Link": "Your Referral Link",
"Your setup guide is collapsed so usage stays in focus.": "Your setup guide is collapsed so usage stays in focus.",
"Your system access token for API authentication. Keep it secure and don't share it with others.": "Your system access token for API authentication. Keep it secure and don't share it with others.",