Skip to content

Conversation

@drifter089
Copy link
Owner

@drifter089 drifter089 commented Dec 25, 2025

Summary

Fixes roles in the dashboard drawer's Roles tab showing "Unassigned" when they have assignedUserId but assignedUserName is null in the database.

Changes

  • Add enrichRolesWithUserNames and enrichChartRolesWithUserNames shared utilities
  • Apply role enrichment to dashboard queries (getDashboardCharts, getAllDashboardChartsWithData)
  • Refactor public-view router to use the shared utility, removing duplicate code

Summary by CodeRabbit

  • Bug Fixes
    • Improved assigned role display: user names for assigned roles are now consistently and reliably populated across dashboard charts and publicly shared team views.

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

@vercel
Copy link

vercel bot commented Dec 25, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
org-os Ready Ready Preview, Comment Dec 25, 2025 11:16pm

@coderabbitai
Copy link

coderabbitai bot commented Dec 25, 2025

📝 Walkthrough

Walkthrough

Consolidated role enrichment logic by introducing new utility functions to populate missing assignedUserName values for chart roles and team roles across API routers. Both dashboard and public-view routers now delegate enrichment to shared utilities in organization-members, replacing inline conditional logic with unified calls.

Changes

Cohort / File(s) Summary
Enrichment Utility Addition
src/server/api/utils/organization-members.ts
Added RoleWithUser type and two new enrichment functions: enrichRolesWithUserNames() for generic role lists and enrichChartRolesWithUserNames() for dashboard charts. Both functions fetch organization members and populate missing assignedUserName fields; they only perform lookups when enrichment is needed.
Dashboard Router Integration
src/server/api/routers/dashboard.ts
Updated getAllDashboardChartsWithData() and getDashboardCharts() to call enrichChartRolesWithUserNames() before applying goal progress enrichment, ensuring chart metric roles have assignedUserName populated.
Public View Router Simplification
src/server/api/routers/public-view.ts
Replaced conditional enrichment logic with direct call to enrichRolesWithUserNames() in the getTeamByShareToken flow. Removed intermediate buildMemberNameMap and fetchOrganizationMembers imports; removed detection of roles needing enrichment and manual per-role augmentation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 A rabbit hops through roles so neat,
Where names and users finally meet!
From scattered logic, now consolidated—
Rich enrichment, neatly delegated.
The charts now glow, the teams aligned,
With user names no longer left behind! ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main fix: enriching dashboard roles with missing assignedUserName during initial load, which is the core objective of the PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch neon-shadow-drift

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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/server/api/routers/public-view.ts (1)

122-126: Missing role enrichment for public dashboard view.

The getDashboardByShareToken procedure includes roles: true (line 104) but does not call enrichChartRolesWithUserNames before returning, unlike the authenticated dashboard queries in dashboard.ts. This means public dashboard views will still show "Unassigned" for roles with a missing assignedUserName.

🔎 Proposed fix
+import {
+  enrichChartRolesWithUserNames,
+  enrichRolesWithUserNames,
+  getOrganizationDirectoryId,
+} from "@/server/api/utils/organization-members";
-import {
-  enrichRolesWithUserNames,
-  getOrganizationDirectoryId,
-} from "@/server/api/utils/organization-members";

Then update the enrichment flow:

+      // Enrich roles with missing assignedUserName
+      const directoryId = await getOrganizationDirectoryId(team.organizationId);
+      const chartsWithUserNames = await enrichChartRolesWithUserNames(
+        dashboardCharts,
+        team.organizationId,
+        directoryId,
+      );
+
       // Enrich charts with goal progress and value labels
       const enrichedCharts = await enrichChartsWithGoalProgress(
-        dashboardCharts,
+        chartsWithUserNames,
         ctx.db,
       );
🧹 Nitpick comments (1)
src/server/api/utils/organization-members.ts (1)

166-202: LGTM!

Efficient implementation that fetches organization members once for all charts rather than per-chart. The nested mapping correctly handles the chart.metric.roles structure.

The role mapping logic (lines 190-198) is duplicated from enrichRolesWithUserNames. You could optionally extract a helper or reuse enrichRolesWithUserNames internally:

roles: await enrichRolesWithUserNames(chart.metric.roles, organizationId, directoryId),

However, this would require passing the already-fetched nameMap to avoid redundant API calls, so the current approach is acceptable for clarity.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d125cc9 and 6411df7.

📒 Files selected for processing (3)
  • src/server/api/routers/dashboard.ts
  • src/server/api/routers/public-view.ts
  • src/server/api/utils/organization-members.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Use TypeScript 5.9 with strict type checking for all frontend and backend code

Use Next.js 15 App Router with tRPC 11 and TanStack Query for API communication. For server components, use direct tRPC calls (import { api } from '@/trpc/server') for 10x faster performance. For client components, use React hooks with TanStack Query (import { api } from '@/trpc/react').

Files:

  • src/server/api/utils/organization-members.ts
  • src/server/api/routers/dashboard.ts
  • src/server/api/routers/public-view.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

All TypeScript/JavaScript files should use ESLint and Prettier for code quality, with import sorting via @trivago/prettier-plugin-sort-imports using inline type imports.

Files:

  • src/server/api/utils/organization-members.ts
  • src/server/api/routers/dashboard.ts
  • src/server/api/routers/public-view.ts
src/server/api/routers/**/*.ts

📄 CodeRabbit inference engine (GEMINI.md)

src/server/api/routers/**/*.ts: In tRPC procedures, never assume authentication; always use helpers like getTeamAndVerifyAccess to verify access before operations
Be careful when modifying team save logic related to EditSession model, which handles locking for concurrent team editing

src/server/api/routers/**/*.ts: Always use protectedProcedure or workspaceProcedure for tRPC routes that require authentication. Include authorization checks using helpers from @/server/api/utils/authorization to verify resources belong to the user's organization.
For new tRPC procedures, use workspaceProcedure for org-scoped operations, call authorization helpers for resource verification, and invalidate cache tags after mutations using invalidateCacheByTags(ctx.db, [tagName]).

Files:

  • src/server/api/routers/dashboard.ts
  • src/server/api/routers/public-view.ts
src/**/*{metric,role,dashboard}*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

When linking/unlinking roles to metrics, update both TanStack Query caches: role.getByTeamId cache and dashboard.getDashboardCharts cache. Use use-optimistic-role-update.ts hook for consistent cache management across both dashboards and canvas.

Files:

  • src/server/api/routers/dashboard.ts
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T20:38:49.083Z
Learning: Applies to src/**/*{metric,role,dashboard}*.{ts,tsx} : When linking/unlinking roles to metrics, update both TanStack Query caches: `role.getByTeamId` cache and `dashboard.getDashboardCharts` cache. Use `use-optimistic-role-update.ts` hook for consistent cache management across both dashboards and canvas.
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T20:38:49.083Z
Learning: Applies to src/app/teams/[teamId]/**/*role*.{ts,tsx} : For role nodes in the team canvas, store only the `roleId` in node data, not the full role object. Fetch display data from TanStack Query cache using the `useRoleData(roleId)` pattern to keep nodes lightweight and cache-efficient.
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T20:38:49.083Z
Learning: Applies to src/app/teams/[teamId]/**/*role*node*.tsx : Consolidate duplicated `role-node.tsx` and `public-role-node.tsx` by extracting a shared `RoleNodeTemplate` component with an `isEditable` prop.
📚 Learning: 2025-12-25T20:38:49.083Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T20:38:49.083Z
Learning: Applies to src/**/*{metric,role,dashboard}*.{ts,tsx} : When linking/unlinking roles to metrics, update both TanStack Query caches: `role.getByTeamId` cache and `dashboard.getDashboardCharts` cache. Use `use-optimistic-role-update.ts` hook for consistent cache management across both dashboards and canvas.

Applied to files:

  • src/server/api/utils/organization-members.ts
  • src/server/api/routers/dashboard.ts
  • src/server/api/routers/public-view.ts
📚 Learning: 2025-12-25T20:38:49.083Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T20:38:49.083Z
Learning: Applies to src/app/teams/[teamId]/**/*role*.{ts,tsx} : For role nodes in the team canvas, store only the `roleId` in node data, not the full role object. Fetch display data from TanStack Query cache using the `useRoleData(roleId)` pattern to keep nodes lightweight and cache-efficient.

Applied to files:

  • src/server/api/utils/organization-members.ts
  • src/server/api/routers/dashboard.ts
  • src/server/api/routers/public-view.ts
📚 Learning: 2025-12-25T20:38:49.083Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T20:38:49.083Z
Learning: Applies to src/app/teams/[teamId]/**/*role*node*.tsx : Consolidate duplicated `role-node.tsx` and `public-role-node.tsx` by extracting a shared `RoleNodeTemplate` component with an `isEditable` prop.

Applied to files:

  • src/server/api/utils/organization-members.ts
  • src/server/api/routers/public-view.ts
📚 Learning: 2025-12-20T22:12:00.576Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: Applies to src/app/teams/[teamId]/**/*.tsx : Avoid modifying `enrichNodesWithRoleData` flow without understanding the complete canvas serialization logic for saving/loading React Flow nodes to the database

Applied to files:

  • src/server/api/utils/organization-members.ts
  • src/server/api/routers/dashboard.ts
  • src/server/api/routers/public-view.ts
📚 Learning: 2025-12-25T20:38:49.083Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T20:38:49.083Z
Learning: Applies to src/**/*dashboard*metric*card*.tsx : Consolidate duplicated `dashboard-metric-card.tsx` and `public-dashboard-metric-card.tsx` by adding a `readOnly` mode instead of maintaining separate components.

Applied to files:

  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-20T22:12:00.576Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: Applies to src/app/teams/[teamId]/**/*.tsx : React Flow nodes must store minimal data (e.g., just `roleId`); fetch full Role data from TanStack Query cache in the Node component to keep canvas and sidebars in sync

Applied to files:

  • src/server/api/routers/dashboard.ts
  • src/server/api/routers/public-view.ts
📚 Learning: 2025-12-25T20:38:49.083Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T20:38:49.083Z
Learning: Applies to src/server/api/routers/**/*.ts : For new tRPC procedures, use `workspaceProcedure` for org-scoped operations, call authorization helpers for resource verification, and invalidate cache tags after mutations using `invalidateCacheByTags(ctx.db, [tagName])`.

Applied to files:

  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-25T20:38:49.083Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T20:38:49.083Z
Learning: Applies to src/server/api/routers/**/*.ts : Always use `protectedProcedure` or `workspaceProcedure` for tRPC routes that require authentication. Include authorization checks using helpers from `@/server/api/utils/authorization` to verify resources belong to the user's organization.

Applied to files:

  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-25T20:38:49.083Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T20:38:49.083Z
Learning: Applies to **/*.{ts,tsx} : Use Next.js 15 App Router with tRPC 11 and TanStack Query for API communication. For server components, use direct tRPC calls (`import { api } from '@/trpc/server'`) for 10x faster performance. For client components, use React hooks with TanStack Query (`import { api } from '@/trpc/react'`).

Applied to files:

  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-20T22:12:00.576Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: Applies to src/server/api/routers/**/*.ts : Be careful when modifying team save logic related to `EditSession` model, which handles locking for concurrent team editing

Applied to files:

  • src/server/api/routers/public-view.ts
🧬 Code graph analysis (2)
src/server/api/routers/dashboard.ts (2)
src/server/api/utils/organization-members.ts (1)
  • enrichChartRolesWithUserNames (170-202)
src/server/api/utils/enrich-charts-with-goal-progress.ts (1)
  • enrichChartsWithGoalProgress (60-141)
src/server/api/routers/public-view.ts (1)
src/server/api/utils/organization-members.ts (2)
  • getOrganizationDirectoryId (117-128)
  • enrichRolesWithUserNames (140-164)
🔇 Additional comments (7)
src/server/api/routers/dashboard.ts (3)

12-12: LGTM!

The import of enrichChartRolesWithUserNames correctly brings in the shared utility for role enrichment.


50-57: LGTM!

Role enrichment is correctly applied before goal progress enrichment. The flow ensures assignedUserName is populated before charts are returned to the client.


98-105: LGTM!

Consistent enrichment pattern with getAllDashboardChartsWithData. Both dashboard queries now properly populate missing assignedUserName values.

src/server/api/routers/public-view.ts (2)

11-14: LGTM!

Import updated to use the shared enrichRolesWithUserNames utility, removing the now-unnecessary individual imports.


55-63: LGTM!

Clean refactor using the shared enrichRolesWithUserNames utility. The public view correctly fetches the directory ID separately since it lacks workspace context.

src/server/api/utils/organization-members.ts (2)

129-134: LGTM!

Minimal type definition that captures the required fields for enrichment. The generic constraint pattern (<T extends RoleWithUser>) allows the functions to work with full role objects while only requiring these two fields.


136-164: LGTM!

Well-implemented enrichment function with:

  • Early return optimization to avoid unnecessary WorkOS API calls
  • Correct preservation of original role properties via spread
  • Sensible fallback (User ${id.substring(0, 8)}) for unknown users

@drifter089 drifter089 merged commit 4a8084e into main Dec 25, 2025
4 checks passed
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.

2 participants