-
Notifications
You must be signed in to change notification settings - Fork 974
feat: display the number of idle tasks in the navbar #19471
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
const { data: idleTasks } = useQuery({ | ||
queryKey: ["tasks", filter], | ||
queryFn: () => data.fetchTasks(filter), | ||
refetchInterval: 10_000, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use a longer fetch interval and conditionally refetch if an action to create a workspace / task was performed in the last fetch interval?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use a longer fetch interval
Yeap! Wdyt about one minute?
Conditionally refetch if an action to create a workspace / task was performed in the last fetch interval?
Hm... I think so, but it looks complex. IMO, we could increase the refetch time and see if it is necessary to optimize it to avoid adding unnecessary complexity. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, let's go with 30 60s initially.
data: [ | ||
{ | ||
prompt: "Task 1", | ||
workspace: { | ||
...MockWorkspace, | ||
latest_app_status: { | ||
...MockWorkspaceAppStatus, | ||
state: "idle", | ||
}, | ||
}, | ||
}, | ||
], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggest including additional non-idle tasks in the input
const search = | ||
idleTasks && idleTasks.length > 0 | ||
? new URLSearchParams({ | ||
username: user.username, | ||
tab: "waiting-for-input", | ||
}).toString() | ||
: undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should change the url of this button just based on whether you have an idle task or not. if clicking the badge specifically took you to the page with this search set I would be fine with that, but the behavior of the whole button changing back and forth is confusing to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense 👍
enabled: canSeeTasks, | ||
refetchOnWindowFocus: true, | ||
select: (data) => | ||
data.filter((task) => task.workspace.latest_app_status?.state === "idle"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
data.filter((task) => task.workspace.latest_app_status?.state === "idle"), | |
data.filter((task) => task.workspace.latest_app_status?.state === "idle").length, |
I think you could just select the length yeah? and maybe even set initialData
to 0
so you don't have to worry about loading states as much
<NavLink | ||
to={{ pathname: "/tasks", search }} | ||
className={({ isActive }) => { | ||
return cn(linkStyles.default, isActive ? linkStyles.active : ""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return cn(linkStyles.default, isActive ? linkStyles.active : ""); | |
return cn(linkStyles.default, isActive && linkStyles.active); |
no need to hand it an empty string, it's smart enough to filter
WalkthroughAdds a Tasks nav item that fetches user-scoped tasks via the experimental API, counts “idle” tasks, and displays a badge with a tooltip. Updates NavbarView to require a user prop and adjusts rendering. Storybook now preloads filter-scoped task data and adds an IdleTasks story. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor U as User
participant NV as NavbarView
participant TNI as TasksNavItem
participant RQ as ReactQuery Cache
participant API as experimental.getTasks(filter)
U->>NV: Mount navbar with user
NV->>TNI: Render TasksNavItem(user)
TNI->>RQ: useQuery(["tasks", userFilter], fetcher, { refetchInterval, initialData })
alt Cache hit
RQ-->>TNI: Return cached tasks
else Cache miss
RQ->>API: Fetch tasks for user
API-->>RQ: Tasks[]
RQ-->>TNI: Store + return
end
TNI->>TNI: Compute idleCount = tasks.filter(s=="idle").length
alt idleCount > 0
TNI-->>U: Render Tasks link with Badge(idleCount) + Tooltip
else
TNI-->>U: Render Tasks link without Badge
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~55 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. 📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
♻️ Duplicate comments (1)
site/src/modules/dashboard/Navbar/NavbarView.tsx (1)
162-162
: Simplified cn usage is preferred.Returning
cn(linkStyles.default, { [linkStyles.active]: isActive })
is cleaner and matches prior feedback.Also applies to: 170-170
🧹 Nitpick comments (1)
site/src/modules/dashboard/Navbar/NavbarView.tsx (1)
211-236
: Minor a11y improvement for the link’s accessible name.Currently the link’s accessible name will be “Tasks 3”; the badge’s
aria-label
does not affect the parentNavLink
. Consider giving the NavLink a more descriptivearia-label
when there are idle tasks.Apply this diff:
- <NavLink - to="/tasks" - className={({ isActive }) => { - return cn(linkStyles.default, { [linkStyles.active]: isActive }); - }} - > + <NavLink + to="/tasks" + aria-label={idleCount > 0 ? `Tasks — ${idleTasksLabel(idleCount)}` : "Tasks"} + className={({ isActive }) => + cn(linkStyles.default, { [linkStyles.active]: isActive }) + } + >
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
site/src/modules/dashboard/Navbar/NavbarView.stories.tsx
(2 hunks)site/src/modules/dashboard/Navbar/NavbarView.tsx
(6 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
site/**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
All user-facing frontend code is developed in TypeScript using React and lives in the
site/
directory.
Files:
site/src/modules/dashboard/Navbar/NavbarView.stories.tsx
site/src/modules/dashboard/Navbar/NavbarView.tsx
site/src/**/*.tsx
📄 CodeRabbit inference engine (site/CLAUDE.md)
site/src/**/*.tsx
: MUI components are deprecated - migrate away from these when encountered
Use shadcn/ui components first - check site/src/components for existing implementations
Emotion CSS is deprecated. Use Tailwind CSS instead.
Responsive design - use Tailwind's responsive prefixes (sm:, md:, lg:, xl:)
Do not usedark:
prefix for dark mode
Group related Tailwind classes
Prefer Tailwind utilities over custom CSS when possible
Use Tailwind classes for all new styling
Replace Emotioncss
prop with Tailwind classes
Leverage custom color tokens: content-primary, surface-secondary, etc.
Use className with clsx for conditional styling
Don’t call component functions directly; render them via JSX. This keeps Hook rules intact and lets React optimize reconciliation.
After calling a setter you’ll still read the previous state during the same event; updates are queued and batched.
Use functional updates (setX(prev ⇒ …)) whenever next state depends on previous state.
Pass a function to useState(initialFn) for lazy initialization—it runs only on the first render.
If the next state is Object.is-equal to the current one, React skips the re-render.
An Effect takes a setup function and optional cleanup; React runs setup after commit, cleanup before the next setup or on unmount.
The dependency array must list every reactive value referenced inside the Effect, and its length must stay constant.
Effects run only on the client, never during server rendering.
Use Effects solely to synchronize with external systems; if you’re not “escaping React,” you probably don’t need one.
Every sibling element in a list needs a stable, unique key prop. Never use array indexes or Math.random(); prefer data-driven IDs.
Keys aren’t passed to children and must not change between renders; if you return multiple nodes per item, use
useRef stores a mutable .current without causing re-renders.
Avoid reading or mutating refs during render; access them in event handlers or Effects ...
Files:
site/src/modules/dashboard/Navbar/NavbarView.stories.tsx
site/src/modules/dashboard/Navbar/NavbarView.tsx
site/src/modules/**/*
📄 CodeRabbit inference engine (site/CLAUDE.md)
The modules folder should contain components with business logic specific to the codebase
Files:
site/src/modules/dashboard/Navbar/NavbarView.stories.tsx
site/src/modules/dashboard/Navbar/NavbarView.tsx
site/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (site/CLAUDE.md)
site/src/**/*.{ts,tsx}
: Use ES modules (import/export) syntax, not CommonJS (require)
Destructure imports when possible (eg. import { foo } from 'bar')
Preferfor...of
overforEach
for iteration
Components and custom Hooks must be pure and idempotent—same inputs → same output; move side-effects to event handlers or Effects.
Never mutate props, state, or values returned by Hooks. Always create new objects or use the setter from useState.
Only call Hooks at the top level of a function component or another custom Hook—never in loops, conditions, nested functions, or try / catch.
Only call Hooks from React functions. Regular JS functions, classes, event handlers, useMemo, etc. are off-limits.
Never pass Hooks around as values or mutate them dynamically. Keep Hook usage static and local to each component.
Don’t call Hooks (including useRef) inside loops, conditions, or map(). Extract a child component instead.
Files:
site/src/modules/dashboard/Navbar/NavbarView.stories.tsx
site/src/modules/dashboard/Navbar/NavbarView.tsx
**/*.{go,sql,ts,tsx,js,jsx,md}
📄 CodeRabbit inference engine (CLAUDE.md)
Ensure files end with a newline to avoid missing newlines.
Files:
site/src/modules/dashboard/Navbar/NavbarView.stories.tsx
site/src/modules/dashboard/Navbar/NavbarView.tsx
🧬 Code graph analysis (2)
site/src/modules/dashboard/Navbar/NavbarView.stories.tsx (2)
site/src/testHelpers/entities.ts (3)
MockUserOwner
(487-500)MockWorkspace
(1392-1428)MockWorkspaceAppStatus
(1006-1018)site/src/modules/dashboard/Navbar/NavbarView.tsx (1)
NavbarView
(46-145)
site/src/modules/dashboard/Navbar/NavbarView.tsx (6)
site/src/api/typesGenerated.ts (1)
User
(3362-3365)site/src/modules/dashboard/Navbar/UserDropdown/UserDropdown.tsx (1)
UserDropdown
(19-58)site/src/hooks/useEmbeddedMetadata.ts (1)
useEmbeddedMetadata
(245-247)site/src/api/api.ts (1)
API
(2818-2818)site/src/components/Tooltip/Tooltip.tsx (3)
TooltipProvider
(9-9)TooltipTrigger
(13-13)TooltipContent
(15-42)site/src/components/Badge/Badge.tsx (1)
Badge
(65-83)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: test-e2e
- GitHub Check: chromatic
- GitHub Check: lint
- GitHub Check: gen
🔇 Additional comments (7)
site/src/modules/dashboard/Navbar/NavbarView.tsx (6)
3-12
: Using shadcn/ui primitives for Badge/Tooltip looks good.Imports align with our guidelines (no MUI, Tailwind-based components). Nothing to change here.
18-18
: Prop type tightened: user is now required.Making
NavbarViewProps.user
andNavItemsProps.user
non-nullable is appropriate and simplifies downstream logic. Be sure all call sites are updated (stories are).Also applies to: 28-28, 149-149
71-71
: Passing user to NavItems is correct.Matches the new non-nullable contract and avoids prop drilling via context.
120-127
: Always rendering UserDropdown on md+ improves consistency.This matches the product UX; no issues spotted.
240-242
: Helper reads well.Copy reads clearly and pluralization is correct.
186-205
: No further action needed—getTasks
returnsTask[]
as expected.I verified that in
site/src/api/api.ts
the method is declared as:getTasks = async (filter: TasksFilter): Promise<Task[]> => { // … return workspaces.workspaces.map(workspace => ({ workspace, prompt: prompts.prompts[workspace.latest_build.id], })); };which clearly returns an array of
Task
objects, matching thePromise<Task[]>
signature and satisfyinginitialData: []
.site/src/modules/dashboard/Navbar/NavbarView.stories.tsx (1)
2-7
: Good inclusion of workspace fixtures.Using
MockWorkspace
andMockWorkspaceAppStatus
makes the story realistic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice!
Depends on: #19377
Closes #19323
Screenshot:
Screen recording:
Screen.Recording.2025-08-21.at.11.52.43.mov
Summary by CodeRabbit
New Features
Improvements
Tests