Add an opt-in card view to the shared data-table stack (DataTablePage),
toggled via a segmented control in the toolbar with per-table localStorage
persistence. Cards render generically from column meta by default, with an
optional renderCard slot. Defaults to table-only so existing pages are
unchanged.
Wire it into the channels page with a bespoke ChannelCard that reuses every
column's cell renderer, preserving all table information and interactions
(selection, inline priority/weight, balance refresh, status, actions, tag
expand).
- apply table-level truncation only to primitive text cells.
- let tables expand to content width with horizontal scrolling to avoid column overlap.
- update model badges to show full model names on one line.
TanStack row objects may keep a stable reference while their selection
state changes, so reading row.getIsSelected() inside the React.memo
comparator could miss updates. Capture isSelected as an explicit prop
and compare it instead, ensuring rows re-render when selection toggles.
* fix(ui): prevent table cell text overflow
- add default truncation with hover details for text cells in shared and static data tables to prevent content from spilling into adjacent columns.
- adjust API key group, model, and IP restriction columns to fix badge overlap and left alignment drift.
- reuse a shared truncated cell component and add width constraints for composite badge cells.
* fix(table): prevent badge content from overflowing columns
- make table text and badge cells shrink within constrained columns so long values truncate instead of bleeding into adjacent cells.
- add a shared BadgeCell wrapper to keep badge alignment consistent across API keys and other list pages.
- update affected list views to use constrained wrappers for group, provider, pricing, OAuth, and API info values.
* perf(table): use percentage-based column widths
- compute each column's width as a percentage of total column size instead of a fixed pixel value, letting the colgroup scale fluidly with the table container.
* perf(data-table): reduce unnecessary re-renders across table components
- stabilize commitSearchValue in toolbar by reading table/searchKey via refs, eliminating recreation on every parent render
- store onColumnFiltersChange in a ref so debounce effect is not reset when the caller passes a new function reference each render
- wrap DataTableRow in React.memo with a custom comparator that ignores getColumnClassName reference churn
- memoize selectedValues Set in DataTableFacetedFilter and wrap with React.memo to prevent rerenders on unrelated state changes
- cache cell meta reads in CompactRow and FallbackRow to a single pass per row; memoize hasCompactMeta in MobileCardList
- memoize hideable columns list in DataTableViewOptions and colSpan in DataTableView
- remove tableClassName and colgroup from scroll-sync effect deps; cache toolbar button NodeList via useLayoutEffect to avoid per-keydown DOM queries
* perf(data-table): replace scroll-sync split header with CSS sticky
- remove JS scroll-sync effect and event listener between split header and body containers.
- merge separate header/body tables into a single scrollable table element, reducing DOM complexity.
- apply CSS sticky positioning to the header for a simpler, hardware-accelerated freeze effect.
* fix(data-table): replace opacity muted colors with color-mix
- switch from bg-muted/50 and bg-muted/30 to color-mix(in oklch) to produce opaque blended backgrounds that prevent scroll content from showing through pinned cells.
- expose --table-header-bg CSS variable so pinned header cells inherit the exact same computed color as the thead background.
- add group class to TableRow to enable group-hover selectors on pinned cell styles.
* feat(data-table): support column pinning via meta.pinned
- add pinned?: 'left' | 'right' to ColumnMeta so pinning is declared once in the column definition and applies to both header and body automatically
- DataTableView derives pinnedColumns from meta.pinned at runtime, merged with any explicit pinnedColumns prop; explicit entries take precedence
- add header and meta.pinned: 'right' to all actions columns across channels, users, api-keys, redemption-codes, models, deployments, and subscriptions tables
* style(row-actions): align action buttons to leading edge of column
* refactor(data-table): extract BadgeListCell and centralize badge alignment
- add BadgeListCell component to data-table for badge lists with overflow tooltip, replacing duplicated renderLimitedItems helpers in channels, models, and pricing columns
- move StatusBadge -ml-1.5 alignment into the component itself via a table-cell context selector, so callers no longer need manual offset wrappers
- remove the table-cell-level -ml-1.5 selector from TableCell now that alignment is handled by StatusBadge directly
* style(row-actions): offset action buttons to align with column header text
* refactor(data-table): consolidate mobile meta into ColumnMeta declaration
- move mobileTitle, mobileBadge, mobileHidden into the global ColumnMeta augmentation so the type is shared across the project
- remove the local MobileColumnMeta interface and getCellMeta helper from mobile-card-list.tsx
- direct col.columnDef.meta access is now type-safe without explicit casting
* refactor(data-table): simplify column header and meta config
- auto-render string `header` values via DataTableColumnHeader so sortable/non-sortable columns work without boilerplate function wrappers
- promote mobile layout hints (mobileTitle, mobileBadge, mobileHidden) into the global ColumnMeta type, removing the local MobileColumnMeta cast in mobile-card-list
- migrate all column files from `meta: { label }` to top-level `header: t('...')`, cutting ~180 lines of repetitive template code
- ViewOptions and MobileCardList label resolution now reads string header first, then meta.label as fallback
* feat(status-badge): add text and underline display types
- introduce StatusBadgeType ('badge' | 'text' | 'underline') and StatusBadgeTypeContext so ancestors can override rendering without touching call sites
- mobile card field rows now use the text type via context, showing badges as plain colored text instead of pills
- ProviderBadge gains data-slot='provider-badge' to enable targeted CSS resets in compact layouts
- replace the implicit [[data-slot=table-cell]>&]:-ml-1.5 rule with explicit -ml-1.5 at each column call site
* refactor(data-table): simplify table filtering internals
- derive toolbar search state from the active table filter to avoid render-time ref writes.
- extract faceted filter selection updates into a pure helper for clearer single and multi-select behavior.
- split pinned column resolution into focused helpers so explicit and meta pins merge predictably.
Co-authored-by: t0ng7u <dev@aiass.cc>
* refactor(web): centralize data table implementation
- route all TanStack table setup through a shared data-table hook to remove repeated state and row model wiring.
- move table rendering, static table wrappers, empty states, and primitive exports behind the data-table module.
- update feature tables and configuration editors to share the same table UX while preserving their existing workflows.
* refactor(web): trim data table public API
- remove unused data-table exports and dead static table helper types.
- keep internal table header, skeleton, empty state, and faceted filter helpers private to the data-table module.
- route feature imports through the data-table barrel to avoid subpath coupling.
* refactor(web): unify table rendering components
- centralize static table headers, bodies, empty states, and shared class names behind the data-table package.
- migrate settings, pricing, channel, key, subscription, and model tables to the shared table APIs.
- remove data-table exports for low-level table primitives so feature code uses one supported abstraction.
* perf(web): keep list tables fixed within page content
- make shared data table pages fill available height and scroll row data inside the table body.
- add a fixed content layout mode so selected list pages avoid page-level scrolling.
- apply the fixed table behavior to keys, logs, channels, models, users, redemptions, and subscriptions.
* perf(web): refine table pagination controls
- show total row counts instead of redundant page range text.
- tighten visible page buttons so pagination fits constrained table widths.
- align pagination controls and tune text hierarchy for clearer scanning.
* perf(web): stabilize model pricing table columns
- keep model pricing columns at fixed widths so headers do not collapse in narrow layouts.
- truncate long model names and pricing summaries within their cells instead of squeezing adjacent columns.
* refactor(web): simplify data table rendering internals
- split table body rendering into focused helpers for loading, empty, and row states.
- extract static table row and cell class resolution to reduce branching in the main component.
- reuse a single pagination page-size option list to avoid duplicated constants.
* perf(pricing): reduce dynamic pricing table render work
- reuse dynamic pricing field metadata instead of rebuilding it inside table columns.
- precompute formatted dynamic prices per tier and group to avoid repeated entry mapping for each cell.
- simplify select option construction in related dialogs while preserving the same choices.
* refactor(web): streamline pricing table rendering
- reuse translated endpoint select options between trigger data and menu items.
- precompute dynamic pricing maps per group so table cells only resolve formatted values.
- add local dynamic pricing type aliases to keep helper signatures readable.
* refactor(web): merge pricing table imports
* refactor(web): merge upstream ratio table imports
* refactor(web): merge channel selector table imports
* refactor(web): simplify tiered pricing select items
* refactor(web): reuse model ratio row state
* refactor(web): rely on table view row defaults
* refactor(web): reuse pagination state values
* refactor(web): hoist pagination size select items
* refactor(web): clarify static table body rows
* refactor(web): extract table page pagination rendering
* fix(web): remove direct hast type dependency
- rely on Shiki transformer contextual typing for line nodes.
- allow frontend typecheck to pass without an undeclared hast package.
* refactor(web): trim data table hook return API
- return only the TanStack table instance from useDataTable.
- keep internal state handling private because callers do not consume it directly.
* refactor(web): keep static table empty row private
- stop exporting the internal StaticDataTableEmptyRow helper.
- keep the public static table API focused on the table component and column type.
* refactor(web): hide data table view props from barrel
* refactor(web): remove stale long text lint override
* fix(web): keep pinned table columns opaque
- apply pinned column background classes after custom column classes.
- use an opaque hover background so scrolled content cannot show through fixed cells.
* refactor(data-table): organize shared table components
- group table primitives, page composition, toolbar controls, static tables, and hooks by responsibility.
- split shared view types, row rendering, header rendering, and pinned-column styling out of the main table view.
- keep the public data-table barrel stable while documenting the new ownership boundaries.
* fix(web): stabilize split table column sizing
- derive default colgroup widths from visible columns when split headers or header sizing are enabled.
- apply a fixed table layout with computed minimum width so header and body columns stay aligned.
- keep split-header containers from leaking horizontal overflow and avoid extra pinned-column borders.
* fix(web): set stable table utility column widths
- assign fixed widths to selection columns so shared colgroup sizing keeps checkbox cells compact.
- size id columns in redemption and user tables to keep split headers aligned with body rows.
* fix(web): align model metadata icon cells
- render compact provider avatars in the metadata icon column instead of wide wordmarks.
- position icons in a fixed-size wrapper so they line up with the existing icon header alignment.
* fix(status-badge): hide status dot by default
* fix(web): prevent user invite info overlap
- give the invite info and created-at columns explicit widths so table sizing reserves enough space.
- allow invite badges to wrap within the cell instead of spilling into adjacent columns.
* perf(data-table): cache pinned column class resolution
- reuse the pinned column lookup while table props stay stable to reduce repeated per-render work.
- share the resolved column class handler across unified and split-header table layouts.
- localize page-number screen reader labels so pagination remains accessible in every locale.
* refactor(data-table): tighten static table modes
- make StaticDataTable distinguish data-driven and children-only usage through explicit prop shapes.
- remove unsupported columns-without-data fallback after confirming no repository callers rely on it.
- default manual table modes away from unused local row models to reduce repeated table work.
* fix(data-table): make pinned edit column opaque
- use an opaque muted background for the active action column so sticky cells do not reveal scrolled content underneath.
* fix(data-table): prevent narrow column overlap
- apply stable header sizing to remaining desktop data table pages so constrained layouts scroll instead of compressing cells.
- add explicit widths for key, quota, badge, and timestamp columns that contain fixed-format content.
- constrain masked values and timestamp cells with truncation to keep content inside its assigned column.
* fix(table): align table cell content with headers
- remove extra inline padding from masked table text buttons so values start at the cell edge.
- tag status badges and offset leading badges inside table cells to match header text alignment.
* fix(table): prevent admin list column overflow
- widen redemption and subscription table columns so masked codes, timestamps, and localized headers fit.
- localize subscription ID headers and add Received amount translations across supported locales.
* fix(provider-badge): unify provider icon spacing
- add a shared provider badge component for icon and status label layout.
- reuse it in channel type and model vendor columns so OpenAI icons align consistently.
- migrate frontend dialogs to the shared footer API so actions stay separated from scrollable body content.
- tune dialog dimensions for model analytics, prefill groups, billing history, channel model sync, and related workflows.
- update channel terminology and dialog action translations across supported locales.
- introduce a reusable dialog component for consistent header, body, and footer layout.
- support per-dialog sizing, trigger rendering, initial focus, and close button controls.
- preserve base dialog open and close motion classes while allowing content-specific styling.
- introduce a shared themed JSON editor with line numbers, formatting, status feedback, and keyboard editing helpers.
- use the shared editor in model pricing JSON mode so pricing maps get consistent editor behavior.
- localize structured JSON validation messages so parse errors avoid browser-specific English text.
- scope validation queries with a form root id so feedback stays inside the submitted form.
- scroll to the earliest invalid control or message and move focus without fighting scroll position.
- avoid handling the same failed submit twice to keep retries from jumping unexpectedly.
Implement the Simple Large-font theme preset and xl font scale options to enhance interface accessibility. Remove status indicator dots from channel badges in logs to keep the table layout visual and clean.
System settings forms that used flat dotted API keys (e.g.
`performance_setting.monitor_cpu_threshold`) with React Hook Form were
broken: RHF stores dotted paths as nested objects on update, while dirty
checks and submit comparisons still read flat keys from defaults. Users
could edit values but always saw "No changes to save".
Refactor affected sections to use nested Zod schemas and default values
for RHF, with explicit helpers to convert between nested form state and
flat API keys. Track a normalized baseline in refs for accurate change
detection and post-save resets.
Add `safeNumberFieldProps` to prevent native `<input type="number">`
from writing NaN into form state when cleared. NaN caused Zod validation
to fail silently and made the save button appear unresponsive. The
helper ignores non-finite updates so controlled inputs snap back to the
last valid value, matching legacy Semi InputNumber behavior.
Sections refactored for dotted-key handling:
- maintenance/performance-section
- models/grok-settings-card
- auth/passkey-section
- auth/oauth-section
- auth/section-registry (pass attachment_preference raw; normalize in section)
Sections migrated to safeNumberFieldProps:
- maintenance/performance-section
- models/grok-settings-card
- integrations/monitoring-settings-section
- integrations/payment-settings-section
- integrations/creem-product-dialog
- general/pricing-section (USD exchange rate)
- general/system-behavior-section
- content/dashboard-section
Optional numeric fields (e.g. custom currency exchange rate) keep their
existing empty-to-undefined semantics and are intentionally unchanged.
- Restore StatusBadge sizes to h-5/text-xs (sm, md) and h-6/text-xs (lg).
- Restore classic textColorMap coloring and status indicator dot.
- Embed channel type icon directly inside StatusBadge as custom children.
- Re-align status badge colors: danger for manual disabled, warning for auto disabled.
Introduce a switchable Anthropic-inspired color preset and a new Font customization axis so users can adopt the editorial serif look across the entire UI, including sidebar navigation, tabs, form controls, buttons, and table headers.
Theme preset
Add anthropic to the theme preset registry with warm cream canvas, slate foreground, and clay/coral accent tokens for light and dark modes
Define explicit surface colors for the Anthropic preset instead of relying on the semantic surface bridge
Exclude anthropic from the primary-color surface bridge so bespoke warm neutrals are not overridden by accent-tinted mixes
Typography system
Add @fontsource-variable/lora and a global --font-serif token with CJK serif fallbacks (Noto Serif SC, Source Han Serif, Songti SC, etc.)
Introduce a --font-body token and drive <body> font-family from it
Add a Font axis (default | sans | serif) parallel to radius/scale
Resolve font: 'default' against preset defaults (anthropic → serif)
Persist font preference via cookie and apply data-theme-font on <body>
Apply serif OpenType features (kern, liga, calt, tnum) and heading display tuning when serif is active
Remove per-component sans opt-outs so serif inherits through sidebar, tabs, inputs, buttons, badges, and table headers via natural CSS cascade
Keep monospace contexts unchanged via Tailwind preflight and .font-mono
UI and i18n
Add Font selector to the theme config drawer (Auto / Sans / Serif)
Add "Font" and "Select body font" translations for en, zh, fr, ja, ru, vi
Misc
Tighten group and status badge sizing for better balance with serif text
Restructure the default-theme channel create/edit experience to match classic
frontend behavior, improve form UX, and align with 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
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 for all current callers (`options`, `selected`,
`onChange`, `allowCreate`, `createLabel`)
- Support inline custom value creation and comma/newline batch input
- Limit visible chips with a compact "+N more" overflow summary via
`maxVisibleChips` (8 in the channel editor)
- Anchor the dropdown to the full chips container via `useComboboxAnchor` so
the popup matches input width and long model names are no longer truncated
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 badge and existing model-mapping guardrail behavior
i18n:
- Add and sync translation keys for section descriptions, validation messages,
model mapping UI, and MultiSelect labels across en, zh, fr, ja, ru, and vi
- Fix missing translations for "Name, provider type, and availability.",
"Endpoint, provider-specific settings, and credentials.", and "Published
models, groups, and model remapping rules."
- Remove obsolete keys tied to the deprecated summary and manual model entry UI
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`
Refactor the usage log filter toolbar into a shared reusable component for common, drawing, and task logs. Optimize desktop filters with a responsive grid, move secondary filters into a mobile drawer, standardize filter typography, remove redundant filter icons, and add the missing i18n translations for the new drawer description.
Resolve verified V1 frontend feedback by improving channel workflows, auth behavior, API key interactions, user filtering, layout persistence, subscription quota handling, i18n text, pricing metadata, and stale frontend cache recovery.
- Add a global frontend cache version cleanup to prevent old frontend localStorage from causing page errors after upgrades.
- Fix channel copy refresh, model mapping input focus loss, create-channel fetch-model title state, upstream model update confirmation, and batch test toast behavior.
- Respect password login settings and improve Turnstile, forgot-password, registration, and invite-link flows.
- Make user role/status filtering server-side and preserve table page size in URLs.
- Improve API key edit validation feedback and prefetch real keys for reliable copy actions.
- Fix rankings access fail-open behavior, double scrollbars, subscription received amount conversion/display, token i18n wording, model deletion confirmation grammar, and Claude pricing context inference.
- Add clearer Playground model/group loading errors.
Validation:
- bun run typecheck
- bun run i18n:sync
- gofmt on modified Go files
- go test ./controller ./model -run '^$'
Upgrade all web/default dependencies to their latest versions and refresh the Bun lockfile. Add dependency overrides for vulnerable transitive packages so bun audit reports no known vulnerabilities.
Update TypeScript configuration for TypeScript 6 by removing deprecated baseUrl usage and explicitly enabling Node types where needed. Adapt the calendar component to react-day-picker v10 by replacing the removed table class key with month_grid.
Validation:
- bun outdated: no outdated dependencies
- bun audit: no vulnerabilities found
- bun run typecheck: passed
- bun run build: passed
Redesign the system settings interface to align with the rest of the console experience by using fixed header actions, removing redundant subtitles, respecting global content width, and standardizing responsive form layouts.
Introduce reusable settings layout primitives for forms, switch rows, grouped controls, nested control sections, title status indicators, and page action portals. Replace duplicated card-style switch markup with explicit compact components, improve nested switch readability, and reduce visual noise across authentication, billing, content, integrations, maintenance, models, and request-limit settings.
Also complete missing i18n translations, remove obsolete subtitle translation keys, refine i18n sync reporting, fix sidebar truncation for long labels, and verify the frontend with type checking and lint diagnostics.
Replace the ad-hoc "workspace" abstraction with a focused, URL-driven
"sidebar view" registry that implements the modern Vercel / Cloudflare
drill-in pattern: clicking a top-level entry (e.g. System Settings)
swaps the sidebar to a contextual workspace, with a `← Back to
Dashboard` affordance, instead of stacking sub-navigation in the root.
Architecture
------------
- types.ts
+ SidebarView — declarative nested view config
(id, pathPattern, parent, getNavGroups)
+ SidebarViewParent — back-navigation descriptor
+ ResolvedSidebarView — { key, view, navGroups } returned by hook
+ SidebarData — slimmed to { navGroups } only
- Workspace — removed (logo/plan never rendered)
- lib/sidebar-view-registry.ts (new, replaces workspace-registry.ts)
+ SIDEBAR_VIEWS array — single source of truth for nested views
+ resolveSidebarView(pathname)
+ getNavGroupsForPath(pathname, t) — back-compat helper for the
command palette
- config/system-settings.config.ts
Refactored to export a single SYSTEM_SETTINGS_VIEW (SidebarView)
with parent `/dashboard/overview` + label `Back to Dashboard`.
- components/sidebar-view-header.tsx (new)
Renders only the back affordance (chevron + label). Uses the
default SidebarMenuButton size so its typography matches the
nav items below; collapses gracefully into icon mode via the
existing tooltip behavior. The redundant "title + icon" row was
removed — workspace context is already carried by the nav groups.
- hooks/use-sidebar-view.ts (new)
Encapsulates view resolution and root-nav filtering:
· matched view → returns its nav groups verbatim (route-level
beforeLoad guards already enforce access);
· no match → returns root nav groups, narrowed by user
role (admin gate) and useSidebarConfig
(admin × user sidebar_modules overlay).
- components/app-sidebar.tsx
Now a thin presentation layer: reads { key, view, navGroups }
from useSidebarView() and orchestrates the view transition via
AnimatePresence + MOTION_VARIANTS.sidebarSlide (respects
prefers-reduced-motion). No logic, no role checks, no path
matching — those live in the hook.
- components/command-menu.tsx
Switched to the new getNavGroupsForPath() API; behavior preserved.
Cleanup
-------
- Deleted layout/context/workspace-context.tsx (zero consumers).
- Deleted layout/lib/workspace-registry.ts and its
workspace-registry.example.ts companion (over-abstracted: name/id
metadata, isInWorkspace / getAllWorkspaces / WORKSPACE_IDS were
registered but never read).
- Removed `workspaces` field from useSidebarData (never consumed
after the top-switcher was dropped).
- Dropped WorkspaceProvider from authenticated-layout.tsx.
- Trimmed dead `Manage and configure` translation key from all six
locale files and from static-keys.ts.
i18n
----
Added the `Back to Dashboard` key to en, zh, fr, ja, ru, vi, and
registered it in static-keys.ts under "Sidebar views".
Verification
------------
- bun run typecheck: passes
- Lint: no new warnings/errors on the touched files
- Adding a new drill-in workspace now only requires registering a
SidebarView in SIDEBAR_VIEWS — no changes to AppSidebar required.
The faceted filter popover used a fixed width of 200px, which clipped
long option labels (e.g. user-defined channel group names) and forced
the truncated text to be unreadable without leaving a way to see the
full value.
- Switch PopoverContent from `w-[200px]` to
`min-w-[200px] max-w-[360px]` so short option lists keep their
current footprint while long labels can expand up to 360px before
the existing truncate kicks in.
- Add `title={t(option.label)}` on the truncated label span so users
can still hover to see the full text on extreme cases.
Closes#4905
* chore(dev): add local setup state reset target
- add a reset-setup make target to clear setup records, root users, and related options.
- support both docker dev PostgreSQL and local SQLite development databases.
- restart the docker dev backend so setup status is recalculated after reset.
* fix(chat): prevent preset menu text overflow
- add truncation layout for chat preset names to keep long labels inside the sidebar menu.
- prevent loading and external-link icons from shrinking in constrained menu rows.
* fix(i18n): translate dashboard granularity options
- call t() for granularity option labels in dashboard system settings.
- keep localized text consistent between the select trigger and dropdown items.
* chore(dev): add backend dev service rebuild target
- add a dev-api-rebuild make target to rebuild and start the docker backend service.
- reuse DEV_COMPOSE_FILE and DEV_BACKEND_SERVICE variables to avoid repeated compose config literals.
* fix(i18n): align interface language option labels
- add shared interface language options to keep display names consistent.
- reuse the shared options in the header switcher and profile preferences.
- normalize language codes so zh-CN and zh_CN resolve to Simplified Chinese.
* fix(i18n): add missing frontend translation keys
- route channel key prompts, form validation messages, and channel fallback text through i18n.
- add missing translations across six locales for channels, rankings, billing, and logs.
- update i18n sync reports so literal t() keys are present in the base locale.
- Add singleSelect to status/role filters in API keys, users, and redemptions tables (#4880)
- Fix affiliate link 404 by changing /register to /sign-up (#4893)
- Open FetchModelsDialog in channel creation mode via customFetcher prop (#4817)
- Add TruncatedText component with tooltip for long channel names, token names, and usernames (#4877)
- Elevate forgot-password link z-index to prevent label click interception (#4898)