Skip to content

feat(ui): Merge Analytics pilot on the shared design system (U5 B2)#442

Merged
OBenner merged 1 commit into
developfrom
claude/ui-b2-merge-analytics
Jul 24, 2026
Merged

feat(ui): Merge Analytics pilot on the shared design system (U5 B2)#442
OBenner merged 1 commit into
developfrom
claude/ui-b2-merge-analytics

Conversation

@OBenner

@OBenner OBenner commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Summary

Fourth B2 slice — the first to compose the BarList primitive (#441). Its conflict-pattern distribution is exactly the histogram pattern the primitive was built for.

libs/ui

  • AnalyticsDashboard gains an optional barLists prop — titled cards each rendering a BarList distribution, in the main column alongside the chart cards. Backward-compatible (existing Analytics/Productivity screens unaffected).
  • New shared type UiBarListCard.

Electron

  • Pure merge-analytics-ui mappers: shortenPath (compact file labels), formatDuration; buildMergeKpis / buildMergeBarLists / buildMergeSections from MergeAnalytics + ConflictPattern, reusing analytics-ui's formatters. Conflict-bar tone follows the pattern severity (high/critical → red, medium → amber, low → blue); 0–1 rates become whole percents. 7 tests.
  • MergeAnalyticsPilotView over getMergeSummary + getConflictPatterns, mounted as "Merge Analytics (new UI)" beside the legacy view (export flow stays there).

i18n

  • analytics:mergePilot.* (en+fr), navigation:items.mergeAnalyticsNext.

Scope

The merge report has no time series, so the KPI tiles carry no sparklines. The top conflict files render as a BarList ranked by occurrence count; outcome/efficiency figures fill the summary rail.

Verification

  • 7/7 mapper tests; libs/ui + Electron tsc clean; i18n parity confirmed (20 keys en+fr); no nested ternaries. Storybook rebuilt and the new AnalyticsDashboard WithBarList story verified against the mockup in light + dark (severity-toned conflict bars beside KPIs + rail).

Next in B2

Model Usage (line/sparkline + a per-model BarList) closes the batch.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a new Merge Analytics view with KPI summaries, conflict breakdowns, outcomes, and efficiency metrics.
    • Added sidebar navigation for the new analytics experience.
    • Added loading, error, retry, empty, and accessibility states.
    • Added support for distribution-style bar list cards in analytics dashboards.
    • Added English and French translations for the new view.
  • Tests

    • Added coverage for analytics formatting, KPI mapping, conflict summaries, and section content.

Fourth B2 slice, and the first to use the BarList primitive:

- libs/ui: AnalyticsDashboard gains an optional barLists prop (titled
  cards rendering a BarList distribution) alongside the chart cards —
  backward-compatible. New shared type UiBarListCard.
- Electron: pure merge-analytics-ui mappers (shortenPath, formatDuration;
  buildMergeKpis/BarLists/Sections from MergeAnalytics + ConflictPattern,
  reusing analytics-ui's formatters; severity-toned conflict bars; the
  0-1 rates become whole percents; 7 tests) + MergeAnalyticsPilotView
  over getMergeSummary + getConflictPatterns. Mounted as "Merge
  Analytics (new UI)".
- i18n: analytics:mergePilot.* keys (en+fr), navigation.mergeAnalyticsNext.

The merge report has no time series, so the KPI tiles carry no
sparklines; the top conflict patterns render as a BarList ranked by
occurrence count (bar tone follows conflict severity), with outcome /
efficiency summary cards in the rail.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 24, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a new merge analytics navigation view that fetches merge data through Electron IPC, maps it into dashboard cards and sections, renders conflict bar lists, and provides English/French localization with mapper tests.

Changes

Merge analytics dashboard

Layer / File(s) Summary
Dashboard bar-list support
libs/ui/src/client/types.ts, libs/ui/src/index.ts, libs/ui/src/screens/AnalyticsDashboard.tsx, libs/ui/src/screens/AnalyticsDashboard.stories.tsx
Adds the UiBarListCard type, exposes it publicly, renders bar-list cards in AnalyticsDashboard, and adds a Storybook example.
Merge analytics UI mappers
apps/frontend/src/renderer/lib/merge-analytics-ui.ts
Maps analytics and conflict data into KPI tiles, severity-toned bar lists, and outcome/efficiency sections, with path and duration formatting helpers.
Pilot view and navigation
apps/frontend/src/renderer/components/MergeAnalyticsPilotView.tsx, apps/frontend/src/renderer/components/Sidebar.tsx, apps/frontend/src/renderer/App.tsx, apps/frontend/src/shared/i18n/locales/{en,fr}/*.json
Adds IPC data loading with retry and error states, registers the new sidebar view, renders the pilot view, and adds localized labels.
Mapper validation
apps/frontend/src/renderer/__tests__/merge-analytics-ui.test.ts
Tests formatting, KPI conversion and tones, conflict bar-list mapping, empty inputs, and outcome/efficiency sections.

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

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant MergeAnalyticsPilotView
  participant ElectronIPC
  participant merge_analytics_ui
  participant AnalyticsDashboard
  User->>MergeAnalyticsPilotView: open merge-analytics-next
  MergeAnalyticsPilotView->>ElectronIPC: request merge summary and conflict patterns
  ElectronIPC-->>MergeAnalyticsPilotView: return analytics data
  MergeAnalyticsPilotView->>merge_analytics_ui: build dashboard view models
  merge_analytics_ui-->>MergeAnalyticsPilotView: return KPIs, bar lists, and sections
  MergeAnalyticsPilotView->>AnalyticsDashboard: render localized dashboard
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 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 main change: adding a Merge Analytics pilot in the shared UI/design system.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/ui-b2-merge-analytics

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/frontend/src/renderer/lib/merge-analytics-ui.ts`:
- Around line 103-110: Update formatDuration and its callers so duration strings
are produced through the app’s react-i18next-backed formatter or localized
templates exposed via MergeSectionLabels, including the zero/invalid, seconds,
and minutes-and-seconds cases. Remove hardcoded user-facing “m” and “s” text,
pass the localized formatter from the view, and extend the related tests to
verify the French output.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c18372d0-d070-4bc0-9b22-821de938acc7

📥 Commits

Reviewing files that changed from the base of the PR and between 9b463de and 147200d.

📒 Files selected for processing (13)
  • apps/frontend/src/renderer/App.tsx
  • apps/frontend/src/renderer/__tests__/merge-analytics-ui.test.ts
  • apps/frontend/src/renderer/components/MergeAnalyticsPilotView.tsx
  • apps/frontend/src/renderer/components/Sidebar.tsx
  • apps/frontend/src/renderer/lib/merge-analytics-ui.ts
  • apps/frontend/src/shared/i18n/locales/en/analytics.json
  • apps/frontend/src/shared/i18n/locales/en/navigation.json
  • apps/frontend/src/shared/i18n/locales/fr/analytics.json
  • apps/frontend/src/shared/i18n/locales/fr/navigation.json
  • libs/ui/src/client/types.ts
  • libs/ui/src/index.ts
  • libs/ui/src/screens/AnalyticsDashboard.stories.tsx
  • libs/ui/src/screens/AnalyticsDashboard.tsx

Comment on lines +103 to +110
/** Seconds → "45s" or "2m 05s". */
export function formatDuration(seconds: number): string {
if (!Number.isFinite(seconds) || seconds < 0) return '0s';
const whole = Math.round(seconds);
if (whole < 60) return `${whole}s`;
const minutes = Math.floor(whole / 60);
const rest = whole % 60;
return `${minutes}m ${String(rest).padStart(2, '0')}s`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Localize duration display values.

formatDuration emits user-facing "0s", "m", and "s" strings, bypassing the app’s i18n layer. Pass an i18n-backed duration formatter from the view (or localized duration templates through MergeSectionLabels) and update these tests to cover the French result.

Proposed direction
 export interface MergeSectionLabels {
+  formatDuration: (seconds: number) => string;
   // ...
 }

- value: formatDuration(analytics.average_duration_seconds),
+ value: labels.formatDuration(analytics.average_duration_seconds),

As per coding guidelines, “All user-facing text must use i18n translation keys from react-i18next with format namespace:section.key.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/frontend/src/renderer/lib/merge-analytics-ui.ts` around lines 103 - 110,
Update formatDuration and its callers so duration strings are produced through
the app’s react-i18next-backed formatter or localized templates exposed via
MergeSectionLabels, including the zero/invalid, seconds, and minutes-and-seconds
cases. Remove hardcoded user-facing “m” and “s” text, pass the localized
formatter from the view, and extend the related tests to verify the French
output.

Source: Coding guidelines

@sonarqubecloud

Copy link
Copy Markdown

@OBenner
OBenner merged commit 1e7c8a7 into develop Jul 24, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant