Skip to content

Conversation

@zomp
Copy link

@zomp zomp commented Jan 19, 2026

Feature implementation probably finished. Tests not done yet. Waiting on tolgee/tolgee-platform#3246 merge.

Summary by CodeRabbit

  • New Features

    • Branch support added across UI and dev backend so translations can be requested and displayed per branch
    • Branch displayed in key/editor dialogs and appended to platform links
  • Bug Fixes

    • Added user alerts for "branch not found" and read-only mode operations
  • Behavior

    • Read-only mode exposed in dialog state and disables editing with appropriate messages
  • Tests

    • Verified branch is sent as a query parameter when loading records
  • Chores

    • Updated local development script to target the vanilla test app during development runs

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 19, 2026

Walkthrough

Threads an optional branch option from init state and types through plugins, query/provider, DevBackend requests, and KeyDialog UI; adds read-only handling and branch-not-found errors; updates a dev script and adds a test validating branch query propagation.

Changes

Cohort / File(s) Summary
Configuration & Scripts
package.json
Updated develop:web script to use --filter=@tolgee/vanilla-testapp... instead of @tolgee/web-testapp....
Types & Init State
packages/core/src/Controller/State/initState.ts, packages/core/src/types/plugin.ts
Added optional branch?: string to TolgeeOptionsInternal, BackendDevProps, and UiProps.
Plugins Controller
packages/core/src/Controller/Plugins/Plugins.ts
Extracts branch from initial options and passes it into UI initialization and backend dev-record request paths.
Dev Backend
packages/web/src/package/DevBackend.ts
getRecord now accepts projectId and branch, appends branch as a query param, and enforces projectId requirement for PAT keys.
Dialog Context / Query Provider
packages/web/src/package/ui/KeyDialog/dialogContext/index.ts, packages/web/src/package/ui/client/QueryProvider.tsx
Propagates branch into translations queries, create/update payloads, and linkToPlatform URL (/tree/{branch} when present); adds readOnly state exposed in dialog context and included in formDisabled logic.
KeyDialog UI
packages/web/src/package/ui/KeyDialog/KeyForm.tsx, packages/web/src/package/ui/KeyDialog/KeyDialog.tsx, packages/web/src/package/ui/KeyDialog/ErrorAlert.tsx
UI: pass branch to QueryProvider, render conditional Branch display in KeyForm, refactor some styled components, and add error cases for operation_not_permitted_in_read_only_mode and branch_not_found.
Tests
packages/web/src/package/__test__/fetch.apiUrl.test.ts
Added test verifying DevBackend includes branch and ns query params in fetch calls.

Sequence Diagram(s)

sequenceDiagram
  participant UI as UI (KeyDialog / KeyForm)
  participant DialogCtx as DialogContext
  participant QueryProv as QueryProvider
  participant DevBackend as DevBackend
  participant Core as Core/Plugins

  UI->>DialogCtx: open dialog (uiProps.branch?)
  DialogCtx->>QueryProv: set branchParam, readOnly=false
  UI->>QueryProv: request translations (namespace, branch)
  QueryProv->>DevBackend: getRecord(projectId?, branch)
  DevBackend->>Core: resolve project (apiKey or projectId)
  DevBackend->>DevBackend: append ?branch={branch}&ns={ns}
  DevBackend-->>QueryProv: return record or error
  alt branch_not_found or read-only error
    DevBackend-->>DialogCtx: error
    DialogCtx->>UI: set readOnly=true / show error
  else success
    QueryProv-->>UI: provide translations and branch info
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Poem

🐰 A ribbon of branch through code and UI I sew,
From init to backend the little value will go.
Read-only whispers when edits must wait,
Dialogs show branches and links navigate.
Hoppity hop — tests and scripts now know!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: implement branching support' directly and clearly describes the main change across all modified files—adding branch parameter support throughout the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@packages/web/src/package/ui/KeyDialog/dialogContext/index.ts`:
- Around line 275-281: The URL construction for linkToPlatform interpolates
branchParam directly into the path (see linkToPlatform, branchParam,
props.uiProps.apiUrl, scopesLoadable.data.projectId, props.keyName, selectedNs);
change the code to percent-encode branchParam with encodeURIComponent() when
embedding it into the path segment, or if your server rejects encoded slashes
move branchParam out of the path and append it as a query parameter (e.g.,
?branch=encodedBranch) so the branch value is safely transmitted.
🧹 Nitpick comments (1)
packages/web/src/package/DevBackend.ts (1)

35-37: Consider moving validation earlier.

The PAT key validation occurs after URL construction. Moving it before URL construction would avoid unnecessary work when validation fails.

♻️ Suggested reorder
 function createDevBackend(): BackendDevMiddleware {
   return {
     getRecord({
       apiUrl,
       apiKey,
       projectId,
       branch,
       language,
       namespace,
       filterTag,
       fetch,
     }) {
+      if (getApiKeyType(apiKey) === 'tgpat' && projectId === undefined) {
+        throw new Error("You need to specify 'projectId' when using PAT key");
+      }
+
       const pId = getProjectIdFromApiKey(apiKey) ?? projectId;
       let url: URL;
       // ... URL construction ...
-
-      if (getApiKeyType(apiKey) === 'tgpat' && projectId === undefined) {
-        throw new Error("You need to specify 'projectId' when using PAT key");
-      }

@zomp zomp force-pushed the janmolnar/branching branch from 4e4fcec to 8ad0508 Compare January 20, 2026 21:58
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@packages/web/src/package/ui/KeyDialog/dialogContext/index.ts`:
- Around line 399-405: The handler stores read-only state via setReadOnly(true)
but still calls setSubmitError(e), causing duplicate ErrorAlert and the
read-only banner; change the logic in the error handling (the block that checks
e instanceof HttpError && e.code ===
'operation_not_permitted_in_read_only_mode') to setReadOnly(true) and skip
calling setSubmitError for that specific error code so only the read-only
info/banner is shown; retain setSubmitError(e) for all other errors.

Comment on lines +399 to 405
if (
e instanceof HttpError &&
e.code === 'operation_not_permitted_in_read_only_mode'
) {
setReadOnly(true);
}
setSubmitError(e);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Avoid duplicate alerts for read-only submit errors.
When the read-only error occurs, readOnly is set but submitError is still stored, which can lead to a second ErrorAlert in the UI. Consider skipping submitError for this case so only the read-only info banner shows.

💡 Suggested fix
-        if (
-          e instanceof HttpError &&
-          e.code === 'operation_not_permitted_in_read_only_mode'
-        ) {
-          setReadOnly(true);
-        }
-        setSubmitError(e);
+        if (
+          e instanceof HttpError &&
+          e.code === 'operation_not_permitted_in_read_only_mode'
+        ) {
+          setReadOnly(true);
+          setSubmitError(undefined);
+        } else {
+          setSubmitError(e);
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (
e instanceof HttpError &&
e.code === 'operation_not_permitted_in_read_only_mode'
) {
setReadOnly(true);
}
setSubmitError(e);
if (
e instanceof HttpError &&
e.code === 'operation_not_permitted_in_read_only_mode'
) {
setReadOnly(true);
setSubmitError(undefined);
} else {
setSubmitError(e);
}
🤖 Prompt for AI Agents
In `@packages/web/src/package/ui/KeyDialog/dialogContext/index.ts` around lines
399 - 405, The handler stores read-only state via setReadOnly(true) but still
calls setSubmitError(e), causing duplicate ErrorAlert and the read-only banner;
change the logic in the error handling (the block that checks e instanceof
HttpError && e.code === 'operation_not_permitted_in_read_only_mode') to
setReadOnly(true) and skip calling setSubmitError for that specific error code
so only the read-only info/banner is shown; retain setSubmitError(e) for all
other errors.

@zomp zomp marked this pull request as ready for review January 26, 2026 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants