Skip to content

eng-252#352

Merged
Connorbelez merged 2 commits intomainfrom
Connorbelez/eng-252-view-definitions
Mar 30, 2026
Merged

eng-252#352
Connorbelez merged 2 commits intomainfrom
Connorbelez/eng-252-view-definitions

Conversation

@Connorbelez
Copy link
Copy Markdown
Owner

@Connorbelez Connorbelez commented Mar 30, 2026

Summary by CodeRabbit

  • New Features
    • Added comprehensive view management system enabling users to create, update, delete, and duplicate CRM views
    • Added view field configuration with visibility toggles, custom ordering, and column width adjustments
    • Added filtering capabilities for views with operator validation
    • Added Kanban board group management including reordering and collapse state controls

@linear
Copy link
Copy Markdown

linear bot commented Mar 30, 2026

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Sorry @Connorbelez, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 30, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR introduces five new Convex CRM modules implementing comprehensive view definition and child entity management: filterOperatorValidation for operator validation, viewDefs for view CRUD operations, viewFields for field properties management, viewFilters for filter management, and viewKanbanGroups for Kanban group operations. Supporting specification and task documentation is included.

Changes

Cohort / File(s) Summary
Filter Operator Validation
convex/crm/filterOperatorValidation.ts
New pure utility module deriving FieldType and FilterOperator unions from data model. Exports OPERATOR_MAP constant mapping field types to allowed operators, and functions getValidOperators() and isValidOperatorForFieldType() for operator validation.
View Definitions CRUD
convex/crm/viewDefs.ts
New module implementing complete view lifecycle: createView with org scoping, field capability validation, auto-populated viewFields and viewKanbanGroups; updateView with optional field rebinding and conditional kanban group regeneration; deleteView with default-view protection and cascaded child deletion; duplicateView cloning full view graph; listViews and getView with org verification. Exports KANBAN_NO_VALUE_SENTINEL constant.
View Fields Management
convex/crm/viewFields.ts
New module for view field operations: setViewFieldVisibility to create/update field visibility; reorderViewFields to update displayOrder from ordered fieldIds array; setViewFieldWidth to validate and update column width; listViewFields to return fields sorted by displayOrder. All enforce org scoping and view ownership.
View Filters Management
convex/crm/viewFilters.ts
New module for filter CRUD: addViewFilter validates operator against field type and inserts filter; updateViewFilter re-validates operator on change; removeViewFilter hard-deletes with org verification; listViewFilters returns view's filters. All operations include operator-to-field-type validation and audit logging.
Kanban Groups Management
convex/crm/viewKanbanGroups.ts
New module for kanban operations: reorderKanbanGroups updates displayOrder from ordered groupIds array with validation; toggleKanbanGroupCollapse negates collapse state; listKanbanGroups returns groups sorted by displayOrder. All enforce kanban view type and org scoping.
Specification & Task Documentation
specs/ENG-252/tasks.md, specs/ENG-252/type-design-review.md, specs/ENG-252/chunks/manifest.md, specs/ENG-252/chunks/chunk-01-viewdefs-core/*, specs/ENG-252/chunks/chunk-02-child-entities/*
Engineering specifications defining implementation requirements across two chunks: chunk-01 covers filter validation and view definitions CRUD; chunk-02 covers child entity management. Includes task enumeration (T-001–T-021), architectural decisions, invariant analysis, and quality gate checklist.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related issues

  • Phase 3: View Definitions CRUD #330 — Implements the same Convex CRM view CRUD surface across multiple modules (viewDefs, viewFields, viewFilters, viewKanbanGroups) and operator validation utilities, providing direct code-level implementation.

Possibly related PRs

  • eng-247+248 #340 — Introduces foundational schema definitions, validators, and CRM auth chains (fieldDefs, table schemas, org-scoping fluent chains) that these new modules depend on for data access and validation.

Poem

🐰 hops with glee
Views bloom in cascades fair,
Kanban groups arranged with care,
Filters validated just right,
Org-scoped with audit light—
A CRM view system pure and bright! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'eng-252' is a ticket/issue reference but lacks descriptive detail about the actual changes made, making it unclear what this PR accomplishes. Update the title to describe the main change clearly, such as 'Add CRM view definitions CRUD operations and filter validation' or 'Implement view management with filters and kanban groups'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch Connorbelez/eng-252-view-definitions

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Connorbelez Connorbelez marked this pull request as ready for review March 30, 2026 02:34
Copilot AI review requested due to automatic review settings March 30, 2026 02:34
Copy link
Copy Markdown
Owner Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copy link
Copy Markdown

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
convex/crm/viewDefs.ts (1)

245-256: Type annotation for patch is too narrow.

The patch object is typed as Record<string, string | number>, but boundFieldId is typed as Id<"fieldDefs">. While this works at runtime (Convex IDs are strings), the type annotation should be more accurate for TypeScript correctness.

🔧 Proposed fix
-		const patch: Record<string, string | number> = {
+		const patch: {
+			updatedAt: number;
+			name?: string;
+			boundFieldId?: typeof args.boundFieldId;
+		} = {
 			updatedAt: Date.now(),
 		};
 		if (args.name !== undefined) {
 			patch.name = args.name;
 		}
 		if (args.boundFieldId !== undefined) {
 			patch.boundFieldId = args.boundFieldId;
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@convex/crm/viewDefs.ts` around lines 245 - 256, The patch object is currently
typed as Record<string, string | number>, which is too narrow because
args.boundFieldId has type Id<"fieldDefs">; update the type for patch (the
variable named patch used before calling ctx.db.patch) to allow Convex IDs
(string) and numbers — e.g., widen it to Record<string, string | number |
Id<"fieldDefs">> or use a more permissive type like Record<string, unknown> or a
specific union including Id<"fieldDefs"> — then ensure
ctx.db.patch(args.viewDefId, patch) still receives the updated typed object;
adjust any related local references (args.boundFieldId, args.name) to match the
new patch type.
convex/crm/viewFields.ts (1)

124-129: Silently ignoring missing field IDs may cause unintended ordering gaps.

When fieldIds contains IDs that don't have corresponding viewFields records, they are silently skipped. Additionally, if fieldIds is a subset of actual viewFields, the omitted fields retain their old displayOrder values, potentially causing duplicate or inconsistent ordering.

Consider either:

  1. Validating that all provided fieldIds have corresponding viewFields records
  2. Requiring fieldIds to include all viewFields for the view
  3. Documenting that this is intentional partial-reorder behavior
🔧 Option 1: Validate all fieldIds exist in viewFields
 		// Build a lookup from fieldDefId to viewField
 		const fieldToViewField = new Map(
 			viewFields.map((vf) => [vf.fieldDefId, vf])
 		);

+		// Validate all provided fieldIds exist in viewFields
+		for (const fieldId of args.fieldIds) {
+			if (!fieldToViewField.has(fieldId)) {
+				throw new ConvexError(
+					`Field ${fieldId} is not part of this view's fields`
+				);
+			}
+		}
+
 		// Update displayOrder for each fieldId in the provided order
 		for (let i = 0; i < args.fieldIds.length; i++) {
 			const vf = fieldToViewField.get(args.fieldIds[i]);
-			if (vf) {
-				await ctx.db.patch(vf._id, { displayOrder: i });
-			}
+			await ctx.db.patch(vf!._id, { displayOrder: i });
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@convex/crm/viewFields.ts` around lines 124 - 129, The code currently skips
missing IDs when updating displayOrder (loop over args.fieldIds using
fieldToViewField and ctx.db.patch), causing inconsistent ordering; update the
handler to validate that every id in args.fieldIds exists in fieldToViewField
before patching: compute missingIds = args.fieldIds.filter(id =>
!fieldToViewField.has(id)) and if missingIds.length > 0 throw a clear error (or
return a validation failure) listing missingIds so callers must supply only
valid viewField IDs (alternatively enforce that args.fieldIds contains the full
set by comparing against the set of viewFields and error if sizes differ).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@convex/crm/viewKanbanGroups.ts`:
- Around line 53-56: The current loop only patches args.groupIds which allows
omitted groups to keep old displayOrder and cause collisions; modify the reorder
so it fetches all existing group IDs for the same board (e.g., query the groups
table using the boardId available in args or ctx), build a canonical ordered
list by taking args.groupIds in order then appending any remaining existing
group IDs (preserving their current relative order), and then iterate that full
list to call ctx.db.patch(...) to set displayOrder sequentially for every group;
update code around args.groupIds and the ctx.db.patch calls to use this full
ordered list.

---

Nitpick comments:
In `@convex/crm/viewDefs.ts`:
- Around line 245-256: The patch object is currently typed as Record<string,
string | number>, which is too narrow because args.boundFieldId has type
Id<"fieldDefs">; update the type for patch (the variable named patch used before
calling ctx.db.patch) to allow Convex IDs (string) and numbers — e.g., widen it
to Record<string, string | number | Id<"fieldDefs">> or use a more permissive
type like Record<string, unknown> or a specific union including Id<"fieldDefs">
— then ensure ctx.db.patch(args.viewDefId, patch) still receives the updated
typed object; adjust any related local references (args.boundFieldId, args.name)
to match the new patch type.

In `@convex/crm/viewFields.ts`:
- Around line 124-129: The code currently skips missing IDs when updating
displayOrder (loop over args.fieldIds using fieldToViewField and ctx.db.patch),
causing inconsistent ordering; update the handler to validate that every id in
args.fieldIds exists in fieldToViewField before patching: compute missingIds =
args.fieldIds.filter(id => !fieldToViewField.has(id)) and if missingIds.length >
0 throw a clear error (or return a validation failure) listing missingIds so
callers must supply only valid viewField IDs (alternatively enforce that
args.fieldIds contains the full set by comparing against the set of viewFields
and error if sizes differ).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8ec04639-4967-4bff-b0c8-4ecd5de5e336

📥 Commits

Reviewing files that changed from the base of the PR and between be6c98d and eb49577.

📒 Files selected for processing (12)
  • convex/crm/filterOperatorValidation.ts
  • convex/crm/viewDefs.ts
  • convex/crm/viewFields.ts
  • convex/crm/viewFilters.ts
  • convex/crm/viewKanbanGroups.ts
  • specs/ENG-252/chunks/chunk-01-viewdefs-core/context.md
  • specs/ENG-252/chunks/chunk-01-viewdefs-core/tasks.md
  • specs/ENG-252/chunks/chunk-02-child-entities/context.md
  • specs/ENG-252/chunks/chunk-02-child-entities/tasks.md
  • specs/ENG-252/chunks/manifest.md
  • specs/ENG-252/tasks.md
  • specs/ENG-252/type-design-review.md

Comment thread convex/crm/viewKanbanGroups.ts
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds CRM “view” infrastructure to Convex (viewDefs + viewFields + viewFilters + kanban groups), plus accompanying ENG-252 spec docs and task/chunk planning artifacts.

Changes:

  • Introduces viewDefs CRUD (create/update/delete/duplicate/list/get) with capability checks and kanban group auto-creation.
  • Adds child-entity operations for viewFields, viewFilters, and viewKanbanGroups.
  • Adds filterOperatorValidation.ts and extensive ENG-252 specification/task documentation.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
convex/crm/filterOperatorValidation.ts FieldType → valid filter-operator mapping helpers.
convex/crm/viewDefs.ts View definition CRUD, capability validation, cascade delete, duplication, and kanban group bootstrapping.
convex/crm/viewFields.ts View column visibility/width updates and reordering.
convex/crm/viewFilters.ts Filter CRUD with operator-vs-fieldType validation.
convex/crm/viewKanbanGroups.ts Kanban group reorder/toggle/list operations.
specs/ENG-252/type-design-review.md Type/invariant review notes and recommended follow-ups.
specs/ENG-252/tasks.md Master task list + quality gate notes.
specs/ENG-252/chunks/manifest.md Chunk breakdown and execution order.
specs/ENG-252/chunks/chunk-01-viewdefs-core/{context.md,tasks.md} Chunk-01 implementation context + checklist.
specs/ENG-252/chunks/chunk-02-child-entities/{context.md,tasks.md} Chunk-02 implementation context + checklist.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread convex/crm/viewFields.ts
Comment thread convex/crm/viewKanbanGroups.ts
Comment thread convex/crm/viewDefs.ts Outdated
Comment thread convex/crm/viewDefs.ts Outdated
Comment thread convex/crm/filterOperatorValidation.ts Outdated
Comment thread specs/ENG-252/chunks/chunk-01-viewdefs-core/tasks.md Outdated
Comment thread specs/ENG-252/chunks/chunk-02-child-entities/tasks.md Outdated
Comment thread convex/crm/viewFields.ts
…ilent failures

- Extract validateFieldCapability + createKanbanGroupsFromField helpers (DRY)
- Replace silent ?? [] fallbacks with explicit throws in getValidOperators and kanban group creation
- Add completeness checks to reorderViewFields and reorderKanbanGroups
- Add orgId defense-in-depth filter to listViews query
- Add cross-object field validation in setViewFieldVisibility
- Add isActive check on fieldDef in addViewFilter
- Add name validation (trim, empty, max length) to createView/updateView/duplicateView
- Export KANBAN_NO_VALUE_SENTINEL constant, fix patch types to Record<string, unknown>
- Remove unnecessary type cast in isValidOperatorForFieldType
- Add positive width validation in setViewFieldWidth
- Add null guard on post-patch db.get in updateView
- Update chunk task checkboxes to reflect completed status

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Connorbelez Connorbelez merged commit f19570b into main Mar 30, 2026
0 of 3 checks passed
Connorbelez added a commit that referenced this pull request Apr 20, 2026
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **New Features**
  * Added comprehensive view management system enabling users to create, update, delete, and duplicate CRM views
  * Added view field configuration with visibility toggles, custom ordering, and column width adjustments
  * Added filtering capabilities for views with operator validation
  * Added Kanban board group management including reordering and collapse state controls
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants