Skip to content

fix(gui): stop the rollback journal from flooding the Integrations page - #3050

Open
lidge-jun wants to merge 1 commit into
devfrom
codex/integrations-rollback-history
Open

fix(gui): stop the rollback journal from flooding the Integrations page#3050
lidge-jun wants to merge 1 commit into
devfrom
codex/integrations-rollback-history

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Summary

Stops the rollback journal from swamping both Integrations surfaces.

The overview rendered the global journal and every client tab rendered the same journal filtered, and both mapped the entire response into individually bordered rows. The route caps at 50 rows (listOperations default) and keeps 10 restorable snapshots per client, so a user with a few dozen toggles behind them got fifty loose strips stacked under the real controls, twice — and most of them could not be undone anyway.

Three changes fix it:

  • The newest row stays visible, because it is the one a user reaches for after a mistake. The rest collapse behind a disclosure and reveal six at a time, matching LANE_PAGE in claude-desktop-lane.ts.
  • Rows share one container boundary with border-top separators instead of a border and radius each. That texture was the actual visual complaint.
  • No total is displayed. The payload carries neither a total nor a hasMore, so any number shown would be a claim the response cannot support.

The older rows are folded rather than dropped: the overview is the only surface showing one chronology across clients, since each client tab reads its own filtered journal.

Three defects in the same rendering path are fixed alongside it:

  • Cold, failed and empty rendered identically, because data ?? [] collapses all three into an empty array and the empty state followed. A user whose journal request failed was told they had no history. They now get a skeleton while cold, an error with a retry while failed, and the empty state only when the response really is empty.
  • RestoreDialog rendered <dialog open>, which is non-modal: the page behind a confirmation that is about to overwrite a config file stayed focusable and in the accessibility tree, and an inline full-screen style block existed only to fake the backdrop the modal state provides for free. It now uses ConsequenceDialog's lifecycle — showModal(), backdrop dismiss, role="document", focus restore.
  • The overview heading outline went h2 straight to h4, so all fifteen card titles were an orphan level and the rollback section sat at the same depth as things it is not part of. An h3 now owns the client catalog and rollback is its sibling: H2:Integrations → H3:Clients → H4:…cards… → H3:Rollback center, verified in the live DOM.

Collapsed, with a 30-row journal seeded on a live proxy:

Rollback collapsed

Expanded:

Rollback expanded

At 390px:

Rollback at 390px

Verification

  • bun run typecheck — clean
  • bun run lint:gui — clean
  • cd gui && bun test tests/integrations-rollback-history.test.tsx — 7 pass (new file)
  • cd gui && bun test tests/integrations-surfaces.test.tsx — 23 pass, including a new populated-overview case
  • cd gui && bun test tests/locale-parity.test.ts tests/i18n-locales.test.ts tests/consequence-dialog.test.tsx — pass; the four new keys are present in all nine locales with placeholders preserved
  • Live proxy with a seeded 30-row journal: the served DOM contains exactly one .integration-history-row outside the disclosure, six inside it, and a Show 6 more control. Measured child geometry at 390px and 320px shows the row wrapping to three lines with negative overflowRight on every child, so nothing clips.

The full suite runs in CI rather than locally, per the maintainer guidance for scoped changes.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Summary by CodeRabbit

  • New Features

    • Added clearer rollback history states for loading, errors, empty results, and populated results.
    • Kept the newest operation visible while older entries can be expanded in pages.
    • Added restore controls, expired-status indicators, and client names where applicable.
    • Improved restore dialog focus handling and backdrop dismissal.
  • Localization

    • Added translations for the client catalog, rollback history, “show more” controls, and loading errors.
  • Style

    • Refined integration history layout and responsive behavior.

@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner August 31, 2026 05:26
@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Aug 31, 2026
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3d5e466a-e970-40de-9b8e-857f38bacc22

📥 Commits

Reviewing files that changed from the base of the PR and between f979d17 and f60e64c.

📒 Files selected for processing (1)
  • gui/tests/fr-localization.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Walkthrough

The integrations UI now uses a shared, paginated rollback history component. Both integration surfaces show loading, failure, empty, and populated states. Restore dialogs use native modal behavior with focus restoration. New labels are localized across supported languages.

Changes

Integrations rollback history

Layer / File(s) Summary
Rollback history contract and rendering
gui/src/pages/integrations/overview-clients.ts, gui/src/pages/integrations/RollbackHistory.tsx, gui/src/i18n/*
Adds JOURNAL_KIND_KEY and shared rollback row rendering. The newest row remains visible. Older rows appear in pages of six. Expired snapshots show no restore control. New catalog, disclosure, pagination, and failure strings are localized.
Surface state handling and integration
gui/src/pages/integrations/IntegrationsOverview.tsx, gui/src/pages/integrations/FileIntegrationPage.tsx
Both surfaces now render explicit loading, initial failure with retry, empty, and populated states. Populated histories use RollbackHistory. The overview adds catalog and rollback h3 headings.
Restore dialog modal lifecycle
gui/src/pages/integrations/RestoreDialog.tsx
Uses showModal() with focus capture and restoration. Cancel and backdrop dismissal remain disabled while restore is pending.
History presentation and behavioral validation
gui/src/styles-integrations.css, gui/tests/integrations-rollback-history.test.tsx, gui/tests/integrations-surfaces.test.tsx, gui/tests/fr-localization.test.ts
Reworks history borders, disclosure styling, and narrow-screen layout. Tests cover pagination, restore reachability, expiration, client display, shared boundaries, overview integration, and the intentional French translation value.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to f60e6

This PR improves rollback-history presentation, request-state messaging, confirmation-dialog behavior, and heading structure without changing backend behavior or deployment configuration; no actionable merge-blocking risk remains after normal checks and review.

Suggested reviewers: ingwannu

Sequence Diagram(s)

sequenceDiagram
  participant IntegrationSurface
  participant historyResource
  participant RollbackHistory
  participant RestoreDialog

  historyResource->>IntegrationSurface: provide history state
  IntegrationSurface->>RollbackHistory: pass populated rows and onRestore
  RollbackHistory-->>IntegrationSurface: render newest and paginated older rows
  RollbackHistory->>RestoreDialog: invoke restore for selected row
  RestoreDialog->>RestoreDialog: open modal and manage focus
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 17 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the primary change: preventing the rollback journal from overwhelming the Integrations page by collapsing older operations. It is concise, specific, and consistent with the…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title clearly describes the primary change: preventing the rollback journal from overwhelming the Integrations page by collapsing older operations. It is concise, specific, and consistent with the pull request objectives.

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/integrations-rollback-history

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.

@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 57 / 80

설명

이 PR은 Integrations 페이지의 롤백 기록이 화면을 덮는 문제를 고친다. 지금 dev HEAD는 293a2b887 (패키지 2.38.0)이다. 현재 gui/src/pages/integrations/FileIntegrationPage.tsxIntegrationsOverview.tsx는 저널 응답을 전부 한 줄 한 줄 테두리 있는 리스트로 그린다. 서버가 최대 50행을 주고, 되돌릴 수 있는 스냅샷은 클라이언트당 10개라서, 대부분의 줄은 눌러도 소용이 없는 기록이다. 개요는 모든 클라이언트 기록을 한곳에 모으니 카드 아래에 줄이 잔뜩 쌓인다.

베이스는 dev다. Aside 탭(#3048)과 브랜드 마크(#3049)를 기다릴 필요는 없다. 다만 같은 파일을 Aside 부모 #3047도 만진다. FileIntegrationPage.tsxoverview-clients.ts다. 둘을 순서 없이 머지하면 충돌한다.

새 컴포넌트 gui/src/pages/integrations/RollbackHistory.tsx가 세 가지를 한다. 가장 최근 한 줄은 그대로 보여 준다. 나머지는 <details> 안에 넣고 한 번에 6개씩 연다. Claude Desktop 레인의 페이지 크기와 같다. 줄마다 테두리를 그리지 않고 상자 하나와 사이 구분선만 쓴다. 총 개수는 안 보여 준다. 서버 응답에 전체 개수나 hasMore가 없어서, 숫자를 쓰면 거짓이 되기 때문이다.

지금 dev는 저널을 data ?? []로 받아서, 아직 로딩 중일 때와 실패했을 때와 진짜 빈 기록이 같은 빈 배열이 된다. 실패했는데 ‘아직 적용 기록이 없습니다’라고 말하는 셈이다. 이 PR은 스켈레톤, 실패+재시도, 빈 상태, 리스트를 나눈다. RestoreDialog<dialog open> 대신 showModal()을 쓴다. 예전에는 뒤 페이지가 포커스를 받아서, 파일을 덮어쓰기 직전 확인 창에서 Tab이 밖으로 나갔다.

아홉 로케일에 integrations.catalog.title, integrations.rollback.older, integrations.rollback.showMore, integrations.rollback.failed를 넣었다. 개요 제목을 h2에서 카드로 바로 h4 쓰지 않고, 카탈로그 h3와 롤백 h3를 형제로 둔다. gui/tests/integrations-rollback-history.test.tsx는 50행이 한 줄만 보이게, 최신 Undo가 접지 않아도 눌리게, 6개씩 더 보이게 잠근다. types.ts/config.ts 분할과 무관하다. 중복 PR이 아니다. 프리뷰 배포는 계획에 없다. 점수 57은 ‘지금 페이지를 실제로 덜 아프게 만들지만, Aside 스택과 파일이 겹친다’는 뜻이다.

경로 gui/src/pages/integrations/RollbackHistory.tsx newest - 첫 줄 RollbackRowkey={row.opId}가 없다. 지금은 한 개라 괜찮다. 나중에 최근 줄을 두 개로 늘리면 경고가 난다.
경로 gui/src/pages/integrations/RollbackHistory.tsx 정렬 - [newest, ...older] = rows는 배열 첫 칸이 최신이라고 믿는다. 테스트 주석도 라우트가 최신 먼저라고 적는다. 그 계약이 서버에서 깨지면 접힌 쪽에 최신 줄이 들어간다. 이 파일 안에서 시간 정렬을 한 번 더 하지 않는다.
경로 gui/src/pages/integrations/FileIntegrationPage.tsx / overview-clients.ts - #3047도 이 두 파일을 고친다(Aside 맵, FILE_LABEL_KEY.aside). 이 PR은 저널 UI와 JOURNAL_KIND_KEY를 넣는다. 한쪽을 머지하면 다른 쪽은 리베이스가 필요하다.
경로 gui/src/pages/integrations/RestoreDialog.tsx 포커스 - 접힌 줄의 버튼은 닫을 때 DOM에서 사라질 수 있다. 주석대로 best effort다. 최신 줄 Undo는 접히지 않으니 그 경로는 포커스가 돌아온다.
경로 gui/src/pages/integrations/FileIntegrationPage.tsx 롤백 제목 - 클라이언트 탭은 여전히 롤백을 h4로 두고, 개요는 h3로 올린다. 탭 안 계층(h3 제목 → h4 롤백)은 맞다. 두 면의 제목 레벨만 다르다.

메인테이너의 판단이 필요한 지점

너의 추천

CI가 초록이면 dev에 머지한다. 지금 페이지를 덜 아프게 하는 수정이고 Aside를 기다릴 이유가 없다. #3047/#3048보다 먼저 올리는 편이 충돌을 한쪽으로 모은다. 그 경우 Aside 스택을 이 HEAD 위에 다시 쌓는다. 분할 무효화·중복 닫기 해당 없음. 프리뷰 배포는 계획에 없다.

이 댓글은 grok-bot이 작성했습니다

@lidge-jun
lidge-jun force-pushed the codex/integrations-rollback-history branch from f979d17 to f60e64c Compare August 31, 2026 05:42
…urfaces

The overview showed the global journal and every client tab showed the same
journal filtered, both mapping the whole response into individually bordered
rows. The route caps at 50 and keeps 10 restorable snapshots per client, so a
user with a few dozen toggles behind them got fifty loose strips stacked under
the real controls, twice, and most of them could not be undone.

The newest row stays visible because it is the one a user reaches for after a
mistake. The rest collapse behind a disclosure and reveal six at a time, the
page size ClaudeDesktop's lane already uses. Rows now share one container
boundary with border-top separators, which is what removes the stacked-strip
texture. No total is displayed: the payload carries neither a total nor a
hasMore, so any number would be a claim we cannot support.

Three things were fixed alongside it, all in the same rendering path:

- Cold, failed and empty rendered identically, because `data ?? []` collapses
  all three. A user whose journal request failed was told they had no history;
  they now get a skeleton, an error with retry, or the empty state.
- RestoreDialog rendered `<dialog open>`, which is non-modal: the page behind a
  confirmation that overwrites a file stayed focusable, and an inline
  full-screen style block faked the backdrop. It now uses ConsequenceDialog's
  modal lifecycle.
- The overview outline went h2 straight to h4, so every card title was an
  orphan level. An h3 owns the client catalog and rollback is its sibling.

integrations.catalog.title joins the French intentional-English allowlist:
"Clients" is the same word in French, and fr-localization's accidental-English
guard is right to ask.

Verification: bun run typecheck and bun run lint:gui clean; the full GUI suite
runs 1119 pass / 0 fail; rendered against a live proxy with a seeded 30-row
journal, the served DOM carries exactly one history row outside the disclosure,
six inside it and a "Show 6 more" control, and measured child geometry at 390px
and 320px wraps to three lines with no child overflowing its row.
@lidge-jun
lidge-jun force-pushed the codex/integrations-rollback-history branch from f60e64c to b5b491b Compare August 31, 2026 05:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant