Conversation
|
Warning Rate limit exceeded@tlgimenes has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 1 minutes and 24 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)
WalkthroughReplaces ResourceTable with CollectionTable, adds reusable collection UI primitives (page, header, search, display button, table wrapper, integration icon), simplifies card/table UIs and CollectionsList (schema-driven columns, new sortableFields), removes several legacy components (collection-table, user-indicator), and migrates many imports to the new collection-table types/components. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Page as CollectionPage
participant Header as CollectionHeader
participant Search as CollectionSearch
participant DisplayBtn as CollectionDisplayButton
participant Wrapper as CollectionTableWrapper
participant Cards as CardGrid
User->>Page: open collections view
Page->>Header: mount (provide viewMode, sort state)
Header->>DisplayBtn: render toggle & sort options
User->>Search: type query
Search->>Page: emit onChange(trimmed)
Page->>Wrapper: apply filter/sort -> update data
User->>DisplayBtn: toggle view (cards/table)
DisplayBtn->>Page: emit onViewModeChange
alt cards
Page->>Cards: render card grid (IntegrationIcon, title, desc)
Cards->>User: show cards
else table
Page->>Wrapper: render table view
Wrapper->>User: show rows (sorted/filtered)
end
User->>DisplayBtn: pick sort option
DisplayBtn->>Page: emit onSort(key)
Page->>Wrapper: re-sort & re-render
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings, 1 inconclusive)
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 |
Deploying decocms-admin-frontend with
|
| Latest commit: |
a53c6ed
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://d4b4815f.admin-decocms-frontend.pages.dev |
| Branch Preview URL: | https://valls-collection-ui.admin-decocms-frontend.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/mesh/src/web/components/collections/collection-card.tsx (1)
7-12: Remove unused props from interface.The
CollectionCardPropsinterface declaresreadOnlyandonActionprops (lines 10-11), but the component implementation doesn't use them. This creates confusion about the component's actual API surface.Apply this diff to align the interface with actual usage:
interface CollectionCardProps<T extends BaseCollectionEntity> { item: T; schema: z.AnyZodObject; - readOnly?: boolean; - onAction: (action: "open" | "delete" | "duplicate", item: T) => void; }apps/mesh/src/web/components/collections/collection-table.tsx (1)
9-18: Remove or document unused props in interface.The
CollectionTablePropsinterface declaresreadOnlyandonActionprops (lines 12-13), but the component implementation prefixes them with underscores (lines 23-24), indicating they're intentionally unused. Since the Actions column functionality was removed entirely, these props appear to be dead code in the public API.If these props are no longer needed, remove them from the interface:
interface CollectionTableProps<T extends BaseCollectionEntity> { data: T[]; schema: z.AnyZodObject; - readOnly?: boolean; - onAction: (action: "open" | "delete" | "duplicate", item: T) => void; sortKey?: string; sortDirection?: "asc" | "desc" | null; onSort?: (key: string) => void; onRowClick?: (item: T) => void; }And update the function signature:
export function CollectionTable<T extends BaseCollectionEntity>({ data, schema, - readOnly: _readOnly, - onAction: _onAction, sortKey, sortDirection, onSort, onRowClick, }: CollectionTableProps<T>) {If they're kept for backward compatibility, add a JSDoc comment explaining this.
Also applies to: 23-24
🧹 Nitpick comments (10)
apps/mesh/src/web/components/integration-icon.tsx (1)
4-9: Consider reusing the existing IntegrationIconProps interface.An
IntegrationIconPropsinterface already exists inapps/web/src/components/integrations/common.tsx(lines 4-9) with a more comprehensive set of size options ("xs" | "sm" | "base" | "lg" | "xl" | "2xl" | "3xl"). Duplicating this interface creates maintenance overhead and potential type inconsistencies.Consider importing and extending the existing interface, or adjusting the size mapping to align with the shared definition:
+import type { IntegrationIconProps as BaseIntegrationIconProps } from "apps/web/src/components/integrations/common.tsx"; + -interface IntegrationIconProps { - icon: string | null | undefined; - name: string; - size?: "sm" | "md" | "lg"; - className?: string; -} +interface IntegrationIconProps extends Omit<BaseIntegrationIconProps, 'icon'> { + icon: string | null | undefined; +}Alternatively, if the simplified size options are intentional for this context, consider renaming to avoid confusion (e.g.,
IntegrationIconDisplayProps).apps/mesh/src/web/components/collections/collection-table-wrapper.tsx (1)
26-32: Consider using a loading spinner for better visual feedback.The coding guidelines recommend "loading spinners" for proper UI feedback. A simple text message may not provide sufficient visual indication of loading state.
+import { Loader2 } from "lucide-react"; + // In the loading block: if (isLoading) { return ( <div className="flex items-center justify-center h-full"> - <div className="text-muted-foreground">Loading...</div> + <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" /> </div> ); }apps/mesh/src/web/components/collections/collection-display-button.tsx (2)
79-116: Add accessibility attributes to view mode toggle buttons.The toggle buttons lack accessibility attributes. Screen readers won't announce which view mode is currently active.
<button ref={tableRef} type="button" + aria-pressed={viewMode === "table"} + aria-label="Table view" onClick={() => { onViewModeChange("table"); }} className="relative z-10 flex-1 flex items-center justify-center gap-2 h-12 px-4 rounded-lg" > ... </button> <button ref={cardsRef} type="button" + aria-pressed={viewMode === "cards"} + aria-label="Cards view" onClick={() => { onViewModeChange("cards"); }} className="relative z-10 flex-1 flex items-center justify-center gap-2 h-12 px-4 rounded-lg" >
54-63: ConsiderrequestAnimationFrameinstead ofsetTimeout(0)for more reliable DOM measurement timing.
setTimeout(0)can be unreliable for post-render DOM measurements.requestAnimationFrameensures the callback runs after the browser has painted.onOpenChange={(open) => { if (open) { - setTimeout(() => { + requestAnimationFrame(() => { const ref = viewMode === "table" ? tableRef : cardsRef; updateIndicator(ref); - }, 0); + }); } }}apps/mesh/src/web/routes/orgs/connections.tsx (3)
214-214: Address the TODO: hardcodedcreated_byvalue.The
created_byfield is hardcoded to"system", which will produce incorrect audit trails. Consider using a user context hook to get the actual user ID.Would you like me to open an issue to track this, or help implement user ID retrieval from context?
510-520: ConsideruseDeferredValuefor search to prevent blocking user input.Per coding guidelines,
useDeferredValueshould be used for search operations to keep the input responsive during filtering. This is especially important as the connections list grows.import { useDeferredValue } from "react"; // In the component: const deferredSearch = useDeferredValue(listState.search); // Pass deferredSearch to the data-fetching hook instead of listState.search // Keep listState.search for the input value to maintain responsive typingBased on learnings, useDeferredValue prevents blocking user input during filtering.
525-528: Loading UI is duplicated between cards view andCollectionTableWrapper.Consider extracting the loading state into a shared component or pattern to maintain consistency and reduce duplication.
apps/mesh/src/web/components/details/connection.tsx (3)
698-713: Consider usinguseDeferredValuefor search to prevent blocking user input.Per coding guidelines, search operations should use
useDeferredValueto prevent blocking user input during filtering. Additionally, the sorting state cycle logic is correct but could be simplified.const [search, setSearch] = useState(""); +const deferredSearch = useDeferredValue(search); const [viewMode, setViewMode] = useState<"table" | "cards">("table"); const [sortKey, setSortKey] = useState<string | undefined>("name"); const [sortDirection, setSortDirection] = useState<"asc" | "desc" | null>( "asc", ); const handleSort = (key: string) => { if (sortKey === key) { - setSortDirection((prev) => - prev === "asc" ? "desc" : prev === "desc" ? null : "asc", - ); - if (sortDirection === "desc") setSortKey(undefined); + if (sortDirection === "asc") { + setSortDirection("desc"); + } else if (sortDirection === "desc") { + setSortKey(undefined); + setSortDirection(null); + } else { + setSortDirection("asc"); + } } else { setSortKey(key); setSortDirection("asc"); } };Then update the
filteredToolsdependency to usedeferredSearch:const filteredTools = useMemo(() => { if (!tools || tools.length === 0) return []; - if (!search.trim()) return tools; - const searchLower = search.toLowerCase(); + if (!deferredSearch.trim()) return tools; + const searchLower = deferredSearch.toLowerCase(); return tools.filter( (t) => t.name.toLowerCase().includes(searchLower) || (t.description && t.description.toLowerCase().includes(searchLower)), ); -}, [tools, search]); +}, [tools, deferredSearch]);
726-735: Casting toRecord<string, unknown>could be avoided with better typing.The cast
(a as unknown as Record<string, unknown>)is a workaround for accessing dynamic keys. Since the tool type is{ name: string; description?: string }, you could simplify this with a type guard or index signature.const sortedTools = useMemo(() => { if (!sortKey || !sortDirection) return filteredTools; return [...filteredTools].sort((a, b) => { - const aVal = (a as unknown as Record<string, unknown>)[sortKey] || ""; - const bVal = (b as unknown as Record<string, unknown>)[sortKey] || ""; + const aVal = sortKey === "name" ? a.name : (a.description ?? ""); + const bVal = sortKey === "name" ? b.name : (b.description ?? ""); const comparison = String(aVal).localeCompare(String(bVal)); return sortDirection === "asc" ? comparison : -comparison; }); }, [filteredTools, sortKey, sortDirection]);
977-995: Duplicated sort options generation logic betweenToolsListandCollectionContent.Both components generate sort options from schema/columns with similar filtering logic. Consider extracting this into a shared utility function for consistency and maintainability.
You could create a shared helper:
// In a shared utils file export function generateSortOptionsFromSchema( schema: z.AnyZodObject, excludeFields: string[] = ["id", "created_at", "updated_at", "created_by", "updated_by", "organization_id"] ): Array<{ id: string; label: string }> { return Object.keys(schema.shape) .filter((key) => !excludeFields.includes(key)) .map((key) => ({ id: key, label: key.charAt(0).toUpperCase() + key.slice(1).replace(/_/g, " "), })); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
apps/mesh/public/emptystate-mcp.svgis excluded by!**/*.svg
📒 Files selected for processing (18)
apps/mesh/src/web/components/collections/collection-card.tsx(3 hunks)apps/mesh/src/web/components/collections/collection-display-button.tsx(1 hunks)apps/mesh/src/web/components/collections/collection-header.tsx(1 hunks)apps/mesh/src/web/components/collections/collection-page.tsx(1 hunks)apps/mesh/src/web/components/collections/collection-search.tsx(1 hunks)apps/mesh/src/web/components/collections/collection-table-wrapper.tsx(1 hunks)apps/mesh/src/web/components/collections/collection-table.tsx(4 hunks)apps/mesh/src/web/components/collections/collections-list.tsx(2 hunks)apps/mesh/src/web/components/collections/types.ts(1 hunks)apps/mesh/src/web/components/details/connection.tsx(6 hunks)apps/mesh/src/web/components/details/layout.tsx(1 hunks)apps/mesh/src/web/components/empty-state.tsx(1 hunks)apps/mesh/src/web/components/empty-states/search-empty-state.tsx(1 hunks)apps/mesh/src/web/components/integration-icon.tsx(1 hunks)apps/mesh/src/web/routes/orgs/connections.tsx(10 hunks)packages/ui/src/components/deco-chat-aside.tsx(1 hunks)packages/ui/src/components/resource-table.tsx(3 hunks)packages/ui/src/styles/global.css(1 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/data-flow.mdc)
Handle loading and error states appropriately when using React Query hooks in components
Files:
packages/ui/src/components/deco-chat-aside.tsxapps/mesh/src/web/components/collections/collection-page.tsxapps/mesh/src/web/components/empty-states/search-empty-state.tsxapps/mesh/src/web/components/collections/collection-search.tsxapps/mesh/src/web/components/empty-state.tsxapps/mesh/src/web/components/collections/collection-header.tsxapps/mesh/src/web/components/collections/collection-display-button.tsxapps/mesh/src/web/components/details/layout.tsxapps/mesh/src/web/components/integration-icon.tsxapps/mesh/src/web/components/collections/collection-card.tsxapps/mesh/src/web/components/details/connection.tsxapps/mesh/src/web/components/collections/collections-list.tsxpackages/ui/src/components/resource-table.tsxapps/mesh/src/web/components/collections/collection-table-wrapper.tsxapps/mesh/src/web/routes/orgs/connections.tsxapps/mesh/src/web/components/collections/collection-table.tsx
**/*.{ts,tsx,js,jsx,css}
📄 CodeRabbit inference engine (.cursor/rules/structure.mdc)
Run formatting with
bun run fmtbefore opening pull requestsKeep Tailwind design tokens consistent per
plugins/ensure-tailwind-design-system-tokens.tswhich will fail builds otherwise
Files:
packages/ui/src/components/deco-chat-aside.tsxpackages/ui/src/styles/global.cssapps/mesh/src/web/components/collections/collection-page.tsxapps/mesh/src/web/components/empty-states/search-empty-state.tsxapps/mesh/src/web/components/collections/collection-search.tsxapps/mesh/src/web/components/empty-state.tsxapps/mesh/src/web/components/collections/collection-header.tsxapps/mesh/src/web/components/collections/collection-display-button.tsxapps/mesh/src/web/components/details/layout.tsxapps/mesh/src/web/components/integration-icon.tsxapps/mesh/src/web/components/collections/collection-card.tsxapps/mesh/src/web/components/details/connection.tsxapps/mesh/src/web/components/collections/collections-list.tsxpackages/ui/src/components/resource-table.tsxapps/mesh/src/web/components/collections/types.tsapps/mesh/src/web/components/collections/collection-table-wrapper.tsxapps/mesh/src/web/routes/orgs/connections.tsxapps/mesh/src/web/components/collections/collection-table.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/structure.mdc)
Run type checking with
bun run checkbefore opening pull requestsFavor TypeScript types over
anykeyword
**/*.{ts,tsx}: Write concise, maintainable, and technically accurate TypeScript code with relevant examples
Use functional and declarative programming patterns; avoid classes
Favor iteration and modularization to adhere to DRY principles and avoid code duplication
Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)
Organize files systematically: each file should contain only related content, such as exported components, subcomponents, helpers, static content, and types
Favor named exports for functions
Use TypeScript for all code
Prefer interfaces over types for their extendability and ability to merge
Avoid enums; use maps instead for better type safety and flexibility
Use the "function" keyword for pure functions to benefit from hoisting and clarity
Files:
packages/ui/src/components/deco-chat-aside.tsxapps/mesh/src/web/components/collections/collection-page.tsxapps/mesh/src/web/components/empty-states/search-empty-state.tsxapps/mesh/src/web/components/collections/collection-search.tsxapps/mesh/src/web/components/empty-state.tsxapps/mesh/src/web/components/collections/collection-header.tsxapps/mesh/src/web/components/collections/collection-display-button.tsxapps/mesh/src/web/components/details/layout.tsxapps/mesh/src/web/components/integration-icon.tsxapps/mesh/src/web/components/collections/collection-card.tsxapps/mesh/src/web/components/details/connection.tsxapps/mesh/src/web/components/collections/collections-list.tsxpackages/ui/src/components/resource-table.tsxapps/mesh/src/web/components/collections/types.tsapps/mesh/src/web/components/collections/collection-table-wrapper.tsxapps/mesh/src/web/routes/orgs/connections.tsxapps/mesh/src/web/components/collections/collection-table.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/structure.mdc)
Run linting with
bun run lintbefore opening pull requests
**/*.{ts,tsx,js,jsx}: Use PascalCase for component and class names
Use camelCase for hooks and utility function names
Files:
packages/ui/src/components/deco-chat-aside.tsxapps/mesh/src/web/components/collections/collection-page.tsxapps/mesh/src/web/components/empty-states/search-empty-state.tsxapps/mesh/src/web/components/collections/collection-search.tsxapps/mesh/src/web/components/empty-state.tsxapps/mesh/src/web/components/collections/collection-header.tsxapps/mesh/src/web/components/collections/collection-display-button.tsxapps/mesh/src/web/components/details/layout.tsxapps/mesh/src/web/components/integration-icon.tsxapps/mesh/src/web/components/collections/collection-card.tsxapps/mesh/src/web/components/details/connection.tsxapps/mesh/src/web/components/collections/collections-list.tsxpackages/ui/src/components/resource-table.tsxapps/mesh/src/web/components/collections/types.tsapps/mesh/src/web/components/collections/collection-table-wrapper.tsxapps/mesh/src/web/routes/orgs/connections.tsxapps/mesh/src/web/components/collections/collection-table.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Keep imports sorted in all code files
Files:
packages/ui/src/components/deco-chat-aside.tsxapps/mesh/src/web/components/collections/collection-page.tsxapps/mesh/src/web/components/empty-states/search-empty-state.tsxapps/mesh/src/web/components/collections/collection-search.tsxapps/mesh/src/web/components/empty-state.tsxapps/mesh/src/web/components/collections/collection-header.tsxapps/mesh/src/web/components/collections/collection-display-button.tsxapps/mesh/src/web/components/details/layout.tsxapps/mesh/src/web/components/integration-icon.tsxapps/mesh/src/web/components/collections/collection-card.tsxapps/mesh/src/web/components/details/connection.tsxapps/mesh/src/web/components/collections/collections-list.tsxpackages/ui/src/components/resource-table.tsxapps/mesh/src/web/components/collections/types.tsapps/mesh/src/web/components/collections/collection-table-wrapper.tsxapps/mesh/src/web/routes/orgs/connections.tsxapps/mesh/src/web/components/collections/collection-table.tsx
packages/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Enforce kebab-case filenames in shared packages via
plugins/enforce-kebab-case-file-names.ts
Files:
packages/ui/src/components/deco-chat-aside.tsxpackages/ui/src/components/resource-table.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react-ts.mdc)
**/*.tsx: Use functional components with TypeScript interfaces
Favor using the already-present ui components inpackages/uifolder instead of creating custom components
Use useMemo for expensive computations like filtering and sorting operations to optimize performance in data-intensive applications
Memoize objects and arrays using useMemo to maintain stable references across renders
Use useDeferredValue for search operations to prevent blocking user input during filtering
Follow MCP (Model Context Protocol) patterns for consistent data fetching with hooks like useAgents, useIntegrations, and useUpdateAgent
Use react-hook-form with Zod validation instead of manual useState for form management
Avoid prop drilling by using Form Context to share form state across components
Use design system Form components (Form, FormControl, FormField, FormItem, FormLabel, FormMessage) from @deco/ui with proper error handling
Apply Single Responsibility Principle to components: each component should have a focused purpose and be composable
Ensure dependency arrays contain stable references; avoid creating inline objects or arrays that cause unnecessary re-renders
Implement consistent error and loading state handling with proper UI feedback (loading spinners, error messages, empty states)
Apply changes immediately to DOM for instant visual feedback, then debounce state updates for features like theme editors and live previews
Use custom events dispatched via window.dispatchEvent and window.addEventListener for cross-component communication of state updates
Implement single-level undo that reverts to the saved state, not just the previous change; use refs to track original saved values
Use useSetThreadContextEffect to inject rules and toolsets into AI chat threads; use explicit union types for context items
Extract complex logic from JSX into separate components instead of using IIFEs (immediately invoked function expressions)
Files:
packages/ui/src/components/deco-chat-aside.tsxapps/mesh/src/web/components/collections/collection-page.tsxapps/mesh/src/web/components/empty-states/search-empty-state.tsxapps/mesh/src/web/components/collections/collection-search.tsxapps/mesh/src/web/components/empty-state.tsxapps/mesh/src/web/components/collections/collection-header.tsxapps/mesh/src/web/components/collections/collection-display-button.tsxapps/mesh/src/web/components/details/layout.tsxapps/mesh/src/web/components/integration-icon.tsxapps/mesh/src/web/components/collections/collection-card.tsxapps/mesh/src/web/components/details/connection.tsxapps/mesh/src/web/components/collections/collections-list.tsxpackages/ui/src/components/resource-table.tsxapps/mesh/src/web/components/collections/collection-table-wrapper.tsxapps/mesh/src/web/routes/orgs/connections.tsxapps/mesh/src/web/components/collections/collection-table.tsx
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/api-development.mdc)
Define both input and output Zod schemas for all API operations with appropriate type constraints (min/max length, optional fields, descriptions) and map them to TypeScript interfaces
Files:
apps/mesh/src/web/components/collections/types.ts
🧠 Learnings (27)
📚 Learning: 2025-12-01T21:09:54.719Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: docs/.cursor/rules/main.mdc:0-0
Timestamp: 2025-12-01T21:09:54.719Z
Learning: Applies to docs/view/{astro.config.mjs,src/styles/global.css} : Customize theme through view/astro.config.mjs for basic configuration and view/src/styles/global.css for Tailwind CSS theming including fonts and colors
Applied to files:
packages/ui/src/styles/global.css
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Use functional components with TypeScript interfaces
Applied to files:
apps/mesh/src/web/components/collections/collection-page.tsxapps/mesh/src/web/components/collections/collection-card.tsxapps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:09:05.323Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/structure.mdc:0-0
Timestamp: 2025-12-01T21:09:05.323Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use React 19 for UI development in the decocms admin shell and marketplace
Applied to files:
apps/mesh/src/web/components/collections/collection-page.tsxapps/mesh/src/web/components/collections/collection-card.tsxapps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Implement consistent error and loading state handling with proper UI feedback (loading spinners, error messages, empty states)
Applied to files:
apps/mesh/src/web/components/empty-states/search-empty-state.tsxapps/mesh/src/web/components/empty-state.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Use useDeferredValue for search operations to prevent blocking user input during filtering
Applied to files:
apps/mesh/src/web/components/collections/collection-search.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Use design system Form components (Form, FormControl, FormField, FormItem, FormLabel, FormMessage) from deco/ui with proper error handling
Applied to files:
apps/mesh/src/web/components/collections/collection-search.tsxapps/mesh/src/web/components/collections/collection-card.tsxapps/mesh/src/web/components/details/connection.tsxapps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to apps/web/src/components/layout/*.tsx : Conditionally render AI chat panel based on current route to show it only on specific pages where it provides value
Applied to files:
apps/mesh/src/web/components/empty-state.tsx
📚 Learning: 2025-12-01T21:09:05.323Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/structure.mdc:0-0
Timestamp: 2025-12-01T21:09:05.323Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use shadcn/ui shared design system components from packages/ui
Applied to files:
apps/mesh/src/web/components/integration-icon.tsxapps/mesh/src/web/components/collections/collection-card.tsxapps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to apps/web/src/components/integrations/apps.ts : Add native app to NATIVE_APPS array with id prefixed with 'native:::', descriptive name, icon, and provider set to 'native'
Applied to files:
apps/mesh/src/web/components/integration-icon.tsx
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to apps/web/src/components/**/*-view.tsx : Use explicit union type annotation for threadContextItems array: Array<{ id: string; type: 'rule'; text: string } | { id: string; type: 'toolset'; integrationId: string; enabledTools: string[] }>
Applied to files:
apps/mesh/src/web/components/integration-icon.tsxapps/mesh/src/web/components/collections/collection-card.tsxapps/mesh/src/web/components/details/connection.tsxapps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Favor using the already-present ui components in `packages/ui` folder instead of creating custom components
Applied to files:
apps/mesh/src/web/components/collections/collection-card.tsxapps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:07:47.300Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/data-flow.mdc:0-0
Timestamp: 2025-12-01T21:07:47.300Z
Learning: Applies to **/*{tools,api,index}*.ts : Organize MCP tools into typed collections (GLOBAL_TOOLS, WORKSPACE_TOOLS, AGENT_TOOLS, EMAIL_TOOLS) by functionality and scope
Applied to files:
apps/mesh/src/web/components/details/connection.tsx
📚 Learning: 2025-12-01T22:44:21.356Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/api-development.mdc:0-0
Timestamp: 2025-12-01T22:44:21.356Z
Learning: Applies to packages/sdk/src/mcp/index.ts : Export all new API tools in the WORKSPACE_TOOLS array with proper import statements from feature-specific api.ts files
Applied to files:
apps/mesh/src/web/components/details/connection.tsx
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to apps/web/src/components/chat/provider.tsx : In chat provider, handle tool calls and invalidate/refetch queries when AI updates features; dispatch custom events for UI updates
Applied to files:
apps/mesh/src/web/components/details/connection.tsx
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to apps/web/src/components/sidebar/index.tsx : Update sidebar navigation by adding feature name to wellKnownItems array and resourceTypeOrder array
Applied to files:
apps/mesh/src/web/components/details/connection.tsxapps/mesh/src/web/components/collections/collections-list.tsx
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to apps/web/src/components/**/*-view.tsx : In main view components, use `useSetThreadContextEffect` hook to inject context items (rules and toolsets) for AI chat integration
Applied to files:
apps/mesh/src/web/components/details/connection.tsxapps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:09:54.719Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: docs/.cursor/rules/main.mdc:0-0
Timestamp: 2025-12-01T21:09:54.719Z
Learning: Applies to docs/server/**/*.ts : Define tools as functions that create tool instances with id, description, inputSchema, outputSchema, and execute method in server/main.ts
Applied to files:
apps/mesh/src/web/components/details/connection.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Follow MCP (Model Context Protocol) patterns for consistent data fetching with hooks like useAgents, useIntegrations, and useUpdateAgent
Applied to files:
apps/mesh/src/web/components/details/connection.tsxapps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Use react-hook-form with Zod validation instead of manual useState for form management
Applied to files:
apps/mesh/src/web/components/details/connection.tsxapps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:09:54.719Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: docs/.cursor/rules/main.mdc:0-0
Timestamp: 2025-12-01T21:09:54.719Z
Learning: Applies to docs/server/**/*.ts : Use Zod (z.object) for defining inputSchema and outputSchema in tools and workflows
Applied to files:
apps/mesh/src/web/components/details/connection.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Ensure dependency arrays contain stable references; avoid creating inline objects or arrays that cause unnecessary re-renders
Applied to files:
apps/mesh/src/web/components/collections/collections-list.tsx
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to apps/web/src/components/**/resource-list.tsx : Create resource list component that uses `useTrackNativeViewVisit` hook to track view visits for recents and pinning functionality
Applied to files:
apps/mesh/src/web/components/collections/collections-list.tsxapps/mesh/src/web/components/collections/collection-table-wrapper.tsx
📚 Learning: 2025-12-01T21:08:08.813Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/deconfig.mdc:0-0
Timestamp: 2025-12-01T21:08:08.813Z
Learning: Applies to packages/sdk/src/mcp/deconfig/**/*.ts : Implement modular composition where merge() reuses diff() + transactionalWrite(), and transactionalWrite() has internal method for different scenarios to ensure code reuse and consistency
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Avoid prop drilling by using Form Context to share form state across components
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to apps/web/src/components/*-editor/*.tsx : Use debounced form updates with immediate DOM manipulation for real-time visual feedback in editors
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to packages/sdk/src/hooks/*.ts : Create React Query hooks using `useQuery` for data fetching and `useMutation` for updates, with proper cache invalidation on success
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:07:47.300Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/data-flow.mdc:0-0
Timestamp: 2025-12-01T21:07:47.300Z
Learning: Applies to **/*.{tsx,jsx} : Handle loading and error states appropriately when using React Query hooks in components
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
🧬 Code graph analysis (8)
apps/mesh/src/web/components/collections/collection-header.tsx (1)
apps/mesh/src/web/components/collections/collection-display-button.tsx (1)
CollectionDisplayButton(21-179)
apps/mesh/src/web/components/collections/collection-display-button.tsx (1)
packages/ui/src/components/dropdown-menu.tsx (4)
DropdownMenu(242-242)DropdownMenuTrigger(256-256)DropdownMenuContent(244-244)DropdownMenuItem(246-246)
apps/mesh/src/web/components/integration-icon.tsx (1)
apps/web/src/components/integrations/common.tsx (1)
IntegrationIconProps(5-10)
apps/mesh/src/web/components/collections/collection-card.tsx (2)
packages/ui/src/components/card.tsx (1)
Card(79-79)apps/mesh/src/web/components/integration-icon.tsx (1)
IntegrationIcon(11-59)
apps/mesh/src/web/components/collections/collections-list.tsx (5)
apps/mesh/src/web/components/collections/types.ts (1)
CollectionsListProps(7-132)apps/mesh/src/web/components/collections/collection-display-button.tsx (1)
CollectionDisplayButton(21-179)apps/mesh/src/web/components/empty-state.tsx (1)
EmptyState(28-63)apps/mesh/src/web/components/collections/collection-card.tsx (1)
CollectionCard(64-97)apps/mesh/src/web/components/collections/collection-table-wrapper.tsx (1)
CollectionTableWrapper(16-58)
packages/ui/src/components/resource-table.tsx (1)
packages/ui/src/components/table.tsx (3)
TableHeader(114-114)TableRow(115-115)TableHead(113-113)
apps/mesh/src/web/components/collections/collection-table-wrapper.tsx (1)
packages/ui/src/components/resource-table.tsx (2)
ResourceTable(34-133)ResourceTable(136-136)
apps/mesh/src/web/components/collections/collection-table.tsx (1)
apps/mesh/src/web/components/collections/user-indicator.tsx (1)
UserIndicator(24-54)
🪛 GitHub Actions: Tests
apps/mesh/src/web/components/collections/collections-list.tsx
[error] 90-90: Type '((mode: "table" | "cards") => void) | undefined' is not assignable to type '(mode: "table" | "cards") => void'.
⏰ 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)
- GitHub Check: Cloudflare Pages
🔇 Additional comments (26)
packages/ui/src/components/deco-chat-aside.tsx (1)
44-44: LGTM! Header height increase aligns with collection UI updates.The height increase from
h-10toh-12is intentional and consistent with the PR's goal of standardizing header layouts across the collection UI. The flex layout structure will adapt properly to the increased header height.packages/ui/src/styles/global.css (1)
30-30: The--cardcolor change is valid and requires no action.The
--cardvariable at line 30 has been updated tooklch(1 0 0), matching the--card-foregroundapproach established in the design system. Visual distinction is maintained through borders (--border: oklch(0.85 0 0)) and foreground colors (--card-foreground: oklch(0.205 0 0)). The design system validation plugin is currently disabled and only applies to JSX className attributes, not CSS custom properties, so no design system validation check is needed for this CSS file.apps/mesh/src/web/components/collections/collection-page.tsx (1)
1-13: LGTM! Clean wrapper component.The implementation is straightforward and follows functional component patterns with proper TypeScript interfaces. The component serves as a focused layout container for collection pages.
apps/mesh/src/web/components/integration-icon.tsx (1)
29-41: LGTM! Proper fallback handling.The icon rendering logic correctly handles both the presence and absence of icon URLs with appropriate fallback UI.
apps/mesh/src/web/components/empty-states/search-empty-state.tsx (1)
1-17: LGTM! Consistent empty state implementation.The component follows proper empty state patterns and provides clear user feedback for empty search results. The use of HTML entities for quotes and the default
entityNameparameter enhance reusability.apps/mesh/src/web/components/collections/collection-card.tsx (1)
78-95: LGTM! Simplified card rendering.The updated card layout using
IntegrationIconprovides a clean, consistent presentation with proper fallback for missing descriptions.packages/ui/src/components/resource-table.tsx (2)
43-55: Improved sort icon rendering.The fixed-width container with conditional rendering prevents layout shifts when toggling sort states, providing a better user experience.
57-62: LGTM! Updated header styling.The refined header styling with reduced height (h-9) and tracking adjustments creates a more compact, polished table header appearance.
apps/mesh/src/web/components/collections/collection-table.tsx (1)
35-36: LGTM! Enhanced sortability.Adding sortable flags to columns by default (excluding "actions") provides a better user experience and aligns with the broader collection UI improvements in this PR.
Also applies to: 45-46, 60-61, 83-84
apps/mesh/src/web/components/empty-state.tsx (1)
43-47: LGTM! Enhanced image rendering control.The updated condition (
image !== null) provides better API flexibility:
undefined→ shows default illustrationnull→ hides image section entirely- Custom ReactNode → shows custom image
This allows consumers to explicitly control whether the image section appears.
apps/mesh/src/web/components/collections/types.ts (1)
114-119: LGTM! Well-documented type addition.The new
sortableFieldsprop is clearly documented with its purpose, default behavior, and usage patterns. This provides fine-grained control over column sortability in the collection UI.apps/mesh/src/web/components/collections/collection-search.tsx (1)
21-45: LGTM!Clean presentational component that properly delegates state management to the parent. The use of design system components (
Icon,Input) and TypeScript interface aligns with coding guidelines.apps/mesh/src/web/components/collections/collection-table-wrapper.tsx (1)
46-57: LGTM!The data rendering path correctly delegates to
ResourceTablewith all necessary props forwarded. The overflow container ensures proper scrolling behavior.apps/mesh/src/web/components/collections/collection-header.tsx (1)
15-43: LGTM!Well-structured header component that follows the Single Responsibility Principle. Clean composition of
CollectionDisplayButtonwith proper prop forwarding and sensible defaults.apps/mesh/src/web/components/details/layout.tsx (1)
44-67: LGTM!The header restructuring aligns well with the new collection-driven UI pattern. The use of
ml-autofor action alignment and the icon-only back button provide a cleaner, more compact layout.apps/mesh/src/web/components/collections/collection-display-button.tsx (1)
130-175: LGTM!The sort options section has good UX with clear visual indicators for the selected option and sort direction. The conditional rendering based on
sortOptions.length > 0 && onSortis appropriate.apps/mesh/src/web/routes/orgs/connections.tsx (1)
329-626: Good integration of the new collection UI components.The component properly uses
react-hook-formwith Zod validation, dialog state management viauseReducer, and the new collection-based layout pattern. The separation between cards and table views is well-handled.apps/mesh/src/web/components/details/connection.tsx (5)
4-10: LGTM! Clean import organization for new collection UI components.The new imports are well-organized and bring in the necessary components for the enhanced collection UI.
53-53: LGTM! Layout components imported for structured view composition.The
ViewLayout,ViewTabs, andViewActionsimports enable a consistent layout pattern across views.
279-324: LGTM! Improved conditional rendering with cleaner structure.The restructured conditional rendering provides clear separation between authentication states, tools view, settings, and collection content. The use of wrapper divs with consistent padding improves layout uniformity.
768-868: LGTM! Well-structured tools list UI with proper empty states.The implementation properly handles:
- Search with escape key to clear
- Toggle between card and table views
- Consistent empty state messaging for both views
- Click-based navigation to tool details
997-1054: LGTM! CollectionContent properly integrates with the new collection UI components.The component correctly:
- Uses
ViewActionsfor consistent toolbar placement- Implements search with escape key handling
- Passes schema-derived sort options to
CollectionDisplayButton- Uses
hideToolbar={true}onCollectionsListto avoid duplicate controlsapps/mesh/src/web/components/collections/collections-list.tsx (4)
2-9: LGTM! Imports updated for new component dependencies.The new imports align with the component's enhanced functionality for table/card views and sorting.
38-74: LGTM! Sort options generation logic is well-structured.The implementation correctly:
- Derives options from columns when available, falling back to schema
- Filters out internal fields consistently
- Respects the
sortableFieldsprop for customization- Generates human-readable labels from field keys
121-144: LGTM! Card grid rendering with proper fallback chain.The implementation properly handles:
- Custom
renderCardfunction when provided- Schema-based
CollectionCardas secondary option- Basic card fallback when neither is available
- Click handlers with appropriate cursor styling
176-217: LGTM! Well-designed schema-to-columns generator.The
generateColumnsFromSchemahelper:
- Correctly filters out internal fields
- Provides special date formatting for
_atsuffixed fields- Handles null/undefined/object values gracefully
- Respects
sortableFieldsfor sortability control
| <EmptyState | ||
| icon="inbox" | ||
| title="No items found" | ||
| description={ | ||
| search ? "Try adjusting your search" : "No items to display" | ||
| } | ||
| /> |
There was a problem hiding this comment.
EmptyState prop mismatch: icon should be image.
According to the EmptyState component signature in the codebase, it expects an image prop (which can be a ReactNode or null), not an icon prop. This will cause a runtime error or the icon won't render.
<EmptyState
- icon="inbox"
+ image={null}
title="No items found"
description={
search ? "Try adjusting your search" : "No items to display"
}
/>Apply the same fix at lines 161-167:
<EmptyState
- icon="inbox"
+ image={null}
title="No items found"
description={
search ? "Try adjusting your search" : "No items to display"
}
/>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <EmptyState | |
| icon="inbox" | |
| title="No items found" | |
| description={ | |
| search ? "Try adjusting your search" : "No items to display" | |
| } | |
| /> | |
| <EmptyState | |
| image={null} | |
| title="No items found" | |
| description={ | |
| search ? "Try adjusting your search" : "No items to display" | |
| } | |
| /> |
| <EmptyState | |
| icon="inbox" | |
| title="No items found" | |
| description={ | |
| search ? "Try adjusting your search" : "No items to display" | |
| } | |
| /> | |
| <EmptyState | |
| image={null} | |
| title="No items found" | |
| description={ | |
| search ? "Try adjusting your search" : "No items to display" | |
| } | |
| /> |
🤖 Prompt for AI Agents
In apps/mesh/src/web/components/collections/collections-list.tsx around lines
111-117 and 161-167, the EmptyState component is being passed an icon prop but
its API expects image (ReactNode|null); replace icon="inbox" with image={<Icon
name="inbox" />} or the appropriate ReactNode (or null) in both locations so the
prop matches the component signature and the icon renders without runtime
errors.
| const collection = useConnectionsCollection(); | ||
| const { data: connections, isLoading, isError } = useConnections(listState); | ||
| const { data: connections, isLoading } = useConnections(listState); |
There was a problem hiding this comment.
Handle error state from useConnections hook.
The coding guidelines require "Handle loading and error states appropriately when using React Query hooks." The isLoading state is handled, but error state is not destructured or displayed to users.
- const { data: connections, isLoading } = useConnections(listState);
+ const { data: connections, isLoading, error } = useConnections(listState);Then render an error state when error is truthy, or at minimum show a toast notification.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const collection = useConnectionsCollection(); | |
| const { data: connections, isLoading, isError } = useConnections(listState); | |
| const { data: connections, isLoading } = useConnections(listState); | |
| const collection = useConnectionsCollection(); | |
| const { data: connections, isLoading, error } = useConnections(listState); |
🤖 Prompt for AI Agents
In apps/mesh/src/web/routes/orgs/connections.tsx around lines 110-111, the call
to useConnections only destructures isLoading but not error; update the hook
call to also destructure error, then handle it by rendering an error state
(e.g., an inline error message or ErrorFallback component) or at minimum fire a
toast notification and return early so the rest of the component does not
attempt to render with invalid data; keep the existing isLoading handling and
ensure any error details are surfaced (and optionally logged) for debugging.
| aria-hidden="true" | ||
| /> | ||
| } | ||
| title={listState.search ? "No MCPs found" : "No MCPs found"} |
There was a problem hiding this comment.
Redundant ternary - both branches have the same title.
The ternary condition evaluates to "No MCPs found" regardless of listState.search. Consider differentiating the messaging, e.g., "No results" vs "No MCPs yet".
- title={listState.search ? "No MCPs found" : "No MCPs found"}
+ title={listState.search ? "No results" : "No MCPs yet"}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| title={listState.search ? "No MCPs found" : "No MCPs found"} | |
| title={listState.search ? "No results" : "No MCPs yet"} |
🤖 Prompt for AI Agents
In apps/mesh/src/web/routes/orgs/connections.tsx around line 540, the title prop
uses a redundant ternary that returns "No MCPs found" for both branches; replace
it with a meaningful conditional message (for example, when listState.search is
truthy use "No results" or "No MCPs found for your search", otherwise use "No
MCPs yet" or "No MCPs found") so the UI communicates different states; update
the ternary or switch to a small helper that returns the appropriate string and
ensure any i18n keys are used if applicable.
| col.wrap | ||
| ? "whitespace-normal break-words" | ||
| ? "whitespace-normal wrap-break-word" | ||
| : "truncate overflow-hidden whitespace-nowrap", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for wrap-break-word definition in the entire codebase
rg "wrap-break-word" --type=ts --type=tsx --type=js --type=jsx --type=json -C 3Repository: decocms/admin
Length of output: 84
🏁 Script executed:
#!/bin/bash
# Search for Tailwind config files and check for custom utility definitions
find . -name "tailwind.config.*" -o -name "tailwind.config.*.ts" | head -20Repository: decocms/admin
Length of output: 39
🏁 Script executed:
#!/bin/bash
# Check the plugin file that enforces design system tokens
cat packages/ui/src/components/resource-table.tsx | head -120 | tail -15Repository: decocms/admin
Length of output: 688
🏁 Script executed:
#!/bin/bash
# Look for any custom break word utilities in Tailwind config
rg "break-word|wrapBreak" --type=ts --type=tsx --type=js --type=json -C 2Repository: decocms/admin
Length of output: 84
🏁 Script executed:
#!/bin/bash
# Search for wrap-break-word without file type restriction
rg "wrap-break-word" -C 3Repository: decocms/admin
Length of output: 2956
🏁 Script executed:
#!/bin/bash
# Search for break-words (standard Tailwind) to compare usage
rg "break-words" -C 2Repository: decocms/admin
Length of output: 9329
🏁 Script executed:
#!/bin/bash
# Find and examine tailwind config files
find . -name "tailwind.config*" -type f 2>/dev/null | head -5Repository: decocms/admin
Length of output: 39
🏁 Script executed:
#!/bin/bash
# Check if there's a custom utility definition in the config
find . -path "*/node_modules" -prune -o -name "*.config.*" -type f -print | grep -E "(tailwind|design|theme)" | head -10Repository: decocms/admin
Length of output: 39
🏁 Script executed:
#!/bin/bash
# Search for wrap-break-word in CSS files
rg "wrap-break-word" --type=css -C 3Repository: decocms/admin
Length of output: 39
🏁 Script executed:
#!/bin/bash
# Look for Tailwind config or custom utility definitions
find . -path "*/node_modules" -prune -o -type f \( -name "*.css" -o -name "*.ts" -o -name "*.js" \) -print | xargs grep -l "extend\|@apply" 2>/dev/null | grep -E "(tailwind|global|theme)" | head -10Repository: decocms/admin
Length of output: 92
🏁 Script executed:
#!/bin/bash
# Check for CSS files that might define wrap-break-word
find . -path "*/node_modules" -prune -o -name "*.css" -type f -print | head -20Repository: decocms/admin
Length of output: 169
🏁 Script executed:
#!/bin/bash
# Look at the plugin file mentioned in the guidelines
find . -path "*/node_modules" -prune -o -name "ensure-tailwind-design-system-tokens.ts" -type f -printRepository: decocms/admin
Length of output: 39
🏁 Script executed:
#!/bin/bash
# Check the global CSS files for custom utilities
cat packages/ui/src/styles/global.cssRepository: decocms/admin
Length of output: 11650
🏁 Script executed:
#!/bin/bash
# Find the plugins directory
find . -path "*/node_modules" -prune -o -type d -name "plugins" -print | head -5Repository: decocms/admin
Length of output: 66
🏁 Script executed:
#!/bin/bash
# Search more broadly for any definition of wrap-break-word
rg "wrap-break-word" -C 5 | head -50Repository: decocms/admin
Length of output: 4417
🏁 Script executed:
#!/bin/bash
# Verify the plugin exists and check its content
find ./plugins -name "*tailwind*" -o -name "*design*" | head -10Repository: decocms/admin
Length of output: 106
🏁 Script executed:
#!/bin/bash
# Check plugin directory structure
ls -la ./plugins/ 2>/dev/null | head -20Repository: decocms/admin
Length of output: 424
🏁 Script executed:
#!/bin/bash
# Read the plugin that enforces design tokens
cat ./plugins/ensure-tailwind-design-system-tokens.jsRepository: decocms/admin
Length of output: 2582
Replace wrap-break-word with the standard Tailwind utility break-words.
Line 115 uses "whitespace-normal wrap-break-word", but wrap-break-word is not a valid Tailwind utility. The correct standard class is break-words. Additionally, this class appears in 3 other files in the codebase (view-console.tsx, document-detail.tsx), indicating a systematic issue.
While the design token enforcement plugin is currently disabled, the coding guidelines require consistency with Tailwind design tokens, and using non-existent utilities will cause issues with Tailwind's purging and type checking.
Apply this fix:
col.wrap
- ? "whitespace-normal wrap-break-word"
+ ? "whitespace-normal break-words"
: "truncate overflow-hidden whitespace-nowrap",Also update the other 3 occurrences in apps/web/src/components/views/view-console.tsx and apps/web/src/components/documents/document-detail.tsx (2 instances).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| col.wrap | |
| ? "whitespace-normal break-words" | |
| ? "whitespace-normal wrap-break-word" | |
| : "truncate overflow-hidden whitespace-nowrap", | |
| col.wrap | |
| ? "whitespace-normal break-words" | |
| : "truncate overflow-hidden whitespace-nowrap", |
🤖 Prompt for AI Agents
In packages/ui/src/components/resource-table.tsx around lines 114-116, replace
the non-standard Tailwind class "wrap-break-word" with the correct utility
"break-words" so the conditional becomes "whitespace-normal break-words"; also
update the same incorrect usage found in
apps/web/src/components/views/view-console.tsx and
apps/web/src/components/documents/document-detail.tsx (two instances) to use
"break-words" to ensure consistency with Tailwind design tokens and proper
purging/type-checking.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (2)
apps/mesh/src/web/routes/orgs/connections.tsx (2)
118-120: HandleuseConnectionserror state and guard against undefined data.
useConnections(listState)is only usingdataandisLoading, but:
connectionsis assumed to always be an array (connections.length,connections.map), which will throw if it’s everundefined.- Error state from the underlying React Query hook is not surfaced, which conflicts with the guidelines around explicit loading/error handling. Based on learnings, this should show either an error empty state or at least a clear message.
Consider:
- const { data: connections, isLoading } = useConnections(listState); + const { + data: connections = [], + isLoading, + error, + } = useConnections(listState);And gate the main content with an explicit error state:
- {/* Content: Cards or Table */} - {listState.viewMode === "cards" ? ( + {/* Content: Error / Cards or Table */} + {error ? ( + <div className="flex-1 overflow-auto p-5"> + <EmptyState + image={null} + title="Failed to load MCPs" + description="There was a problem loading your MCPs. Please try again." + /> + </div> + ) : listState.viewMode === "cards" ? ( <div className="flex-1 overflow-auto p-5"> {isLoading ? ( <div className="flex items-center justify-center h-full"> <div className="text-muted-foreground">Loading...</div> </div> ) : connections.length === 0 ? ( … ) : ( … )} </div> ) : ( <CollectionTableWrapper columns={columns} data={connections} isLoading={isLoading} … /> )}This aligns with the “Handle loading and error states appropriately when using React Query hooks in components” guideline and avoids runtime errors if
datais ever undefined.Also applies to: 571-627, 629-673
578-595: Differentiate empty-state titles for “no results” vs “no items”.The card-view EmptyState title currently uses a redundant ternary, and the table-view “no items yet” case shares the same
"No MCPs found"copy as the “no results” case. That makes it harder for users to distinguish “nothing here yet” from “search returned no matches.”You can keep semantics while simplifying and improving messaging, e.g.:
- title={listState.search ? "No MCPs found" : "No MCPs found"} + title={listState.search ? "No MCPs found" : "No MCPs yet"}And for the non-search table empty state:
- <EmptyState + <EmptyState image={ <img src="/emptystate-mcp.svg" alt="" width={500} height={223} aria-hidden="true" /> } - title="No MCPs found" + title="No MCPs yet" description="Create a connection to get started." />This mirrors the earlier review feedback and makes the two states clearer to the user.
Also applies to: 643-670
🧹 Nitpick comments (2)
apps/mesh/src/web/routes/orgs/connections.tsx (2)
211-233: Verify default metadata for new connections (created_by,status).For new inserts you’re hardcoding:
created_by: "system"(with a TODO to wire the actual user).status: "inactive"as the initial status.Both are reasonable defaults but have product implications (audit trails and activation behavior). Please confirm with the domain model that:
"inactive"is the correct initial state and is supported by downstream logic (filters, badges, activation flows).- Using
"system"won’t confuse audit/reporting until real user IDs are plumbed through, or track this via a follow-up issue.No code change strictly required here, but it’s worth validating before this ships.
559-563: Minor UX copy nit: placeholder phrasing.
"Search for a MCP..."is a bit awkward grammatically; consider making it plural or dropping the article:- placeholder="Search for a MCP..." + placeholder="Search MCPs..."(or
"Search for MCPs...") for slightly cleaner copy.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/mesh/src/web/components/collections/collection-table.tsx(0 hunks)apps/mesh/src/web/components/collections/user-indicator.tsx(0 hunks)apps/mesh/src/web/routes/orgs/connections.tsx(11 hunks)
💤 Files with no reviewable changes (2)
- apps/mesh/src/web/components/collections/user-indicator.tsx
- apps/mesh/src/web/components/collections/collection-table.tsx
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/data-flow.mdc)
Handle loading and error states appropriately when using React Query hooks in components
Files:
apps/mesh/src/web/routes/orgs/connections.tsx
**/*.{ts,tsx,js,jsx,css}
📄 CodeRabbit inference engine (.cursor/rules/structure.mdc)
Run formatting with
bun run fmtbefore opening pull requestsKeep Tailwind design tokens consistent per
plugins/ensure-tailwind-design-system-tokens.tswhich will fail builds otherwise
Files:
apps/mesh/src/web/routes/orgs/connections.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/structure.mdc)
Run type checking with
bun run checkbefore opening pull requestsFavor TypeScript types over
anykeyword
**/*.{ts,tsx}: Write concise, maintainable, and technically accurate TypeScript code with relevant examples
Use functional and declarative programming patterns; avoid classes
Favor iteration and modularization to adhere to DRY principles and avoid code duplication
Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)
Organize files systematically: each file should contain only related content, such as exported components, subcomponents, helpers, static content, and types
Favor named exports for functions
Use TypeScript for all code
Prefer interfaces over types for their extendability and ability to merge
Avoid enums; use maps instead for better type safety and flexibility
Use the "function" keyword for pure functions to benefit from hoisting and clarity
Files:
apps/mesh/src/web/routes/orgs/connections.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/structure.mdc)
Run linting with
bun run lintbefore opening pull requests
**/*.{ts,tsx,js,jsx}: Use PascalCase for component and class names
Use camelCase for hooks and utility function names
Files:
apps/mesh/src/web/routes/orgs/connections.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Keep imports sorted in all code files
Files:
apps/mesh/src/web/routes/orgs/connections.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react-ts.mdc)
**/*.tsx: Use functional components with TypeScript interfaces
Favor using the already-present ui components inpackages/uifolder instead of creating custom components
Use useMemo for expensive computations like filtering and sorting operations to optimize performance in data-intensive applications
Memoize objects and arrays using useMemo to maintain stable references across renders
Use useDeferredValue for search operations to prevent blocking user input during filtering
Follow MCP (Model Context Protocol) patterns for consistent data fetching with hooks like useAgents, useIntegrations, and useUpdateAgent
Use react-hook-form with Zod validation instead of manual useState for form management
Avoid prop drilling by using Form Context to share form state across components
Use design system Form components (Form, FormControl, FormField, FormItem, FormLabel, FormMessage) from @deco/ui with proper error handling
Apply Single Responsibility Principle to components: each component should have a focused purpose and be composable
Ensure dependency arrays contain stable references; avoid creating inline objects or arrays that cause unnecessary re-renders
Implement consistent error and loading state handling with proper UI feedback (loading spinners, error messages, empty states)
Apply changes immediately to DOM for instant visual feedback, then debounce state updates for features like theme editors and live previews
Use custom events dispatched via window.dispatchEvent and window.addEventListener for cross-component communication of state updates
Implement single-level undo that reverts to the saved state, not just the previous change; use refs to track original saved values
Use useSetThreadContextEffect to inject rules and toolsets into AI chat threads; use explicit union types for context items
Extract complex logic from JSX into separate components instead of using IIFEs (immediately invoked function expressions)
Files:
apps/mesh/src/web/routes/orgs/connections.tsx
🧠 Learnings (17)
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Follow MCP (Model Context Protocol) patterns for consistent data fetching with hooks like useAgents, useIntegrations, and useUpdateAgent
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:08:08.813Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/deconfig.mdc:0-0
Timestamp: 2025-12-01T21:08:08.813Z
Learning: Applies to packages/sdk/src/mcp/deconfig/**/*.ts : Implement modular composition where merge() reuses diff() + transactionalWrite(), and transactionalWrite() has internal method for different scenarios to ensure code reuse and consistency
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:07:47.300Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/data-flow.mdc:0-0
Timestamp: 2025-12-01T21:07:47.300Z
Learning: Applies to **/*{tools,api,index}*.ts : Organize MCP tools into typed collections (GLOBAL_TOOLS, WORKSPACE_TOOLS, AGENT_TOOLS, EMAIL_TOOLS) by functionality and scope
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:08:08.813Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/deconfig.mdc:0-0
Timestamp: 2025-12-01T21:08:08.813Z
Learning: Applies to packages/sdk/src/mcp/deconfig/**/*.ts : Ensure full TypeScript type safety with interfaces for all data structures, generated RPC types for tool integration, and Zod schema validation where needed
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:07:47.300Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/data-flow.mdc:0-0
Timestamp: 2025-12-01T21:07:47.300Z
Learning: Applies to **/*.{tsx,jsx} : Handle loading and error states appropriately when using React Query hooks in components
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Implement consistent error and loading state handling with proper UI feedback (loading spinners, error messages, empty states)
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:07:47.300Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/data-flow.mdc:0-0
Timestamp: 2025-12-01T21:07:47.300Z
Learning: Applies to **/*{hook,mutation,use}*.{ts,tsx} : Implement optimistic updates in React Query mutations with proper rollback on error using `onMutate` and `onError` callbacks
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to apps/web/src/components/**/*-view.tsx : Use explicit union type annotation for threadContextItems array: Array<{ id: string; type: 'rule'; text: string } | { id: string; type: 'toolset'; integrationId: string; enabledTools: string[] }>
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Use design system Form components (Form, FormControl, FormField, FormItem, FormLabel, FormMessage) from deco/ui with proper error handling
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:09:05.323Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/structure.mdc:0-0
Timestamp: 2025-12-01T21:09:05.323Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use shadcn/ui shared design system components from packages/ui
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Avoid prop drilling by using Form Context to share form state across components
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Use react-hook-form with Zod validation instead of manual useState for form management
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:09:05.323Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/structure.mdc:0-0
Timestamp: 2025-12-01T21:09:05.323Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use React 19 for UI development in the decocms admin shell and marketplace
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to apps/web/src/components/*-editor/*.tsx : Use debounced form updates with immediate DOM manipulation for real-time visual feedback in editors
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to apps/web/src/components/**/*-view.tsx : In main view components, use `useSetThreadContextEffect` hook to inject context items (rules and toolsets) for AI chat integration
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to packages/sdk/src/hooks/*.ts : Create React Query hooks using `useQuery` for data fetching and `useMutation` for updates, with proper cache invalidation on success
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Use functional components with TypeScript interfaces
Applied to files:
apps/mesh/src/web/routes/orgs/connections.tsx
🧬 Code graph analysis (1)
apps/mesh/src/web/routes/orgs/connections.tsx (7)
apps/mesh/src/web/components/integration-icon.tsx (1)
IntegrationIcon(11-59)apps/mesh/src/web/components/collections/collection-page.tsx (1)
CollectionPage(7-13)apps/mesh/src/web/components/collections/collection-header.tsx (1)
CollectionHeader(15-43)apps/mesh/src/web/components/collections/collection-search.tsx (1)
CollectionSearch(21-45)apps/mesh/src/web/components/empty-state.tsx (1)
EmptyState(28-63)packages/ui/src/components/empty-state.tsx (1)
EmptyState(6-60)apps/mesh/src/web/components/collections/collection-table-wrapper.tsx (1)
CollectionTableWrapper(16-58)
⏰ 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)
- GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
apps/mesh/src/web/routes/orgs/connections.tsx (1)
255-268: Table columns and row actions wiring look solid.The icon column using
IntegrationIcon, the status badge variant, and the actions dropdown (withstopPropagationon buttons/items) are all wired cleanly and match the new collection-table semantics and UX expectations. The explicitcellClassNamewidths also help keep the table layout stable.Also applies to: 313-364
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/mesh/src/web/components/collections/collection-card.tsx (1)
7-12: Remove unusedreadOnlyandonActionprops from the interface.The interface defines
readOnlyandonActionprops that are not used by the component (onlyitemandschemaare destructured at line 64-67). This leaves dead code that can confuse future maintainers.Apply this diff to clean up the interface:
-interface CollectionCardProps<T extends BaseCollectionEntity> { - item: T; - schema: z.AnyZodObject; - readOnly?: boolean; - onAction: (action: "open" | "delete" | "duplicate", item: T) => void; -} +interface CollectionCardProps<T extends BaseCollectionEntity> { + item: T; + schema: z.AnyZodObject; +}
🧹 Nitpick comments (2)
apps/mesh/src/web/components/collections/collection-card.tsx (2)
77-95: Add hover state for interactive feedback.The Card uses
cursor-pointerandtransition-colors, but there's no hover state to provide visual feedback. Users expect clickable elements to respond visually on hover.- <Card className="cursor-pointer transition-colors"> + <Card className="cursor-pointer transition-colors hover:bg-accent/50">Also, if the card is meant to be clickable, ensure the click handler is either passed as a prop or the component is wrapped appropriately at the parent level.
86-86:gap-0is redundant.The default gap value for flex containers is already 0.
- <div className="flex flex-col gap-0"> + <div className="flex flex-col">
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/mesh/src/web/components/collections/collection-card.tsx(3 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/data-flow.mdc)
Handle loading and error states appropriately when using React Query hooks in components
Files:
apps/mesh/src/web/components/collections/collection-card.tsx
**/*.{ts,tsx,js,jsx,css}
📄 CodeRabbit inference engine (.cursor/rules/structure.mdc)
Run formatting with
bun run fmtbefore opening pull requestsKeep Tailwind design tokens consistent per
plugins/ensure-tailwind-design-system-tokens.tswhich will fail builds otherwise
Files:
apps/mesh/src/web/components/collections/collection-card.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/structure.mdc)
Run type checking with
bun run checkbefore opening pull requestsFavor TypeScript types over
anykeyword
**/*.{ts,tsx}: Write concise, maintainable, and technically accurate TypeScript code with relevant examples
Use functional and declarative programming patterns; avoid classes
Favor iteration and modularization to adhere to DRY principles and avoid code duplication
Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)
Organize files systematically: each file should contain only related content, such as exported components, subcomponents, helpers, static content, and types
Favor named exports for functions
Use TypeScript for all code
Prefer interfaces over types for their extendability and ability to merge
Avoid enums; use maps instead for better type safety and flexibility
Use the "function" keyword for pure functions to benefit from hoisting and clarity
Files:
apps/mesh/src/web/components/collections/collection-card.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/structure.mdc)
Run linting with
bun run lintbefore opening pull requests
**/*.{ts,tsx,js,jsx}: Use PascalCase for component and class names
Use camelCase for hooks and utility function names
Files:
apps/mesh/src/web/components/collections/collection-card.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Keep imports sorted in all code files
Files:
apps/mesh/src/web/components/collections/collection-card.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react-ts.mdc)
**/*.tsx: Use functional components with TypeScript interfaces
Favor using the already-present ui components inpackages/uifolder instead of creating custom components
Use useMemo for expensive computations like filtering and sorting operations to optimize performance in data-intensive applications
Memoize objects and arrays using useMemo to maintain stable references across renders
Use useDeferredValue for search operations to prevent blocking user input during filtering
Follow MCP (Model Context Protocol) patterns for consistent data fetching with hooks like useAgents, useIntegrations, and useUpdateAgent
Use react-hook-form with Zod validation instead of manual useState for form management
Avoid prop drilling by using Form Context to share form state across components
Use design system Form components (Form, FormControl, FormField, FormItem, FormLabel, FormMessage) from @deco/ui with proper error handling
Apply Single Responsibility Principle to components: each component should have a focused purpose and be composable
Ensure dependency arrays contain stable references; avoid creating inline objects or arrays that cause unnecessary re-renders
Implement consistent error and loading state handling with proper UI feedback (loading spinners, error messages, empty states)
Apply changes immediately to DOM for instant visual feedback, then debounce state updates for features like theme editors and live previews
Use custom events dispatched via window.dispatchEvent and window.addEventListener for cross-component communication of state updates
Implement single-level undo that reverts to the saved state, not just the previous change; use refs to track original saved values
Use useSetThreadContextEffect to inject rules and toolsets into AI chat threads; use explicit union types for context items
Extract complex logic from JSX into separate components instead of using IIFEs (immediately invoked function expressions)
Files:
apps/mesh/src/web/components/collections/collection-card.tsx
🧠 Learnings (7)
📚 Learning: 2025-12-01T21:09:30.412Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/wallet.mdc:0-0
Timestamp: 2025-12-01T21:09:30.412Z
Learning: Applies to **/*wallet*.ts : Remove payer field from transaction records and eliminate trial credits tracking - use plan-based monthly credits instead.
Applied to files:
apps/mesh/src/web/components/collections/collection-card.tsx
📚 Learning: 2025-12-01T21:09:05.323Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/structure.mdc:0-0
Timestamp: 2025-12-01T21:09:05.323Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use shadcn/ui shared design system components from packages/ui
Applied to files:
apps/mesh/src/web/components/collections/collection-card.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Use design system Form components (Form, FormControl, FormField, FormItem, FormLabel, FormMessage) from deco/ui with proper error handling
Applied to files:
apps/mesh/src/web/components/collections/collection-card.tsx
📚 Learning: 2025-12-01T21:09:05.323Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/structure.mdc:0-0
Timestamp: 2025-12-01T21:09:05.323Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use React 19 for UI development in the decocms admin shell and marketplace
Applied to files:
apps/mesh/src/web/components/collections/collection-card.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Favor using the already-present ui components in `packages/ui` folder instead of creating custom components
Applied to files:
apps/mesh/src/web/components/collections/collection-card.tsx
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to apps/web/src/components/**/*-view.tsx : Use explicit union type annotation for threadContextItems array: Array<{ id: string; type: 'rule'; text: string } | { id: string; type: 'toolset'; integrationId: string; enabledTools: string[] }>
Applied to files:
apps/mesh/src/web/components/collections/collection-card.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Use functional components with TypeScript interfaces
Applied to files:
apps/mesh/src/web/components/collections/collection-card.tsx
🧬 Code graph analysis (1)
apps/mesh/src/web/components/collections/collection-card.tsx (2)
packages/ui/src/components/card.tsx (1)
Card(79-79)apps/mesh/src/web/components/integration-icon.tsx (1)
IntegrationIcon(11-59)
⏰ 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)
- GitHub Check: Cloudflare Pages
…pty state handling - Added `CollectionHeader`, `CollectionDisplayButton`, and `CollectionPage` components for enhanced collection management. - Implemented `CollectionSearch` for improved item searching within collections. - Introduced `CollectionTableWrapper` to handle table display logic, replacing the deprecated `CollectionTable`. - Added `IntegrationIcon` for better visual representation of collection items. - Created a new SVG file for empty state illustration in collections. - Updated `EmptyState` component to provide clearer messaging when no items are found. - Refactored `CollectionsList` to utilize new components and improve overall structure. - Removed unused `UserIndicator` component to streamline the codebase.
87637d4 to
d9e4de9
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
apps/web/src/components/views/internal-resource-list.tsx (1)
80-111: Avoid stale search results and duplicate searches inrunSearch
runSearchis async and invoked both viauseEffectonqand via the input’s Enter key, without any request tracking. If multiple searches overlap, a slower, older request can overwriteitemsandloadingfrom a newer term, and typing triggers a request on every keystroke plus Enter.Consider:
- Tracking a
lastRequestIdwithuseRefand only applying results/loading state when the current request is still the latest, and- Either debouncing
qor relying on Enter-only search (not both) to avoid unnecessary calls, optionally viauseDeferredValuefor smoother typing, as per the search guidelines.Example sketch:
+ const lastRequestIdRef = useRef(0); + async function runSearch(term: string) { - setLoading(true); + const requestId = ++lastRequestIdRef.current; + setLoading(true); try { const result = (await callTool(integration?.connection, { name: "DECO_CHAT_RESOURCES_SEARCH", arguments: { name, term, limit: 50 }, })) as { structuredContent?: { items?: Array<...> } }; const itemsRaw = result.structuredContent?.items ?? []; const mapped = itemsRaw.map((r) => ({ ... })); - setItems(mapped); + if (lastRequestIdRef.current === requestId) { + setItems(mapped); + } } finally { - setLoading(false); + if (lastRequestIdRef.current === requestId) { + setLoading(false); + } } }And then decide whether
useEffect([q])alone should drive search, or Enter should, but not both.Also applies to: 113-115, 290-303
apps/web/src/components/settings/members/roles.tsx (1)
1420-1427: Add missing dependencies touseMemohooks to prevent stale filtered resultsThree
useMemohooks read external data that is not listed in their dependency arrays. When these data sources update from their React Query hooks, the memoized results won't recalculate, causing stale data to display:
- Lines 1420–1427:
integrationsWithToolsusesintegrationsbut depends only onteamRoleData?.tools- Lines 1479–1484:
roleMembersListusesmembersbut depends only onteamRoleData?.members- Lines 1534–1537:
roleAgentsListusesagentsbut depends only onteamRoleData?.agentsAdd the missing variables to each dependency array:
- }, [teamRoleData?.tools]); + }, [integrations, teamRoleData?.tools]);- }, [teamRoleData?.members]); + }, [members, teamRoleData?.members]);- }, [teamRoleData?.agents]); + }, [agents, teamRoleData?.agents]);apps/mesh/src/web/components/collections/collection-card.tsx (1)
7-12: Interface declares props that are not used.
CollectionCardPropsstill declaresreadOnlyandonActionprops (lines 10-11), but the component signature only destructuresitemandschema. This creates a mismatch: callers (e.g.,CollectionsList) pass these props expecting them to work, but they're silently ignored.Either remove the unused props from the interface or implement the functionality:
interface CollectionCardProps<T extends BaseCollectionEntity> { item: T; schema: z.AnyZodObject; - readOnly?: boolean; - onAction: (action: "open" | "delete" | "duplicate", item: T) => void; }Also applies to: 64-67
♻️ Duplicate comments (5)
packages/ui/src/components/collection-table.tsx (1)
114-116: Replacewrap-break-wordwith standard Tailwind utilitybreak-words.Line 115 uses
"whitespace-normal wrap-break-word", butwrap-break-wordis not a valid Tailwind utility. The correct standard class isbreak-words.As per coding guidelines, Tailwind design tokens must be consistent with
plugins/ensure-tailwind-design-system-tokens.ts, and using non-existent utilities will cause issues with Tailwind's purging and type checking.Apply this fix:
col.wrap - ? "whitespace-normal wrap-break-word" + ? "whitespace-normal break-words" : "truncate overflow-hidden whitespace-nowrap",apps/mesh/src/web/components/collections/collections-list.tsx (2)
111-117: Verify EmptyState prop matches import source.The import is from
@deco/ui/components/empty-state.tsxwhich accepts aniconprop. However, there's also@/web/components/empty-state.tsx(used elsewhere in the PR) which expects animageprop. Ensure the correct component is being used here.If you intend to use the mesh app's
EmptyState(which has richer illustration support), update the import:-import { EmptyState } from "@deco/ui/components/empty-state.tsx"; +import { EmptyState } from "@/web/components/empty-state.tsx";Then change
icontoimage:- icon="inbox" + image={null}Also applies to: 161-167
88-95: Fix type error:onViewModeChangemay be undefined.The pipeline failure indicates
onViewModeChangeis optional butCollectionDisplayButtonexpects a required function. Guard against undefined:<CollectionDisplayButton viewMode={viewMode} - onViewModeChange={onViewModeChange} + onViewModeChange={onViewModeChange ?? (() => {})} sortKey={sortKey} sortDirection={sortDirection} onSort={onSort} sortOptions={sortOptions} />apps/mesh/src/web/routes/orgs/connections.tsx (2)
117-118: Handle error state fromuseConnectionshook.Per coding guidelines, error states should be handled when using React Query hooks. Destructure
errorand provide user feedback:- const { data: connections, isLoading } = useConnections(listState); + const { data: connections, isLoading, error } = useConnections(listState);Then handle the error state in the render, e.g., show a toast or error UI.
589-589: Redundant ternary: both branches have the same title.Differentiate the messaging for better UX:
- title={listState.search ? "No MCPs found" : "No MCPs found"} + title={listState.search ? "No results" : "No MCPs yet"}
🧹 Nitpick comments (10)
apps/mesh/src/web/hooks/use-collections.ts (2)
417-424: Potential unreachable fallback in field filter logic.Line 419's truthiness check (
if (!item[filter.column as keyof T]) continue;) ensures that the field is truthy before reaching line 421. This makes the?? ""fallback on line 421 logically unreachable, since we only proceed when the field has a truthy value.If the fallback is required for TypeScript type safety (because TS cannot narrow
keyof Tsufficiently), consider adding a comment explaining this. Otherwise, the fallback could be removed.for (const filter of filters) { if (!item[filter.column as keyof T]) continue; - // Column must match an entity property - const field = item[filter.column as keyof T] ?? ""; + // Column must match an entity property (truthiness checked above) + const field = item[filter.column as keyof T] as string; conditions.push(eq(field as string, filter.value)); }
435-435: Consider usinguseDeferredValuefor search to improve UX.The dependency array correctly uses
trimmedSearchTermand contains stable references.However, per coding guidelines learnings, consider wrapping
trimmedSearchTermwithuseDeferredValueto prevent blocking user input during filtering, especially when dealing with large collections:const deferredSearchTerm = useDeferredValue(trimmedSearchTerm);Then use
deferredSearchTermin the query logic and dependency array. This keeps the search input responsive while filtering runs in the background.Based on learnings,
useDeferredValueimproves search UX by preventing input blocking.apps/web/src/components/settings/usage/users-table.tsx (2)
155-162: Remove debugconsole.logcalls from render pathThe
console.login thetotalcolumn renderer and the two logs before the<Table>render will generate noisy output and can impact performance on large datasets.Consider stripping them before shipping:
- { - id: "total", - header: "Total Cost", - render: (user) => { - console.log( - `Rendering user ${user.userId} total cost:`, - user.totalCost, - typeof user.totalCost, - ); - return ( - <span className="font-medium">$ {user.totalCost.toFixed(2)}</span> - ); - }, - sortable: true, - }, + { + id: "total", + header: "Total Cost", + render: (user) => ( + <span className="font-medium">$ {user.totalCost.toFixed(2)}</span> + ), + sortable: true, + },- console.log("UsersTable - enrichedUsers:", enrichedUsers); - console.log("UsersTable - sortedUsers:", sortedUsers);Also applies to: 219-220
17-18: Narrow sort key type to avoid invalid values
sortKeyand related APIs are plainstring, but only a fixed set of keys is valid. Tightening this to a union improves type safety and avoids accidental mismatches between column IDs and sort keys.Example refactor:
- const [sortKey, setSortKey] = useState<string>("total"); + type SortKey = + | "user" + | "agentsUsed" + | "threadsCount" + | "totalTokens" + | "total"; + + const [sortKey, setSortKey] = useState<SortKey>("total"); @@ - const getSortValue = ( - user: (typeof enrichedUsers)[0], - key: string, - ): string | number => { + const getSortValue = ( + user: (typeof enrichedUsers)[0], + key: SortKey, + ): string | number => { @@ - const handleSort = (key: string) => { + const handleSort = (key: SortKey) => {This keeps behavior identical while letting TypeScript catch invalid sort keys at compile time.
Also applies to: 169-187, 189-198
apps/mesh/src/web/components/collections/collection-search.tsx (1)
1-45: Search component is clean; consider explicit React type importThe
CollectionSearchcomponent is a good, thin wrapper around the design‑systemInputandIcon, and its value/onChange API is straightforward and composable withuseDeferredValuein callers.You are using
React.KeyboardEventin the props type without importingReactas a type. To avoid relying on the globalReactnamespace from@types/react, you could tighten this:-import { Icon } from "@deco/ui/components/icon.tsx"; -import { Input } from "@deco/ui/components/input.tsx"; +import { Icon } from "@deco/ui/components/icon.tsx"; +import { Input } from "@deco/ui/components/input.tsx"; +import type * as React from "react"; @@ - onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void; + onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;(or import
KeyboardEvent/KeyboardEventHandlerfromreactand use those types directly).apps/mesh/src/web/components/details/layout.tsx (1)
44-68: Header layout works; minor flex alignment cleanup possibleThe new header/back‑button layout is fine functionally. In the
{/* Tabs and Actions */}row you have bothjustify-betweenon the container andml-autoon the actions div; only one is needed to push actions to the right:- <div className="flex justify-between px-4 items-center gap-4 flex-1"> + <div className="flex px-4 items-center gap-4 flex-1"> @@ - <div - id={ACTIONS_PORTAL_ID} - className="flex items-center gap-2 ml-auto" - /> + <div + id={ACTIONS_PORTAL_ID} + className="flex items-center gap-2 ml-auto" + />(or keep
justify-betweenand dropml-auto). This is purely cosmetic.apps/mesh/src/web/components/collections/types.ts (1)
5-5: Collections list types align with new collection table and sortingImporting
TableColumnfrom@deco/ui/components/collection-table.tsxand addingsortableFields?: string[]cleanly expose the new sorting capabilities to callers without breaking existing usage.If you want stronger typing, you could later narrow
sortableFieldsto(keyof T)[](or a mapped union of valid sort keys), but the current string list is fine for now and keeps the API simple.Also applies to: 114-120
apps/mesh/src/web/components/collections/collection-display-button.tsx (1)
21-45: Collection display button behavior looks solid; prefer explicitRefObjectimportThe dropdown UI for toggling between table/cards and selecting sort fields is well factored and matches the collection‑UI patterns introduced elsewhere. Indicator updates on
viewModeand when the menu opens, which should keep the highlight in sync.You’re typing
updateIndicatorwithReact.RefObjectbut don’t importReactas a type. To avoid relying on the global React namespace, you could importRefObjectdirectly:-import { useEffect, useRef, useState } from "react"; +import { useEffect, useRef, useState, type RefObject } from "react"; @@ - const tableRef = useRef<HTMLButtonElement>(null); - const cardsRef = useRef<HTMLButtonElement>(null); + const tableRef = useRef<HTMLButtonElement>(null); + const cardsRef = useRef<HTMLButtonElement>(null); @@ - const updateIndicator = (ref: React.RefObject<HTMLButtonElement | null>) => { + const updateIndicator = (ref: RefObject<HTMLButtonElement>) => {Behavior stays the same, but the typing is clearer and doesn’t depend on ambient
Reacttypes.Also applies to: 130-175
apps/mesh/src/web/components/details/connection.tsx (1)
704-720: Sort state toggle logic could becomenullunexpectedly.The
handleSortfunction setssetSortKey(undefined)when cycling through sort states, butsortKeyis initialized to"name". After a full cycle (asc → desc → null),sortKeybecomesundefinedbut the column still expects the sorted state indicator to work. Consider keeping the key but setting direction tonull:const handleSort = (key: string) => { if (sortKey === key) { setSortDirection((prev) => prev === "asc" ? "desc" : prev === "desc" ? null : "asc", ); - if (sortDirection === "desc") setSortKey(undefined); + // Keep sortKey; null direction means unsorted } else { setSortKey(key); setSortDirection("asc"); } };apps/mesh/src/web/routes/orgs/connections.tsx (1)
642-672: Consider consolidating duplicate EmptyState blocks.The two
EmptyStatecomponents share the same image but differ only in title/description. This could be simplified:emptyState={ - listState.search ? ( - <EmptyState - image={...} - title="No MCPs found" - description={`No MCPs match "${listState.search}"`} - /> - ) : ( - <EmptyState - image={...} - title="No MCPs found" - description="Create a connection to get started." - /> - ) + <EmptyState + image={<img src="/emptystate-mcp.svg" alt="" ... />} + title={listState.search ? "No results" : "No MCPs yet"} + description={ + listState.search + ? `No MCPs match "${listState.search}"` + : "Create a connection to get started." + } + /> }
| search={search} | ||
| onSearchChange={setSearch} |
There was a problem hiding this comment.
onSearchChange prop is passed but not used by CollectionsList.
Looking at collections-list.tsx, onSearchChange is not destructured from props, meaning this callback is ignored. Since hideToolbar={true} is set and search is handled externally via CollectionSearch, this prop is redundant here:
<CollectionsList
data={items ?? []}
schema={schema}
viewMode={viewMode}
onViewModeChange={setViewMode}
search={search}
- onSearchChange={setSearch}
sortKey={sortKey as string}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| search={search} | |
| onSearchChange={setSearch} | |
| <CollectionsList | |
| data={items ?? []} | |
| schema={schema} | |
| viewMode={viewMode} | |
| onViewModeChange={setViewMode} | |
| search={search} | |
| sortKey={sortKey as string} |
🤖 Prompt for AI Agents
In apps/mesh/src/web/components/details/connection.tsx around lines 1037-1038,
the onSearchChange={setSearch} prop is being passed into CollectionsList but
CollectionsList does not accept or use that prop (so it’s redundant). Remove the
onSearchChange={setSearch} prop from the CollectionsList JSX here (or
alternatively, if you intend CollectionsList to handle external search updates,
add onSearchChange to its props/interface and forward it to the internal search
handler), and update any related prop types/interfaces accordingly.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
apps/mesh/src/web/components/collections/collections-list.tsx (1)
110-116: Past review unresolved: EmptyState prop should beimage, noticon.This issue was previously flagged: the
EmptyStatecomponent expects animageprop (ReactNode or null), not aniconprop. Please address the past review comment by replacingicon="inbox"with the appropriateimagevalue.The same issue exists at lines 158-164.
🧹 Nitpick comments (2)
apps/mesh/src/web/components/collections/collections-list.tsx (2)
15-15: Reconsider no-op defaults for user interaction callbacks.While providing
onViewModeChange = () => {}as a default resolves the type error flagged in the past review, it creates a poor user experience: the view mode toggle button will be interactive but won't do anything if the parent doesn't provide a handler.Consider one of these approaches instead:
- Only render
CollectionDisplayButtonwhenonViewModeChangeis defined- Make the callback optional in
CollectionDisplayButtonand disable/hide the toggle when absent- If this component is meant to control its own state when no callback is provided, manage
viewModeinternally with useStateThe same concern applies to other interaction callbacks with no-op defaults (lines 19-21).
173-214: Add type guards and error handling in column generation.The helper function uses type assertions that may not be safe:
- Line 186:
row[key as keyof T]assumes schema keys match the typeT, but there's no compile-time guarantee- Line 196:
new Date(val as string)assumes date values are strings, but they could be Date objects or timestamps- Line 208:
typeof val === "object"thenJSON.stringify(val)could fail for circular references or throw for BigInt valuesfunction generateColumnsFromSchema<T extends BaseCollectionEntity>( schema: z.AnyZodObject, sortableFields?: string[], ): TableColumn<T>[] { return Object.keys(schema.shape) .filter( (key) => !["organization_id", "created_by", "updated_by"].includes(key), ) .map((key) => { const isSortable = sortableFields ? sortableFields.includes(key) : !["id"].includes(key); if (key.endsWith("_at")) { return { id: key, header: key.charAt(0).toUpperCase() + key.slice(1).replace(/_/g, " "), render: (row) => { const val = row[key as keyof T]; if (!val) return "—"; - return new Date(val as string).toLocaleDateString(); + try { + const date = typeof val === 'string' || typeof val === 'number' + ? new Date(val as string | number) + : val instanceof Date ? val : null; + return date?.toLocaleDateString() ?? "—"; + } catch { + return "—"; + } }, sortable: isSortable, }; } return { id: key, header: key.charAt(0).toUpperCase() + key.slice(1).replace(/_/g, " "), render: (row) => { const val = row[key as keyof T]; if (val === null || val === undefined) return "—"; - if (typeof val === "object") return JSON.stringify(val); + if (typeof val === "object") { + try { + return JSON.stringify(val); + } catch { + return "[Object]"; + } + } return String(val); }, sortable: isSortable, }; }); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/mesh/src/web/components/collections/collections-list.tsx(1 hunks)apps/mesh/src/web/components/collections/types.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx,js,jsx,css}
📄 CodeRabbit inference engine (.cursor/rules/structure.mdc)
Run formatting with
bun run fmtbefore opening pull requestsKeep Tailwind design tokens consistent per
plugins/ensure-tailwind-design-system-tokens.tswhich will fail builds otherwise
Files:
apps/mesh/src/web/components/collections/types.tsapps/mesh/src/web/components/collections/collections-list.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/structure.mdc)
Run type checking with
bun run checkbefore opening pull requestsFavor TypeScript types over
anykeyword
**/*.{ts,tsx}: Write concise, maintainable, and technically accurate TypeScript code with relevant examples
Use functional and declarative programming patterns; avoid classes
Favor iteration and modularization to adhere to DRY principles and avoid code duplication
Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)
Organize files systematically: each file should contain only related content, such as exported components, subcomponents, helpers, static content, and types
Favor named exports for functions
Use TypeScript for all code
Prefer interfaces over types for their extendability and ability to merge
Avoid enums; use maps instead for better type safety and flexibility
Use the "function" keyword for pure functions to benefit from hoisting and clarity
Files:
apps/mesh/src/web/components/collections/types.tsapps/mesh/src/web/components/collections/collections-list.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/structure.mdc)
Run linting with
bun run lintbefore opening pull requests
**/*.{ts,tsx,js,jsx}: Use PascalCase for component and class names
Use camelCase for hooks and utility function names
Files:
apps/mesh/src/web/components/collections/types.tsapps/mesh/src/web/components/collections/collections-list.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Keep imports sorted in all code files
Files:
apps/mesh/src/web/components/collections/types.tsapps/mesh/src/web/components/collections/collections-list.tsx
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/api-development.mdc)
Define both input and output Zod schemas for all API operations with appropriate type constraints (min/max length, optional fields, descriptions) and map them to TypeScript interfaces
Files:
apps/mesh/src/web/components/collections/types.ts
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/data-flow.mdc)
Handle loading and error states appropriately when using React Query hooks in components
Files:
apps/mesh/src/web/components/collections/collections-list.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react-ts.mdc)
**/*.tsx: Use functional components with TypeScript interfaces
Favor using the already-present ui components inpackages/uifolder instead of creating custom components
Use useMemo for expensive computations like filtering and sorting operations to optimize performance in data-intensive applications
Memoize objects and arrays using useMemo to maintain stable references across renders
Use useDeferredValue for search operations to prevent blocking user input during filtering
Follow MCP (Model Context Protocol) patterns for consistent data fetching with hooks like useAgents, useIntegrations, and useUpdateAgent
Use react-hook-form with Zod validation instead of manual useState for form management
Avoid prop drilling by using Form Context to share form state across components
Use design system Form components (Form, FormControl, FormField, FormItem, FormLabel, FormMessage) from @deco/ui with proper error handling
Apply Single Responsibility Principle to components: each component should have a focused purpose and be composable
Ensure dependency arrays contain stable references; avoid creating inline objects or arrays that cause unnecessary re-renders
Implement consistent error and loading state handling with proper UI feedback (loading spinners, error messages, empty states)
Apply changes immediately to DOM for instant visual feedback, then debounce state updates for features like theme editors and live previews
Use custom events dispatched via window.dispatchEvent and window.addEventListener for cross-component communication of state updates
Implement single-level undo that reverts to the saved state, not just the previous change; use refs to track original saved values
Use useSetThreadContextEffect to inject rules and toolsets into AI chat threads; use explicit union types for context items
Extract complex logic from JSX into separate components instead of using IIFEs (immediately invoked function expressions)
Files:
apps/mesh/src/web/components/collections/collections-list.tsx
🧠 Learnings (5)
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to apps/web/src/components/sidebar/index.tsx : Update sidebar navigation by adding feature name to wellKnownItems array and resourceTypeOrder array
Applied to files:
apps/mesh/src/web/components/collections/types.tsapps/mesh/src/web/components/collections/collections-list.tsx
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to apps/web/src/components/**/resource-list.tsx : Create resource list component that uses `useTrackNativeViewVisit` hook to track view visits for recents and pinning functionality
Applied to files:
apps/mesh/src/web/components/collections/types.ts
📚 Learning: 2025-12-01T21:08:29.999Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/native-apps-and-views.mdc:0-0
Timestamp: 2025-12-01T21:08:29.999Z
Learning: Applies to apps/web/src/components/**/*-view.tsx : Use explicit union type annotation for threadContextItems array: Array<{ id: string; type: 'rule'; text: string } | { id: string; type: 'toolset'; integrationId: string; enabledTools: string[] }>
Applied to files:
apps/mesh/src/web/components/collections/collections-list.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Ensure dependency arrays contain stable references; avoid creating inline objects or arrays that cause unnecessary re-renders
Applied to files:
apps/mesh/src/web/components/collections/collections-list.tsx
📚 Learning: 2025-12-01T22:44:41.561Z
Learnt from: CR
Repo: decocms/admin PR: 0
File: .cursor/rules/react-ts.mdc:0-0
Timestamp: 2025-12-01T22:44:41.561Z
Learning: Applies to **/*.tsx : Implement consistent error and loading state handling with proper UI feedback (loading spinners, error messages, empty states)
Applied to files:
apps/mesh/src/web/components/collections/collections-list.tsx
⏰ 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)
- GitHub Check: Cloudflare Pages
🔇 Additional comments (4)
apps/mesh/src/web/components/collections/types.ts (2)
5-5: LGTM! Import path updated correctly.The import path change from
resource-table.tsxtocollection-table.tsxaligns with the PR's objective to rename ResourceTable to CollectionTable.
109-114: LGTM! Well-documented new property.The
sortableFieldsproperty is clearly documented and provides flexible control over which fields can be sorted. The three behavior modes (undefined, empty array, specific fields) are well explained.apps/mesh/src/web/components/collections/collections-list.tsx (2)
120-141: LGTM! Cards grid rendering looks good.The conditional rendering between
CollectionCard(when schema is present) and fallbackCardis appropriate. The grid layout with responsive columns is well-structured.Note: The optional chaining on
onItemClick?.(item)(line 124) is now redundant since line 21 provides a default no-op function. This is a minor consistency issue, not a blocker.
76-98: LGTM! Clean layout structure.The flex layout with overflow handling and conditional toolbar rendering is well-structured. The separation of header and content areas is clear and maintainable.
5207094 to
a53c6ed
Compare
Summary by CodeRabbit
New Features
Improvements
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.