refactor(frontend): split api-keys settings page into components - #1065
Conversation
There was a problem hiding this comment.
1 issue found across 10 files
Confidence score: 3/5
- In
frontend/src/components/settings/CredentialFormDialog.tsx, building dialog titles viat(...).replace('{provider}', ...)is brittle and can break when translation strings or placeholder formats change, leading to incorrect or untranslated add/edit credential titles in the UI; switch to the i18n library’s interpolation pattern (or equivalent typed params) before merging to de-risk localization regressions.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="frontend/src/components/settings/CredentialFormDialog.tsx">
<violation number="1" location="frontend/src/components/settings/CredentialFormDialog.tsx:123">
P2: Custom agent: **Known caveats**
The dialog titles for editing and adding credentials use manual string replacement on translated text: `t('apiKeys.editConfig').replace('{provider}', ...)`. This is fragile because if a locale defines the string without the literal `{provider}` placeholder, users will see raw placeholder text. Call `t()` with an interpolation argument (e.g., `t('apiKeys.editConfig', { provider: ... })`) so the i18n library resolves the substitution safely across all locales.</violation>
</file>
Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.
Re-trigger cubic
| <DialogHeader> | ||
| <DialogTitle> | ||
| {isEditing | ||
| ? t('apiKeys.editConfig').replace('{provider}', PROVIDER_DISPLAY_NAMES[provider] || provider) |
There was a problem hiding this comment.
P2: Custom agent: Known caveats
The dialog titles for editing and adding credentials use manual string replacement on translated text: t('apiKeys.editConfig').replace('{provider}', ...). This is fragile because if a locale defines the string without the literal {provider} placeholder, users will see raw placeholder text. Call t() with an interpolation argument (e.g., t('apiKeys.editConfig', { provider: ... })) so the i18n library resolves the substitution safely across all locales.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At frontend/src/components/settings/CredentialFormDialog.tsx, line 123:
<comment>The dialog titles for editing and adding credentials use manual string replacement on translated text: `t('apiKeys.editConfig').replace('{provider}', ...)`. This is fragile because if a locale defines the string without the literal `{provider}` placeholder, users will see raw placeholder text. Call `t()` with an interpolation argument (e.g., `t('apiKeys.editConfig', { provider: ... })`) so the i18n library resolves the substitution safely across all locales.</comment>
<file context>
@@ -0,0 +1,270 @@
+ <DialogHeader>
+ <DialogTitle>
+ {isEditing
+ ? t('apiKeys.editConfig').replace('{provider}', PROVIDER_DISPLAY_NAMES[provider] || provider)
+ : t('apiKeys.addConfig').replace('{provider}', PROVIDER_DISPLAY_NAMES[provider] || provider)}
+ </DialogTitle>
</file context>
e80c7d2 to
425c515
Compare
|
Valid catch, but pre-existing: the |
Summary
Move-only refactor of
frontend/src/app/(dashboard)/settings/api-keys/page.tsx(1,441 lines → 147 lines). No user-facing changes.Each of the six components that lived inside the page file now has its own file under
src/components/settings/(exported via the existing barrelindex.ts), and the provider config tables moved tosrc/lib/providers.tsx:CredentialFormDialog.tsxDiscoverModelsDialog.tsxDeleteCredentialDialog.tsxCredentialItem.tsxProviderSection.tsxDefaultModelSelectors.tsxsrc/lib/providers.tsx—ALL_PROVIDERS,PROVIDER_DISPLAY_NAMES,PROVIDER_MODALITIES,PROVIDER_DOCS,TYPE_ICONS,TYPE_COLORS,TYPE_COLOR_INACTIVE,TYPE_LABELS, and theModelTypealias (.tsxbecauseTYPE_ICONSholds JSX)Props, names and behavior are unchanged; prop types were only reshaped into
interface XPropsto match the existing convention incomponents/settings/(e.g.MigrationBanner).Intentional changes (the only two)
Selectblock was duplicated character-for-character between the primary and advanced grids inDefaultModelSelectors. It is now a singleDefaultModelSelectcomponent used by both call sites (advanced passesshowDescription).CredentialItemdefending against a Proxy-basedt()that no longer exists, along with the associatedtestModelLabel/deleteModelLabelcaching variables —t()is called directly now.Test follow-up
The backend cross-check test
tests/test_credential_provider_validation.py::TestSupportedProviderMatchesOtherSourcesOfTruth::test_matches_frontend_all_providers_listparses the frontend source for theALL_PROVIDERSarray; it now readsfrontend/src/lib/providers.tsxinstead of the old page file (same regex, new path).Verification
Inside
frontend/:npm run lint— 0 errors (6 pre-existing warnings, all in untouched files)npm run test— 12 files, 85 tests passednpm run build— production build succeedsBackend:
uv run pytest tests/— 403 passed.