-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feature: org settings #1147
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
feature: org settings #1147
Conversation
|
Warning Rate limit exceeded@ameer2468 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 24 minutes and 39 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (1)
WalkthroughAdds organization- and per-video feature-flag settings across DB, server actions, transcription job, dashboard data/context, UI surfaces (organization and per-cap settings, share/player/sidebar/tabs), and component/type updates including a new transcription status "SKIPPED". Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor U as User
participant WC as Web Client
participant SA as Server Action
participant DB as Database
U->>WC: toggle org/video setting
WC->>SA: call updateOrganizationSettings/updateVideoSettings
SA->>DB: auth check, update settings JSON
DB-->>SA: success
SA-->>WC: { success: true }
WC->>WC: revalidatePath("/dashboard/caps")
sequenceDiagram
autonumber
participant Job as Transcribe Job
participant DB as Database
Job->>DB: Load video + org settings
DB-->>Job: { orgSettings, video.settings }
alt disableTranscript (org or video)
Job->>DB: Update video.transcriptionStatus = "SKIPPED"
DB-->>Job: OK
Job-->>Job: return skipped result
else enabled
Job->>DB: Update transcriptionStatus = "PROCESSING"
Job->>Job: transcribeAudio (dev-mode may short-circuit)
Job->>DB: Save transcript & update status COMPLETE/ERROR
end
sequenceDiagram
autonumber
participant Page as Share Page
participant Ctx as Dashboard Context
participant UI as Player/Sidebar/Toolbar
Page->>Ctx: fetch orgSettings + videoSettings
Ctx-->>Page: settings
Page->>UI: pass disable flags (captions/chapters/comments/reactions)
UI-->>UI: conditionally render controls, tabs and inputs
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60–90 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
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. Comment |
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: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/web/lib/transcribe.ts (1)
146-158: Reset transcription status when skipping in development mode.In development,
transcribeAudionow returns an empty string, we hit this branch, and we return success immediately. However, the video was already markedPROCESSING, and we never transition it toSKIPPED(or any terminal state), so the status remains stuck. Update the status before returning (similar to the org/video disable branch) to keep metadata consistent.if (transcription === "") { if (serverEnv().NODE_ENV === "development") { console.log( "[transcribeVideo] Development mode, skipping transcription", ); + await db() + .update(videos) + .set({ transcriptionStatus: "SKIPPED" }) + .where(eq(videos.id, videoId)); return { success: true, message: "Transcription skipped in development mode", };apps/web/app/s/[videoId]/Share.tsx (1)
304-312: Honor disableReactions on mobile toolbar.The new reactions toggle is ignored on small screens because this Toolbar instance never receives
disableReactions, so emojis remain available even when the feature is disabled.Apply this diff to forward the flag exactly like the desktop toolbar:
<Toolbar onOptimisticComment={handleOptimisticComment} onCommentSuccess={handleCommentSuccess} data={data} user={user} + disableReactions={ + videoSettings?.disableReactions ?? + data.orgSettings?.disableReactions + } />
🧹 Nitpick comments (4)
apps/web/actions/videos/settings.ts (2)
39-44: Consider cache revalidation and settings merge strategy.Two potential concerns:
The settings object is completely replaced rather than merged. If the UI sends partial settings, this could unintentionally clear other flags. Consider fetching existing settings and merging, or ensure callers always provide complete settings objects.
No cache revalidation after the update (e.g.,
revalidatePath). Components displaying these settings may show stale data until a manual refresh.Example merge approach:
+const existingSettings = video.settings || {}; await db() .update(videos) - .set({ settings: videoSettings }) + .set({ settings: { ...existingSettings, ...videoSettings } }) .where(eq(videos.id, videoId)); +revalidatePath(`/dashboard/caps`); +revalidatePath(`/s/${videoId}`); return { success: true };
9-19: Consider extracting shared settings type.The videoSettings parameter type is duplicated from the schema definition. Extracting it to a shared type would ensure consistency and easier maintenance if settings expand.
Example:
// In packages/database/schema.ts or shared types file export type VideoSettings = { disableSummary?: boolean; disableCaptions?: boolean; disableChapters?: boolean; disableReactions?: boolean; disableTranscript?: boolean; disableComments?: boolean; }; // Then use here: export async function updateVideoSettings( videoId: Video.VideoId, videoSettings: VideoSettings, ) {apps/web/app/s/[videoId]/_components/CapVideoPlayer.tsx (1)
619-647: Consider simplifying the IIFE wrapper.The IIFE pattern adds unnecessary complexity. Consider using
useMemofor computed values or extracting to a helper function for better readability.Example with useMemo:
+const filteredComments = useMemo( + () => + comments.filter( + (comment) => + comment && + comment.timestamp !== null && + comment.id && + !(disableCommentStamps && comment.type === "text") && + !(disableReactionStamps && comment.type === "emoji"), + ), + [comments, disableCommentStamps, disableReactionStamps], +); {mainControlsVisible && markersReady && - (() => { - const filteredComments = comments.filter( - (comment) => - comment && - comment.timestamp !== null && - comment.id && - !(disableCommentStamps && comment.type === "text") && - !(disableReactionStamps && comment.type === "emoji"), - ); - - return filteredComments.map((comment) => { + filteredComments.map((comment) => { const position = (Number(comment.timestamp) / duration) * 100; ... return <CommentStamp ... />; - }); -})()} + })}apps/web/app/(org)/dashboard/dashboard-data.ts (1)
46-46: Remove unusedsettingsfromorganizationsWithMembersselect
Line 46:settings: organizations.settings,is never consumed; the actual settings are loaded later at lines 115–119.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (40)
apps/web/actions/organization/settings.ts(1 hunks)apps/web/actions/videos/generate-ai-metadata.ts(0 hunks)apps/web/actions/videos/get-status.ts(4 hunks)apps/web/actions/videos/settings.ts(1 hunks)apps/web/app/(org)/dashboard/Contexts.tsx(4 hunks)apps/web/app/(org)/dashboard/_components/MobileTab.tsx(1 hunks)apps/web/app/(org)/dashboard/_components/Navbar/Items.tsx(1 hunks)apps/web/app/(org)/dashboard/caps/Caps.tsx(1 hunks)apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx(10 hunks)apps/web/app/(org)/dashboard/caps/components/CapCard/CapCardButton.tsx(2 hunks)apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx(1 hunks)apps/web/app/(org)/dashboard/caps/page.tsx(2 hunks)apps/web/app/(org)/dashboard/dashboard-data.ts(7 hunks)apps/web/app/(org)/dashboard/layout.tsx(3 hunks)apps/web/app/(org)/dashboard/settings/organization/Organization.tsx(2 hunks)apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx(1 hunks)apps/web/app/(org)/dashboard/settings/organization/page.tsx(0 hunks)apps/web/app/(org)/dashboard/spaces/[spaceId]/components/SharedCapCard.tsx(1 hunks)apps/web/app/(site)/Navbar.tsx(1 hunks)apps/web/app/s/[videoId]/Share.tsx(8 hunks)apps/web/app/s/[videoId]/_components/CapVideoPlayer.tsx(5 hunks)apps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsx(4 hunks)apps/web/app/s/[videoId]/_components/ShareVideo.tsx(2 hunks)apps/web/app/s/[videoId]/_components/Sidebar.tsx(8 hunks)apps/web/app/s/[videoId]/_components/SummaryChapters.tsx(1 hunks)apps/web/app/s/[videoId]/_components/Toolbar.tsx(2 hunks)apps/web/app/s/[videoId]/_components/tabs/Activity/Comments.tsx(5 hunks)apps/web/app/s/[videoId]/_components/tabs/Activity/EmptyState.tsx(1 hunks)apps/web/app/s/[videoId]/_components/tabs/Activity/index.tsx(4 hunks)apps/web/app/s/[videoId]/_components/tabs/Summary.tsx(9 hunks)apps/web/app/s/[videoId]/_components/utils/transcript-utils.ts(1 hunks)apps/web/app/s/[videoId]/page.tsx(9 hunks)apps/web/lib/transcribe.ts(5 hunks)apps/web/package.json(1 hunks)package.json(1 hunks)packages/database/migrations/meta/_journal.json(1 hunks)packages/database/schema.ts(2 hunks)packages/ui/src/components/Switch.tsx(1 hunks)packages/web-api-contract-effect/src/index.ts(1 hunks)packages/web-domain/src/Video.ts(1 hunks)
💤 Files with no reviewable changes (2)
- apps/web/app/(org)/dashboard/settings/organization/page.tsx
- apps/web/actions/videos/generate-ai-metadata.ts
🧰 Additional context used
📓 Path-based instructions (9)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TanStack Query v5 for all client-side server state and data fetching in the web app
Web mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData rather than broad invalidations
Client code should use useEffectQuery/useEffectMutation and useRpcClient from apps/web/lib/EffectRuntime.ts; do not create ManagedRuntime inside components
Files:
apps/web/app/(org)/dashboard/_components/MobileTab.tsxapps/web/app/(site)/Navbar.tsxapps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsxapps/web/app/(org)/dashboard/_components/Navbar/Items.tsxapps/web/app/s/[videoId]/_components/CapVideoPlayer.tsxapps/web/app/s/[videoId]/_components/SummaryChapters.tsxapps/web/app/(org)/dashboard/caps/Caps.tsxapps/web/actions/organization/settings.tsapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/app/(org)/dashboard/dashboard-data.tsapps/web/lib/transcribe.tsapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/s/[videoId]/_components/Toolbar.tsxapps/web/app/s/[videoId]/_components/tabs/Summary.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/index.tsxapps/web/app/(org)/dashboard/caps/page.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsxapps/web/actions/videos/settings.tsapps/web/app/s/[videoId]/Share.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/components/SharedCapCard.tsxapps/web/app/s/[videoId]/_components/utils/transcript-utils.tsapps/web/app/s/[videoId]/page.tsxapps/web/actions/videos/get-status.tsapps/web/app/(org)/dashboard/caps/components/CapCard/CapCardButton.tsxapps/web/app/(org)/dashboard/Contexts.tsxapps/web/app/(org)/dashboard/settings/organization/Organization.tsxapps/web/app/s/[videoId]/_components/ShareVideo.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/EmptyState.tsxapps/web/app/s/[videoId]/_components/Sidebar.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/Comments.tsx
apps/web/app/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Prefer Server Components for initial data in the Next.js App Router and pass initialData to client components
Files:
apps/web/app/(org)/dashboard/_components/MobileTab.tsxapps/web/app/(site)/Navbar.tsxapps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsxapps/web/app/(org)/dashboard/_components/Navbar/Items.tsxapps/web/app/s/[videoId]/_components/CapVideoPlayer.tsxapps/web/app/s/[videoId]/_components/SummaryChapters.tsxapps/web/app/(org)/dashboard/caps/Caps.tsxapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/app/(org)/dashboard/dashboard-data.tsapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/s/[videoId]/_components/Toolbar.tsxapps/web/app/s/[videoId]/_components/tabs/Summary.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/index.tsxapps/web/app/(org)/dashboard/caps/page.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsxapps/web/app/s/[videoId]/Share.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/components/SharedCapCard.tsxapps/web/app/s/[videoId]/_components/utils/transcript-utils.tsapps/web/app/s/[videoId]/page.tsxapps/web/app/(org)/dashboard/caps/components/CapCard/CapCardButton.tsxapps/web/app/(org)/dashboard/Contexts.tsxapps/web/app/(org)/dashboard/settings/organization/Organization.tsxapps/web/app/s/[videoId]/_components/ShareVideo.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/EmptyState.tsxapps/web/app/s/[videoId]/_components/Sidebar.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/Comments.tsx
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not add inline, block, or docstring comments in any language; code must be self-explanatory
Files:
apps/web/app/(org)/dashboard/_components/MobileTab.tsxapps/web/app/(site)/Navbar.tsxapps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsxapps/web/app/(org)/dashboard/_components/Navbar/Items.tsxapps/web/app/s/[videoId]/_components/CapVideoPlayer.tsxpackages/web-domain/src/Video.tspackages/database/schema.tsapps/web/app/s/[videoId]/_components/SummaryChapters.tsxapps/web/app/(org)/dashboard/caps/Caps.tsxapps/web/actions/organization/settings.tsapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/app/(org)/dashboard/dashboard-data.tspackages/web-api-contract-effect/src/index.tsapps/web/lib/transcribe.tsapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/s/[videoId]/_components/Toolbar.tsxapps/web/app/s/[videoId]/_components/tabs/Summary.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/index.tsxapps/web/app/(org)/dashboard/caps/page.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsxapps/web/actions/videos/settings.tsapps/web/app/s/[videoId]/Share.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/components/SharedCapCard.tsxapps/web/app/s/[videoId]/_components/utils/transcript-utils.tsapps/web/app/s/[videoId]/page.tsxpackages/ui/src/components/Switch.tsxapps/web/actions/videos/get-status.tsapps/web/app/(org)/dashboard/caps/components/CapCard/CapCardButton.tsxapps/web/app/(org)/dashboard/Contexts.tsxapps/web/app/(org)/dashboard/settings/organization/Organization.tsxapps/web/app/s/[videoId]/_components/ShareVideo.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/EmptyState.tsxapps/web/app/s/[videoId]/_components/Sidebar.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/Comments.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use strict TypeScript and avoid any; leverage shared types from packages
**/*.{ts,tsx}: Use a 2-space indent for TypeScript code.
Use Biome for formatting and linting TypeScript/JavaScript files by runningpnpm format.
Files:
apps/web/app/(org)/dashboard/_components/MobileTab.tsxapps/web/app/(site)/Navbar.tsxapps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsxapps/web/app/(org)/dashboard/_components/Navbar/Items.tsxapps/web/app/s/[videoId]/_components/CapVideoPlayer.tsxpackages/web-domain/src/Video.tspackages/database/schema.tsapps/web/app/s/[videoId]/_components/SummaryChapters.tsxapps/web/app/(org)/dashboard/caps/Caps.tsxapps/web/actions/organization/settings.tsapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/app/(org)/dashboard/dashboard-data.tspackages/web-api-contract-effect/src/index.tsapps/web/lib/transcribe.tsapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/s/[videoId]/_components/Toolbar.tsxapps/web/app/s/[videoId]/_components/tabs/Summary.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/index.tsxapps/web/app/(org)/dashboard/caps/page.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsxapps/web/actions/videos/settings.tsapps/web/app/s/[videoId]/Share.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/components/SharedCapCard.tsxapps/web/app/s/[videoId]/_components/utils/transcript-utils.tsapps/web/app/s/[videoId]/page.tsxpackages/ui/src/components/Switch.tsxapps/web/actions/videos/get-status.tsapps/web/app/(org)/dashboard/caps/components/CapCard/CapCardButton.tsxapps/web/app/(org)/dashboard/Contexts.tsxapps/web/app/(org)/dashboard/settings/organization/Organization.tsxapps/web/app/s/[videoId]/_components/ShareVideo.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/EmptyState.tsxapps/web/app/s/[videoId]/_components/Sidebar.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/Comments.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g.,user-menu.tsx).
Use PascalCase for React/Solid components.
Files:
apps/web/app/(org)/dashboard/_components/MobileTab.tsxapps/web/app/(site)/Navbar.tsxapps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsxapps/web/app/(org)/dashboard/_components/Navbar/Items.tsxapps/web/app/s/[videoId]/_components/CapVideoPlayer.tsxpackages/web-domain/src/Video.tspackages/database/schema.tsapps/web/app/s/[videoId]/_components/SummaryChapters.tsxapps/web/app/(org)/dashboard/caps/Caps.tsxapps/web/actions/organization/settings.tsapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/app/(org)/dashboard/dashboard-data.tspackages/web-api-contract-effect/src/index.tsapps/web/lib/transcribe.tsapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/s/[videoId]/_components/Toolbar.tsxapps/web/app/s/[videoId]/_components/tabs/Summary.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/index.tsxapps/web/app/(org)/dashboard/caps/page.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsxapps/web/actions/videos/settings.tsapps/web/app/s/[videoId]/Share.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/components/SharedCapCard.tsxapps/web/app/s/[videoId]/_components/utils/transcript-utils.tsapps/web/app/s/[videoId]/page.tsxpackages/ui/src/components/Switch.tsxapps/web/actions/videos/get-status.tsapps/web/app/(org)/dashboard/caps/components/CapCard/CapCardButton.tsxapps/web/app/(org)/dashboard/Contexts.tsxapps/web/app/(org)/dashboard/settings/organization/Organization.tsxapps/web/app/s/[videoId]/_components/ShareVideo.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/EmptyState.tsxapps/web/app/s/[videoId]/_components/Sidebar.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/Comments.tsx
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, always use
useEffectQueryoruseEffectMutationfrom@/lib/EffectRuntime; never callEffectRuntime.run*directly in components.
Files:
apps/web/app/(org)/dashboard/_components/MobileTab.tsxapps/web/app/(site)/Navbar.tsxapps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsxapps/web/app/(org)/dashboard/_components/Navbar/Items.tsxapps/web/app/s/[videoId]/_components/CapVideoPlayer.tsxapps/web/app/s/[videoId]/_components/SummaryChapters.tsxapps/web/app/(org)/dashboard/caps/Caps.tsxapps/web/actions/organization/settings.tsapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/app/(org)/dashboard/dashboard-data.tsapps/web/lib/transcribe.tsapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/s/[videoId]/_components/Toolbar.tsxapps/web/app/s/[videoId]/_components/tabs/Summary.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/index.tsxapps/web/app/(org)/dashboard/caps/page.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsxapps/web/actions/videos/settings.tsapps/web/app/s/[videoId]/Share.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/components/SharedCapCard.tsxapps/web/app/s/[videoId]/_components/utils/transcript-utils.tsapps/web/app/s/[videoId]/page.tsxapps/web/actions/videos/get-status.tsapps/web/app/(org)/dashboard/caps/components/CapCard/CapCardButton.tsxapps/web/app/(org)/dashboard/Contexts.tsxapps/web/app/(org)/dashboard/settings/organization/Organization.tsxapps/web/app/s/[videoId]/_components/ShareVideo.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/EmptyState.tsxapps/web/app/s/[videoId]/_components/Sidebar.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/Comments.tsx
apps/web/actions/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
All Groq/OpenAI calls must be implemented in Next.js Server Actions under apps/web/actions; do not place AI calls elsewhere
Files:
apps/web/actions/organization/settings.tsapps/web/actions/videos/settings.tsapps/web/actions/videos/get-status.ts
packages/web-api-contract-effect/**
📄 CodeRabbit inference engine (CLAUDE.md)
Update shared HTTP contracts in packages/web-api-contract-effect alongside any API route changes to keep schemas in sync
Files:
packages/web-api-contract-effect/src/index.ts
packages/ui/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Component files in
packages/uishould use PascalCase naming if they define React/Solid components.
Files:
packages/ui/src/components/Switch.tsx
🧠 Learnings (1)
📚 Learning: 2025-09-22T14:17:47.407Z
Learnt from: CR
PR: CapSoftware/Cap#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-22T14:17:47.407Z
Learning: Applies to packages/web-api-contract-effect/** : Update shared HTTP contracts in packages/web-api-contract-effect alongside any API route changes to keep schemas in sync
Applied to files:
packages/web-api-contract-effect/src/index.ts
🧬 Code graph analysis (21)
apps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsx (1)
apps/web/app/s/[videoId]/_components/video/media-player.tsx (2)
MediaPlayerCaptions(3144-3144)MediaPlayerCaptions(3168-3168)
apps/web/app/(org)/dashboard/_components/Navbar/Items.tsx (1)
packages/ui/src/components/Popover.tsx (1)
PopoverTrigger(30-30)
apps/web/app/s/[videoId]/_components/CapVideoPlayer.tsx (1)
packages/database/schema.ts (1)
comments(335-355)
apps/web/app/s/[videoId]/_components/SummaryChapters.tsx (1)
apps/web/app/s/[videoId]/_components/utils/transcript-utils.ts (1)
formatTimeMinutes(29-35)
apps/web/actions/organization/settings.ts (2)
packages/database/index.ts (1)
db(29-34)packages/database/schema.ts (1)
organizations(152-180)
apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx (2)
apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx (1)
SettingsDialog(64-222)apps/web/app/(org)/dashboard/caps/components/CapCard/CapCardButton.tsx (1)
CapCardButton(17-43)
apps/web/app/(org)/dashboard/dashboard-data.ts (2)
packages/database/schema.ts (1)
organizations(152-180)packages/database/index.ts (1)
db(29-34)
apps/web/lib/transcribe.ts (3)
packages/database/schema.ts (3)
videos(256-311)organizations(152-180)s3Buckets(396-406)packages/database/index.ts (1)
db(29-34)packages/env/server.ts (1)
serverEnv(83-87)
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx (4)
apps/web/app/(org)/dashboard/Contexts.tsx (1)
useDashboardContext(50-50)apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-29)packages/utils/src/constants/plans.ts (1)
userIsPro(21-45)apps/web/actions/organization/settings.ts (1)
updateOrganizationSettings(9-44)
apps/web/app/s/[videoId]/_components/Toolbar.tsx (4)
packages/database/schema.ts (1)
videos(256-311)apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-29)packages/database/auth/session.ts (1)
userSelectProps(29-29)apps/web/app/s/[videoId]/Share.tsx (1)
CommentType(30-33)
apps/web/app/(org)/dashboard/caps/page.tsx (1)
packages/database/schema.ts (5)
videos(256-311)comments(335-355)organizations(152-180)users(50-99)videoUploads(674-680)
apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx (4)
apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-29)apps/web/app/(org)/dashboard/Contexts.tsx (1)
useDashboardContext(50-50)packages/utils/src/constants/plans.ts (1)
userIsPro(21-45)apps/web/actions/videos/settings.ts (1)
updateVideoSettings(9-45)
apps/web/actions/videos/settings.ts (2)
packages/database/index.ts (1)
db(29-34)packages/database/schema.ts (1)
videos(256-311)
apps/web/app/s/[videoId]/Share.tsx (3)
apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-29)apps/web/app/s/[videoId]/_components/Sidebar.tsx (1)
Sidebar(71-264)apps/web/app/s/[videoId]/_components/Toolbar.tsx (1)
Toolbar(24-291)
apps/web/app/s/[videoId]/page.tsx (2)
apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-29)packages/database/schema.ts (2)
videos(256-311)organizations(152-180)
apps/web/app/(org)/dashboard/Contexts.tsx (1)
apps/web/app/(org)/dashboard/dashboard-data.ts (2)
Organization(15-26)OrganizationSettings(28-29)
apps/web/app/s/[videoId]/_components/ShareVideo.tsx (5)
apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-29)apps/web/app/s/[videoId]/_components/utils/transcript-utils.ts (1)
TranscriptEntry(3-8)apps/web/hooks/use-transcript.ts (1)
useTranscript(5-27)apps/web/app/s/[videoId]/_components/CapVideoPlayer.tsx (1)
CapVideoPlayer(56-685)apps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsx (1)
HLSVideoPlayer(45-416)
apps/web/app/(org)/dashboard/layout.tsx (1)
apps/web/app/(org)/dashboard/dashboard-data.ts (4)
OrganizationSettings(28-29)Spaces(31-37)UserPreferences(39-39)getDashboardData(41-292)
apps/web/app/s/[videoId]/_components/tabs/Activity/EmptyState.tsx (2)
apps/web/components/EmptyState.tsx (1)
EmptyState(12-31)packages/ui/src/components/LoadingSpinner.tsx (1)
LoadingSpinner(1-36)
apps/web/app/s/[videoId]/_components/Sidebar.tsx (1)
apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-29)
apps/web/app/s/[videoId]/_components/tabs/Activity/Comments.tsx (1)
apps/web/components/EmptyState.tsx (1)
EmptyState(12-31)
🪛 GitHub Actions: Validate Migrations
packages/database/migrations/meta/_journal.json
[error] 2-2: Migration journal version cannot be changed (was: <BASE_VERSION>, now: <CURRENT_VERSION>)
⏰ 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). (2)
- GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Analyze (rust)
🔇 Additional comments (32)
apps/web/app/(org)/dashboard/spaces/[spaceId]/components/SharedCapCard.tsx (1)
1-2: Client directive is the right call
SharedCapCardattaches drag handlers, so marking it as a client component is required for those events to wire up correctly. Nice catch.packages/ui/src/components/Switch.tsx (1)
17-17: LGTM: Design system alignment.The disabled state styling now uses the design system gray scale (
gray-4) and reduces opacity toopacity-40for better visual consistency. This appears to be an intentional alignment with the broader design system updates.apps/web/app/(org)/dashboard/_components/MobileTab.tsx (1)
47-47: LGTM: Layout spacing adjustment.The addition of
gap-5increases horizontal spacing between child elements in the mobile tab container, improving visual layout consistency.packages/web-api-contract-effect/src/index.ts (1)
11-16: LGTM: TranscriptionStatus extension.Adding
"SKIPPED"to theTranscriptionStatusschema properly extends the API contract to support the new transcription state introduced in this PR.Based on coding guidelines: This update to the shared HTTP contract in
packages/web-api-contract-effectaligns with the API route changes across the codebase for organization settings and transcription features.apps/web/app/(site)/Navbar.tsx (1)
141-141: LGTM: Tailwind class standardization.Replacing the arbitrary value
duration-[0.2s]with the standard Tailwind utilityduration-200improves consistency and leverages built-in classes, which can help with bundle optimization.apps/web/app/(org)/dashboard/caps/components/CapCard/CapCardButton.tsx (1)
28-28: LGTM: Simplified event handler.Since
onClickhas a default value of() => {}(line 19), the optional chaining was unnecessary. The direct reference is cleaner and functionally equivalent.apps/web/package.json (1)
56-56: Test Slot behavior across SSR/RSC, ref‐forwarding, and TypeScript after upgrading
Ensure pages using Slot+asChild still render on the server, refs forward correctly to Next Link and fragment children, and your TypeScript build passes without errors.packages/web-domain/src/Video.ts (1)
28-30: LGTM!The addition of "SKIPPED" to the transcriptionStatus enum is clean and consistent with the broader PR changes supporting organization-level transcription controls.
packages/database/schema.ts (2)
162-169: LGTM!The organization-level settings structure is well-defined with typed optional flags. The JSON column approach provides flexibility for future settings additions.
271-280: LGTM!The video-level settings structure mirrors the organization settings, maintaining consistency. The addition of "SKIPPED" to transcriptionStatus completes the domain model alignment.
apps/web/actions/videos/settings.ts (1)
20-37: LGTM!The authorization logic is well-structured with proper checks for user authentication, data validation, video existence, and ownership verification. Error messages are clear and actionable.
apps/web/actions/videos/get-status.ts (1)
17-17: LGTM!The extraction of TranscriptionStatus into a named type alias improves code maintainability and readability. All usages are consistently updated throughout the file.
Also applies to: 20-20
apps/web/app/s/[videoId]/_components/CapVideoPlayer.tsx (2)
38-38: LGTM!The new props for disabling captions and comment/reaction stamps are well-defined with sensible defaults and clear naming.
Also applies to: 44-45, 61-61, 68-69
671-676: LGTM!The conditional rendering of MediaPlayerCaptions based on the disableCaptions flag is implemented correctly.
apps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsx (3)
40-40: LGTM!The disableCaptions prop is properly integrated into the component interface and signature.
Also applies to: 54-54
361-369: LGTM! Good improvement.Making the track elements conditional on the presence of their sources is a solid enhancement that prevents rendering empty tracks and improves robustness.
402-407: LGTM!The conditional rendering of MediaPlayerCaptions is implemented correctly and consistently with the CapVideoPlayer component.
apps/web/app/s/[videoId]/_components/tabs/Summary.tsx (2)
26-26: LGTM!The isSummaryDisabled feature is cleanly implemented with an early return pattern that prevents rendering when the summary is disabled.
Also applies to: 68-68, 146-147
161-174: LGTM!The replacement of the inline SVG with FontAwesomeIcon improves consistency with the rest of the codebase. The styling adjustments are cosmetic and maintain the existing UX.
apps/web/app/(org)/dashboard/_components/Navbar/Items.tsx (1)
97-97: LGTM!The addition of
suppressHydrationWarningis a standard Next.js pattern to address expected hydration mismatches in interactive components.apps/web/app/(org)/dashboard/caps/Caps.tsx (1)
27-27: LGTM: Unused import removed.The removal of
useUploadingContextis correct, as it's not used anywhere in the file. This keeps imports clean.apps/web/app/(org)/dashboard/settings/organization/Organization.tsx (1)
16-16: LGTM: CapSettingsCard integrated properly.The new settings card is correctly imported and positioned in the organization settings flow. The component appears to use dashboard context for data access, consistent with other cards in this layout.
Also applies to: 68-70
apps/web/app/s/[videoId]/_components/utils/transcript-utils.ts (1)
29-35: LGTM: Time formatting logic is correct.The function correctly converts seconds to MM:SS format using floor division and proper padding.
apps/web/app/(org)/dashboard/layout.tsx (1)
13-13: LGTM: Organization settings properly integrated.The
organizationSettingsdata flows correctly fromgetDashboardDatathrough the layout toDashboardContexts, with proper error handling that mirrors the pattern used for other dashboard data.Also applies to: 36-36, 43-43, 50-50, 77-77
apps/web/app/s/[videoId]/_components/tabs/Activity/index.tsx (1)
6-6: LGTM: Comments disabled flag properly threaded.The
commentsDisabledprop is correctly added to the interface, destructured, and passed to theCommentscomponent. The React import consolidation also improves code organization.Also applies to: 24-24, 39-39, 70-70
apps/web/app/s/[videoId]/_components/SummaryChapters.tsx (3)
3-19: LGTM: Props interface well-defined.The
SummaryChaptersPropsinterface clearly defines all required inputs, including feature flags, seek handler, AI data, and loading state.
21-35: LGTM: Conditional rendering logic is clean.The component efficiently computes
hasSummaryandhasChaptersbased on disabled flags and data availability, with an appropriate early return when there's nothing to display.
36-71: LGTM: UI structure is well-organized.The component properly renders Summary and Chapters sections with appropriate styling, semantic HTML, and interactive chapter navigation via the
handleSeekcallback.apps/web/app/(org)/dashboard/dashboard-data.ts (2)
28-29: LGTM: Type export is clean.The
OrganizationSettingstype correctly extracts the settings field type from the organizations schema.
86-86: LGTM: Organization settings integration is complete.The organization settings are properly fetched for the active organization, initialized with appropriate defaults, included in the return value, and handled correctly in error scenarios.
Also applies to: 115-120, 277-277, 289-289
apps/web/app/(org)/dashboard/caps/page.tsx (2)
178-178: LGTM: Video settings properly selected and propagated.The
settingsfield is correctly selected from the videos table and included in the processed output for downstream consumption.Also applies to: 240-240
185-191: Verify org filtering behavior.Adding
eq(videos.orgId, user.activeOrganizationId)restricts the query to videos belonging to the user's active organization only. This is a significant behavioral change that will exclude videos from other organizations, even if the user previously had access to them.Ensure this aligns with the product requirements for the caps page.
Also applies to: 198-198
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx
Outdated
Show resolved
Hide resolved
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.
Critical: Pipeline failure on migration journal version.
The pipeline reports: "Migration journal version cannot be changed (was: <BASE_VERSION>, now: <CURRENT_VERSION>)". This indicates the migration journal's version field was modified, which violates migration integrity constraints.
This must be resolved before merging:
- Check if the migration was regenerated when it shouldn't have been
- Ensure the base migration journal wasn't modified
- Follow the project's migration workflow to properly add new migrations without altering the version field
- Verify with the team if this is a rebase artifact that needs resolution
#!/bin/bash
# Check for any other migration-related changes or conflicts
git log --oneline --all -- packages/database/migrations/
# Compare with the base branch to see what version field changed
git diff origin/main...HEAD -- packages/database/migrations/meta/_journal.json🤖 Prompt for AI Agents
In packages/database/migrations/meta/_journal.json around lines 61 to 67, the
migration journal's "version" field was changed (which is not allowed) — revert
the version field and any other unintended edits in this file to match the base
branch, undo any accidental regeneration of the journal, and re-create new
migrations using the project's approved workflow; verify by comparing with
origin/main, restore the file from the base branch or resolve rebase conflicts,
confirm no other migration files were altered, and consult the team if this
change was received as a rebase artifact before re-committing.
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)
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx (1)
71-76: Sync local state when organizationSettings updates.Local toggles never reflect newly delivered
organizationSettings, so users arriving before the context resolves can overwrite true backend values with defaults. Mirror the incoming payload (or defaults) intosettingsandlastSavedSettings.- useEffect(() => { - if (organizationSettings) { - lastSavedSettings.current = organizationSettings; - } - }, [organizationSettings]); + useEffect(() => { + const next = + organizationSettings ?? { + disableComments: false, + disableSummary: false, + disableCaptions: false, + disableChapters: false, + disableReactions: false, + disableTranscript: false, + }; + setSettings(next); + lastSavedSettings.current = next; + }, [organizationSettings]);
🧹 Nitpick comments (6)
apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx (6)
72-79: State should be Partial and filtered, not an object of undefinedsInitialize overrides as Partial from settingsData, omitting undefineds. This prevents writing undefineds and matches “override” semantics.
-const [settings, setSettings] = useState<OrganizationSettings>({ - disableComments: settingsData?.disableComments, - disableSummary: settingsData?.disableSummary, - disableCaptions: settingsData?.disableCaptions, - disableChapters: settingsData?.disableChapters, - disableReactions: settingsData?.disableReactions, - disableTranscript: settingsData?.disableTranscript, -}); +const [settings, setSettings] = useState<Partial<OrganizationSettings>>( + (settingsData + ? (Object.fromEntries( + Object.entries(settingsData).filter(([, v]) => v !== undefined), + ) as Partial<OrganizationSettings>) + : {}) as Partial<OrganizationSettings>, +);As per coding guidelines
129-136: Simplify effective value calcUse nullish coalescing; current condition is redundant.
-const getEffectiveValue = (key: keyof OrganizationSettings) => { - const videoValue = settings?.[key]; - const orgValue = organizationSettings?.[key] ?? false; - return videoValue !== undefined || videoValue === true - ? videoValue - : orgValue; -}; +const getEffectiveValue = (key: keyof OrganizationSettings) => { + const videoValue = settings?.[key]; + const orgValue = organizationSettings?.[key] ?? false; + return videoValue ?? orgValue; +};
98-103: Type the toggle handler to avoid castsAccept a strongly-typed key instead of string + cast.
-const toggleSettingHandler = useCallback( - (value: string) => { +const toggleSettingHandler = useCallback( + (key: keyof OrganizationSettings) => { setSettings((prev) => { - const key = value as keyof OrganizationSettings; const currentValue = prev?.[key]; const orgValue = organizationSettings?.[key] ?? false;And call with a typed value for options (see next comment). As per coding guidelines
189-191: Use Switch’s checked argument to set value explicitly (less brittle)Avoid manual toggling; derive disable flag from checked. Keeps state in sync with UI source of truth.
-onCheckedChange={() => toggleSettingHandler(option.value)} +onCheckedChange={(checked) => { + const key = option.value as keyof OrganizationSettings; + setSettings((prev) => { + const newValue = !checked; // checked == enabled -> disable flag false + if (key === "disableTranscript" && newValue === true) { + return { + ...prev, + [key]: newValue, + disableSummary: true, + disableChapters: true, + }; + } + return { ...prev, [key]: newValue }; + }); +}}As per coding guidelines
105-109: Remove inline comments (repo guideline)Inline comments are disallowed in TS/JS. Delete these comment lines.
- // If using org default, set to opposite of org value - // If org disabled it (true), enabling means setting to false - // If org enabled it (false), disabling means setting to true - const newValue = currentValue === undefined ? !orgValue : !currentValue; + const newValue = currentValue === undefined ? !orgValue : !currentValue;-// Helper to get the effective value (considering org defaults)- // Disable summary and chapters if transcript is disabledAs per coding guidelines
Also applies to: 129-129, 183-187
83-96: Use useEffectMutation for the save, and update cache instead of blind closeAdopt the app’s EffectRuntime pattern for client mutations and patch related caches (e.g., caps list/cap detail) with setQueryData to reflect updated settings without a full refresh.
I can wire a useEffectMutation around updateVideoSettings and add a setQueryData update for your caps query key. Want a patch?
As per coding guidelines
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (4)
apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx(10 hunks)apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx(1 hunks)apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx(1 hunks)apps/web/app/embed/[videoId]/page.tsx(4 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TanStack Query v5 for all client-side server state and data fetching in the web app
Web mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData rather than broad invalidations
Client code should use useEffectQuery/useEffectMutation and useRpcClient from apps/web/lib/EffectRuntime.ts; do not create ManagedRuntime inside components
Files:
apps/web/app/embed/[videoId]/page.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx
apps/web/app/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Prefer Server Components for initial data in the Next.js App Router and pass initialData to client components
Files:
apps/web/app/embed/[videoId]/page.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not add inline, block, or docstring comments in any language; code must be self-explanatory
Files:
apps/web/app/embed/[videoId]/page.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use strict TypeScript and avoid any; leverage shared types from packages
**/*.{ts,tsx}: Use a 2-space indent for TypeScript code.
Use Biome for formatting and linting TypeScript/JavaScript files by runningpnpm format.
Files:
apps/web/app/embed/[videoId]/page.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g.,user-menu.tsx).
Use PascalCase for React/Solid components.
Files:
apps/web/app/embed/[videoId]/page.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, always use
useEffectQueryoruseEffectMutationfrom@/lib/EffectRuntime; never callEffectRuntime.run*directly in components.
Files:
apps/web/app/embed/[videoId]/page.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx
🧬 Code graph analysis (4)
apps/web/app/embed/[videoId]/page.tsx (1)
packages/database/schema.ts (1)
videos(256-311)
apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx (4)
apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-29)apps/web/app/(org)/dashboard/Contexts.tsx (1)
useDashboardContext(50-50)packages/utils/src/constants/plans.ts (1)
userIsPro(21-45)apps/web/actions/videos/settings.ts (1)
updateVideoSettings(9-45)
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx (4)
apps/web/app/(org)/dashboard/Contexts.tsx (1)
useDashboardContext(50-50)apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-29)packages/utils/src/constants/plans.ts (1)
userIsPro(21-45)apps/web/actions/organization/settings.ts (1)
updateOrganizationSettings(9-44)
apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx (2)
apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx (1)
SettingsDialog(64-218)apps/web/app/(org)/dashboard/caps/components/CapCard/CapCardButton.tsx (1)
CapCardButton(17-43)
⏰ 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). (3)
- GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
- GitHub Check: Analyze (rust)
🔇 Additional comments (2)
apps/web/app/embed/[videoId]/page.tsx (1)
119-160: Remove unusedvideo.settingsor implement feature-gating.The query selects
settings: videos.settingsbut this file never usesvideo.settings(nor does it fetchorgSettings). Either dropsettingsfrom the select to avoid fetching unused data, or add logic here to consumevideo.settings(and joinorganizations.settingsif you need org-level flags).Likely an incorrect or invalid review comment.
apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx (1)
301-306: SettingsDialog wiring LGTMProps and owner gating look correct; closing via onClose updates local state.
apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
Outdated
Show resolved
Hide resolved
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx
Outdated
Show resolved
Hide resolved
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx
Outdated
Show resolved
Hide resolved
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: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/web/app/embed/[videoId]/page.tsx (1)
119-160: Include organization settings in the video query
Add a left join onorganizations, selectorganizations.settingsasorgSettings(using theOrganizationSettingstype), and extend the returned video object so that downstream components can receive and renderorgSettings.apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx (1)
158-168: Replace useMutation with useEffectMutation and remove duplicate Download button
- In apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx (lines 158–168), apply:
Also remove the unused- const deleteMutation = useMutation({ - mutationFn: async () => { - await onDelete?.(); - }, - onError: (error) => { - console.error("Error deleting cap:", error); - }, - onSettled: () => { - setConfirmOpen(false); - }, - }); + const deleteMutation = useEffectMutation({ + mutationFn: () => Effect.promise(() => onDelete?.()), + onSettled: () => setConfirmOpen(false), + onError: (error) => console.error("Error deleting cap:", error), + });useMutationimport.- Remove the first non-owner “Download Cap” button (duplicate); keep the later one with spinner/disabled state.
Verify other occurrences:
rg -n '\buseMutation\(' --glob '*.ts' --glob '*.tsx' apps/web
♻️ Duplicate comments (2)
apps/web/actions/organization/settings.ts (1)
27-34: Good fix on organization existence checkDestructuring the first row and guarding “not found” resolves the prior bug.
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx (1)
72-84: Good fix: sync local state with organizationSettingsSynchronizing both settings and lastSavedSettings addresses stale toggles on context updates.
🧹 Nitpick comments (5)
apps/web/app/embed/[videoId]/page.tsx (1)
256-261: Exclude SKIPPED in transcription trigger
The current check (!== "COMPLETE"&&!== "PROCESSING") still re-triggers forSKIPPED(used whendisableTranscriptis true). Update to also excludeSKIPPED:- if ( - video.transcriptionStatus !== "COMPLETE" && - video.transcriptionStatus !== "PROCESSING" - ) { + if ( + video.transcriptionStatus !== "COMPLETE" && + video.transcriptionStatus !== "PROCESSING" && + video.transcriptionStatus !== "SKIPPED" + ) { transcribeVideo(video.id, video.ownerId, aiGenerationEnabled); }apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx (2)
129-136: Simplify effective value logic and remove inline commentUse nullish coalescing; comment not needed per guidelines.
Apply this diff:
- // Helper to get the effective value (considering org defaults) const getEffectiveValue = (key: keyof OrganizationSettings) => { const videoValue = settings?.[key]; const orgValue = organizationSettings?.[key] ?? false; - return videoValue !== undefined || videoValue === true - ? videoValue - : orgValue; + return videoValue ?? orgValue; };
105-108: Remove inline comments (project policy)Inline comments are disallowed; make code self-explanatory or extract helpers.
Also applies to: 110-117, 181-188
apps/web/actions/organization/settings.ts (1)
27-31: Select only needed fields to reduce IOFetching the whole row isn’t required; select just the id.
Apply this diff:
- const [organization] = await db() - .select() + const [organization] = await db() + .select({ id: organizations.id }) .from(organizations) .where(eq(organizations.id, user.activeOrganizationId));apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx (1)
62-66: Remove inline comments (project policy)Inline comments are not allowed; rely on clear naming or helper extraction.
Also applies to: 71-81, 91-101, 103-109, 112-124, 125-139, 145-153, 172-176, 181-205
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (6)
apps/web/actions/organization/settings.ts(1 hunks)apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx(10 hunks)apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx(1 hunks)apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx(1 hunks)apps/web/app/embed/[videoId]/page.tsx(4 hunks)apps/web/app/s/[videoId]/_components/utils/transcript-utils.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/app/s/[videoId]/_components/utils/transcript-utils.ts
🧰 Additional context used
📓 Path-based instructions (7)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TanStack Query v5 for all client-side server state and data fetching in the web app
Web mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData rather than broad invalidations
Client code should use useEffectQuery/useEffectMutation and useRpcClient from apps/web/lib/EffectRuntime.ts; do not create ManagedRuntime inside components
Files:
apps/web/app/embed/[videoId]/page.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/actions/organization/settings.tsapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
apps/web/app/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Prefer Server Components for initial data in the Next.js App Router and pass initialData to client components
Files:
apps/web/app/embed/[videoId]/page.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not add inline, block, or docstring comments in any language; code must be self-explanatory
Files:
apps/web/app/embed/[videoId]/page.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/actions/organization/settings.tsapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use strict TypeScript and avoid any; leverage shared types from packages
**/*.{ts,tsx}: Use a 2-space indent for TypeScript code.
Use Biome for formatting and linting TypeScript/JavaScript files by runningpnpm format.
Files:
apps/web/app/embed/[videoId]/page.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/actions/organization/settings.tsapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g.,user-menu.tsx).
Use PascalCase for React/Solid components.
Files:
apps/web/app/embed/[videoId]/page.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/actions/organization/settings.tsapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, always use
useEffectQueryoruseEffectMutationfrom@/lib/EffectRuntime; never callEffectRuntime.run*directly in components.
Files:
apps/web/app/embed/[videoId]/page.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/actions/organization/settings.tsapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
apps/web/actions/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
All Groq/OpenAI calls must be implemented in Next.js Server Actions under apps/web/actions; do not place AI calls elsewhere
Files:
apps/web/actions/organization/settings.ts
🧬 Code graph analysis (5)
apps/web/app/embed/[videoId]/page.tsx (1)
packages/database/schema.ts (1)
videos(256-311)
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx (4)
apps/web/app/(org)/dashboard/Contexts.tsx (1)
useDashboardContext(50-50)apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-29)packages/utils/src/constants/plans.ts (1)
userIsPro(21-45)apps/web/actions/organization/settings.ts (1)
updateOrganizationSettings(9-44)
apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx (2)
apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx (1)
SettingsDialog(64-218)apps/web/app/(org)/dashboard/caps/components/CapCard/CapCardButton.tsx (1)
CapCardButton(17-43)
apps/web/actions/organization/settings.ts (2)
packages/database/index.ts (1)
db(29-34)packages/database/schema.ts (1)
organizations(152-180)
apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx (4)
apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-29)apps/web/app/(org)/dashboard/Contexts.tsx (1)
useDashboardContext(50-50)packages/utils/src/constants/plans.ts (1)
userIsPro(21-45)apps/web/actions/videos/settings.ts (1)
updateVideoSettings(9-45)
⏰ 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). (3)
- GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
- GitHub Check: Analyze (rust)
🔇 Additional comments (2)
apps/web/app/embed/[videoId]/page.tsx (1)
186-192: LGTM: Styling consistency improvements.The className changes across the three error/message display divs improve layout consistency using flexbox centering utilities.
Also applies to: 241-250, 288-290
apps/web/actions/organization/settings.ts (1)
36-39: Confirm full replacement vs. merge semanticsThis overwrites settings with the provided object. If partial updates are ever passed, keys may be dropped. Confirm this is intentional for org defaults.
apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
Outdated
Show resolved
Hide resolved
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx
Outdated
Show resolved
Hide resolved
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx
Outdated
Show resolved
Hide resolved
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: 1
♻️ Duplicate comments (1)
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx (1)
42-46: Clarify the transcript dependency relationship."This also allows chapters and summary" is ambiguous. Update to clearly state that transcript is required for downstream features.
Apply this diff:
- description: "This also allows chapters and summary", + description: "Required for summary and chapters",
🧹 Nitpick comments (1)
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx (1)
83-131: Consider removing organizationSettings from dependencies.The
organizationSettingsdependency is only used in the error handler to revert state. Including it may cause unnecessary effect runs since the first effect (lines 70-81) already syncsorganizationSettingsto local state. You could remove it and accept that the error handler reverts to the organizationSettings value captured when the effect was registered, or refactor the error handling to be more explicit.If you choose to remove the dependency:
- }, [debouncedUpdateSettings, organizationSettings]); + }, [debouncedUpdateSettings]);This is a minor optimization and the current implementation is safe.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx(10 hunks)apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx(1 hunks)apps/web/app/(org)/dashboard/dashboard-data.ts(7 hunks)apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/web/app/(org)/dashboard/dashboard-data.ts
- apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
🧰 Additional context used
📓 Path-based instructions (6)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TanStack Query v5 for all client-side server state and data fetching in the web app
Web mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData rather than broad invalidations
Client code should use useEffectQuery/useEffectMutation and useRpcClient from apps/web/lib/EffectRuntime.ts; do not create ManagedRuntime inside components
Files:
apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx
apps/web/app/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Prefer Server Components for initial data in the Next.js App Router and pass initialData to client components
Files:
apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not add inline, block, or docstring comments in any language; code must be self-explanatory
Files:
apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use strict TypeScript and avoid any; leverage shared types from packages
**/*.{ts,tsx}: Use a 2-space indent for TypeScript code.
Use Biome for formatting and linting TypeScript/JavaScript files by runningpnpm format.
Files:
apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g.,user-menu.tsx).
Use PascalCase for React/Solid components.
Files:
apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, always use
useEffectQueryoruseEffectMutationfrom@/lib/EffectRuntime; never callEffectRuntime.run*directly in components.
Files:
apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsxapps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx
🧬 Code graph analysis (2)
apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx (2)
apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx (1)
SettingsDialog(69-226)apps/web/app/(org)/dashboard/caps/components/CapCard/CapCardButton.tsx (1)
CapCardButton(17-43)
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx (4)
apps/web/app/(org)/dashboard/Contexts.tsx (1)
useDashboardContext(50-50)apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-30)packages/utils/src/constants/plans.ts (1)
userIsPro(21-45)apps/web/actions/organization/settings.ts (1)
updateOrganizationSettings(9-44)
⏰ 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). (3)
- GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
- GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Analyze (rust)
🔇 Additional comments (11)
apps/web/app/(org)/dashboard/caps/components/CapCard/CapCard.tsx (8)
18-18: LGTM!The new imports for
faGearandSettingsDialogare properly utilized within the component.Also applies to: 46-46
77-84: LGTM!The
settingsobject is properly typed with optional boolean flags that align with theOrganizationSettingsinterface used inSettingsDialog.
126-126: LGTM!The state declaration follows the standard pattern for controlling dialog visibility.
301-306: LGTM!The
SettingsDialogis properly integrated with correct props matching the interface fromSettingsDialog.tsx.
345-369: Past review comments appear outdated; verify intentional UX asymmetry.The previous review comments flagged duplicate Download buttons for non-owners, but in the current code:
- Owners see a Settings button here + a dropdown menu (lines 411-483) containing Download
- Non-owners see a Download button here + no dropdown (dropdown is owner-only)
There is no duplicate for non-owners. However, the UX is asymmetric: non-owners get direct download access while owners must use the dropdown. Verify this is intentional.
429-438: LGTM!The Download menu item is properly implemented with consistent styling, proper event handling, and reuses the existing
handleDownloadfunction.
539-540: LGTM!The z-index and positioning adjustments ensure proper layering of the upload progress overlay with the new SettingsDialog.
413-413: Verify and remove unnecessary suppressHydrationWarningThe
suppressHydrationWarningprops in layout.tsx (line 107), Navbar/Items.tsx (line 97) and CapCard.tsx (lines 413 & 427) can mask real server-client markup mismatches on client components. Confirm there are actual hydration warnings before keeping them; otherwise remove these props and address the root causes.apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx (3)
133-151: LGTM! Toggle logic correctly handles dependencies.The special case for
disableTranscriptappropriately cascades todisableSummaryanddisableChapters, ensuring the transcript dependency constraint is enforced. The logic preserves user choices when re-enabling transcript.
163-198: LGTM! Render logic and disabled states are correct.The grid layout cleanly presents each option with appropriate disabled states:
- Pro features are gated for non-Pro users
- Summary and chapters are disabled when transcript is disabled
- The inverted checked state (
!settings?.[option.value]) ensures switches are ON when features are enabled, which is intuitive
31-34: Rephrase description to match "Enable" framing.The UI displays "Enable chapters" but the description says "Remove the chapters," which describes the opposite state. Update to something like "Show AI-generated chapters (requires transcript)" to match the enabled state.
Apply this diff:
- description: "Remove the chapters for caps (requires transcript)", + description: "Show AI-generated chapters (requires transcript)",Likely an incorrect or invalid review comment.
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx
Outdated
Show resolved
Hide resolved
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: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx(1 hunks)apps/web/app/(org)/dashboard/layout.tsx(3 hunks)apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TanStack Query v5 for all client-side server state and data fetching in the web app
Web mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData rather than broad invalidations
Client code should use useEffectQuery/useEffectMutation and useRpcClient from apps/web/lib/EffectRuntime.ts; do not create ManagedRuntime inside components
Files:
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
apps/web/app/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Prefer Server Components for initial data in the Next.js App Router and pass initialData to client components
Files:
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not add inline, block, or docstring comments in any language; code must be self-explanatory
Files:
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use strict TypeScript and avoid any; leverage shared types from packages
**/*.{ts,tsx}: Use a 2-space indent for TypeScript code.
Use Biome for formatting and linting TypeScript/JavaScript files by runningpnpm format.
Files:
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g.,user-menu.tsx).
Use PascalCase for React/Solid components.
Files:
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, always use
useEffectQueryoruseEffectMutationfrom@/lib/EffectRuntime; never callEffectRuntime.run*directly in components.
Files:
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
🧬 Code graph analysis (3)
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx (4)
apps/web/app/(org)/dashboard/Contexts.tsx (1)
useDashboardContext(50-50)apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-30)packages/utils/src/constants/plans.ts (1)
userIsPro(21-45)apps/web/actions/organization/settings.ts (1)
updateOrganizationSettings(9-44)
apps/web/app/(org)/dashboard/layout.tsx (1)
apps/web/app/(org)/dashboard/dashboard-data.ts (3)
OrganizationSettings(28-30)Spaces(32-38)getDashboardData(42-293)
apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx (4)
apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-30)apps/web/app/(org)/dashboard/Contexts.tsx (1)
useDashboardContext(50-50)packages/utils/src/constants/plans.ts (1)
userIsPro(21-45)apps/web/actions/videos/settings.ts (1)
updateVideoSettings(9-45)
⏰ 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). (3)
- GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
- GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Analyze (rust)
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: 0
🧹 Nitpick comments (3)
apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx (2)
101-102: Remove dead guard that's always false.
settingsis initialized frombuildSettings(settingsData)and always returns an object, soif (!settings)will never be true. Removing this guard simplifies the code without changing behavior.Apply this diff:
const saveHandler = async () => { - if (!settings) return; setSaveLoading(true); try {
146-152: Simplify redundant condition in getEffectiveValue.The condition
videoValue !== undefined || videoValue === trueworks correctly but the second part is redundant—videoValue !== undefinedalready handles all defined values includingtrue.Apply this diff:
const getEffectiveValue = (key: keyof OrganizationSettings) => { const videoValue = settings?.[key]; const orgValue = organizationSettings?.[key] ?? false; - return videoValue !== undefined || videoValue === true - ? videoValue - : orgValue; + return videoValue !== undefined ? videoValue : orgValue; };apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx (1)
107-115: Consider more robust label extraction for toast messages.The string manipulation
option?.label.split(" ")[1]assumes labels follow "Enable X" format. While it works for current labels, it's brittle and will break if label format changes. Consider extracting the feature name from the option value instead or using a label map.Example alternative:
changedKeys.forEach((changedKey) => { - const option = options.find((opt) => opt.value === changedKey); const isDisabled = debouncedUpdateSettings[changedKey]; const action = isDisabled ? "disabled" : "enabled"; - const label = option?.label.split(" ")[1] || changedKey; + const label = changedKey.replace("disable", "").replace(/([A-Z])/g, " $1").trim().toLowerCase(); toast.success( `${label.charAt(0).toUpperCase()}${label.slice(1)} ${action}`, ); });Or maintain a dedicated label map for feature names.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx(1 hunks)apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TanStack Query v5 for all client-side server state and data fetching in the web app
Web mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData rather than broad invalidations
Client code should use useEffectQuery/useEffectMutation and useRpcClient from apps/web/lib/EffectRuntime.ts; do not create ManagedRuntime inside components
Files:
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
apps/web/app/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Prefer Server Components for initial data in the Next.js App Router and pass initialData to client components
Files:
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not add inline, block, or docstring comments in any language; code must be self-explanatory
Files:
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use strict TypeScript and avoid any; leverage shared types from packages
**/*.{ts,tsx}: Use a 2-space indent for TypeScript code.
Use Biome for formatting and linting TypeScript/JavaScript files by runningpnpm format.
Files:
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g.,user-menu.tsx).
Use PascalCase for React/Solid components.
Files:
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, always use
useEffectQueryoruseEffectMutationfrom@/lib/EffectRuntime; never callEffectRuntime.run*directly in components.
Files:
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsxapps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx
🧬 Code graph analysis (2)
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx (4)
apps/web/app/(org)/dashboard/Contexts.tsx (1)
useDashboardContext(50-50)apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-30)packages/utils/src/constants/plans.ts (1)
userIsPro(21-45)apps/web/actions/organization/settings.ts (1)
updateOrganizationSettings(9-44)
apps/web/app/(org)/dashboard/caps/components/SettingsDialog.tsx (4)
apps/web/app/(org)/dashboard/dashboard-data.ts (1)
OrganizationSettings(28-30)apps/web/app/(org)/dashboard/Contexts.tsx (1)
useDashboardContext(50-50)packages/utils/src/constants/plans.ts (1)
userIsPro(21-45)apps/web/actions/videos/settings.ts (1)
updateVideoSettings(9-45)
⏰ 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). (3)
- GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
- GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Analyze (rust)
🔇 Additional comments (1)
apps/web/app/(org)/dashboard/settings/organization/components/CapSettingsCard.tsx (1)
151-197: LGTM!The JSX structure is clean and the component properly handles organization-level settings with debounced auto-save, per-key success notifications, and proper error recovery. The grid layout and Switch components are correctly configured with appropriate Pro gating and transcript dependency logic.
Summary by CodeRabbit
New Features
Improvements
Chores