Skip to content

Conversation

@asithade
Copy link
Contributor

Summary

  • Added subcommittee support with parent committee selection in committee forms
  • Implemented functional View/Delete menu actions in committee table following established patterns
  • Added committee type filters with dynamic counts matching existing filter patterns
  • Enhanced voting status filter with count labels for consistency
  • Replaced method calls with pipes in templates for better performance
  • Added comprehensive type safety and error handling

Changes Made

  • Committee Form: Added parent committee dropdown with proper filtering logic
  • Committee Table: Implemented menu actions using signal-based state management pattern
  • Filters: Added committee type filter and enhanced voting status filter with counts
  • Performance: Replaced formatDate methods with Angular's built-in date pipe
  • Type Safety: Added proper TypeScript interfaces and signal types
  • Color Consistency: Aligned committee type and meeting type colors

Test Plan

  • Committee creation with parent selection works correctly
  • Committee editing excludes current committee from parent options
  • Table menu actions (View/Delete) function properly
  • All filters work with dynamic count updates
  • Subcommittees display correctly in table
  • Color coding matches between committee and meeting types
  • Performance improved with pipe usage

🤖 Generated with Claude Code

Add comprehensive committee management enhancements including:

- Subcommittee support with parent committee selection dropdown
- Enhanced filtering with dynamic counts for committee types and voting status
- Committee table menu actions (View/Delete) following established patterns
- Color-coded committee types with custom pipe for consistent styling
- Performance improvements by replacing formatDate methods with Angular date pipe
- Documentation updates for data transformation best practices

The parent committee selection prevents circular references and only shows
top-level committees as options. All filters now display counts and are
sorted alphabetically for better UX.

Generated with [Claude Code](https://claude.ai/code)

Closes LFXV2-256

Signed-off-by: Asitha de Silva <[email protected]>
Copilot AI review requested due to automatic review settings August 14, 2025 17:39
@asithade asithade requested a review from jordane as a code owner August 14, 2025 17:39
@coderabbitai
Copy link

coderabbitai bot commented Aug 14, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Refactors the Committees area into a single-column dashboard with summary metrics and filters (including voting status), introduces a standalone CommitteeTable, adds an optional parent committee selector in the form, removes subcommittees UI, adds committee-type color constants and pipe, updates the Committee interface, and adds Angular pipe guidance docs.

Changes

Cohort / File(s) Summary
Dashboard overhaul
apps/lfx-pcc/.../committee-dashboard/committee-dashboard.component.html, apps/lfx-pcc/.../committee-dashboard/committee-dashboard.component.ts
Rebuilt dashboard layout to single-column with header and New Committee button; added top statistics cards; moved/expanded search, category, and voting-status filters; replaced old table with CommitteeTableComponent; added computed metrics, voting status options, and edit/view/delete handlers; removed obsolete UI imports/logic.
Committee table component
apps/lfx-pcc/.../components/committee-table/committee-table.component.html, apps/lfx-pcc/.../components/committee-table/committee-table.component.ts
New standalone CommitteeTableComponent rendering organized parent/subcommittee list, columns for name/description/type/visibility/voting/members/updated/actions, action menu, and outputs for edit/view/delete; integrates project context and uses type-color pipe.
Committee form: parent selector
apps/lfx-pcc/.../components/committee-form/committee-form.component.html, apps/lfx-pcc/.../components/committee-form/committee-form.component.ts
Added optional parent_uid FormControl and a parentCommitteeOptions signal; fetches project committees, filters top-level committees and excludes the currently edited committee; provides “No Parent Committee” option.
Upcoming meeting component cleanup
apps/lfx-pcc/.../components/upcoming-committee-meeting/upcoming-committee-meeting.component.html, apps/lfx-pcc/.../components/upcoming-committee-meeting/upcoming-committee-meeting.component.ts
Removed “Join Meeting” button and ButtonComponent import; adjusted empty-state icon sizing.
Committee view simplification
apps/lfx-pcc/.../committee-view/committee-view.component.html, apps/lfx-pcc/.../committee-view/committee-view.component.ts
Removed Subcommittees UI from template and removed TableComponent import; no new business logic added.
Type color pipe
apps/lfx-pcc/src/app/shared/pipes/committee-type-colors.pipe.ts
Added CommitteeTypeColorPipe delegating to shared constant getter for mapping committee type to color class.
Shared constants for type colors
packages/shared/src/constants/committees.ts
Added COMMITTEE_TYPE_COLORS map, DEFAULT_COMMITTEE_TYPE_COLOR, and getCommitteeTypeColor(type) lookup function.
Committee interfaces update
packages/shared/src/interfaces/committee.interface.ts
Changed data shape: replaced committee_id with optional `parent_uid?: string
Docs update: Angular patterns
docs/architecture/frontend/angular-patterns.md
Added “Data Transformation Best Practices” section advocating pipes over component method calls with examples and benefits.

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant Dashboard as CommitteeDashboardComponent
  participant Filters as Signals (search/category/votingStatus)
  participant Table as CommitteeTableComponent
  User->>Dashboard: Load dashboard
  Dashboard->>Filters: Initialize signals and computed metrics
  Dashboard->>Table: Pass filtered committees
  User->>Dashboard: Update search/category/voting status
  Dashboard->>Filters: Update filters and reset paging
  Dashboard->>Table: Update committees input
  User->>Table: Click Edit/View/Delete
  Table-->>Dashboard: emit edit/view/delete events
  Dashboard->>Dashboard: Handle navigation/confirm delete
Loading
sequenceDiagram
  actor User
  participant Form as CommitteeFormComponent
  participant Project as ProjectService
  participant Data as Committees API
  User->>Form: Open create/edit committee dialog
  Form->>Project: Get current projectId
  alt projectId exists
    Form->>Data: Fetch project committees (as Signal)
    Data-->>Form: Committees list
    Form->>Form: Build parent options (top-level, exclude current)
  else no projectId
    Form->>Form: Use default "No Parent Committee" option
  end
  User->>Form: Select Parent Committee (parent_uid)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 243c1d8 and bca038d.

📒 Files selected for processing (1)
  • packages/shared/src/constants/committees.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/shared/src/constants/committees.ts
⏰ 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: E2E Tests / Playwright E2E Tests
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/LFXV2-256

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

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

This PR adds comprehensive subcommittee support with enhanced filtering and improved performance to the committee management system. The changes focus on implementing hierarchical committee structures with parent-child relationships and modernizing the UI with better filters and performance optimizations.

Key Changes

  • Added subcommittee functionality with parent committee selection in forms and hierarchical display in tables
  • Enhanced filtering system with committee type and voting status filters that include dynamic counts
  • Replaced method-based date formatting with Angular's built-in date pipe for better performance
  • Implemented comprehensive menu actions (View/Delete) in committee tables using signal-based patterns

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/shared/src/interfaces/committee.interface.ts Updated Committee interface to use parent_uid for hierarchical relationships
packages/shared/src/constants/committees.ts Added committee type color mappings and utility functions for consistent styling
docs/architecture/frontend/angular-patterns.md Added documentation for pipe vs method best practices in templates
apps/lfx-pcc/src/app/shared/pipes/committee-type-colors.pipe.ts Created new pipe for committee type color transformation
apps/lfx-pcc/src/app/shared/components/treetable/ New reusable TreeTable component for hierarchical data display
apps/lfx-pcc/src/app/modules/project/committees/components/upcoming-committee-meeting/ Simplified component by removing unused button imports and elements
apps/lfx-pcc/src/app/modules/project/committees/components/committee-table/ New dedicated table component with menu actions and hierarchical display
apps/lfx-pcc/src/app/modules/project/committees/components/committee-form/ Added parent committee dropdown with proper filtering logic
apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/ Enhanced dashboard with statistics, improved filters, and table integration

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

@github-actions
Copy link

github-actions bot commented Aug 14, 2025

✅ E2E Tests Passed

Browser: chromium
Status: passed

All E2E tests passed successfully.

Test Configuration

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🔭 Outside diff range comments (3)
apps/lfx-pcc/src/app/modules/project/committees/components/upcoming-committee-meeting/upcoming-committee-meeting.component.ts (1)

33-41: Fix runtime error: computed reads upcomingMeeting before it’s initialized

initializeCommittees() uses a computed that calls this.upcomingMeeting(). Since committees is initialized in the constructor and upcomingMeeting is assigned later in ngOnInit, the computed will attempt to call undefined as a function and throw.

Move committees initialization to after upcomingMeeting is set.

   public committees!: Signal<string>;

-  public constructor() {
-    this.committees = this.initializeCommittees();
-  }
+  public constructor() {}

   public ngOnInit() {
     runInInjectionContext(this.injector, () => {
       this.upcomingMeeting = this.initializeUpcomingMeeting();
+      this.committees = this.initializeCommittees();
     });
   }

Alternative (if you prefer to keep constructor init): guard the call site inside initializeCommittees:

return computed(() => this.upcomingMeeting?.()?.meeting_committees?.map(c => c.name).join(', ') ?? '');
apps/lfx-pcc/src/app/modules/project/committees/components/committee-form/committee-form.component.ts (1)

37-43: Loading state bug: template uses loading(), code toggles submitting().

The button binds to loading(), but only submitting is toggled in code. Either switch the template to submitting() or derive loading from submitting.

Apply this diff to mirror submitting:

   // Create form group internally
   public form = signal<FormGroup>(this.createCommitteeFormGroup());
-  public loading = signal<boolean>(false);
+  public loading = computed(() => this.submitting());

This keeps the template unchanged while reflecting the actual submit state.

apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts (1)

241-251: Make committees initialization reactive to project changes

initializeCommittees reads project() once. If project signal resolves after construction, committees would stay []. Make it reactive to project changes by combining the project signal with refresh.

Apply these diffs:

  1. Update rxjs-interop import:
-import { toSignal } from '@angular/core/rxjs-interop';
+import { toSignal, toObservable } from '@angular/core/rxjs-interop';
  1. Add combineLatest import:
-import { BehaviorSubject, of } from 'rxjs';
+import { BehaviorSubject, of, combineLatest } from 'rxjs';
  1. Rewrite initializeCommittees:
-  private initializeCommittees(): Signal<Committee[]> {
-    return toSignal(
-      this.project()
-        ? this.refresh.pipe(
-            tap(() => this.committeesLoading.set(true)),
-            switchMap(() => this.committeeService.getCommitteesByProject(this.project()!.uid).pipe(tap(() => this.committeesLoading.set(false))))
-          )
-        : of([]),
-      { initialValue: [] }
-    );
-  }
+  private initializeCommittees(): Signal<Committee[]> {
+    const project$ = toObservable(this.project);
+    return toSignal(
+      combineLatest([project$, this.refresh]).pipe(
+        tap(() => this.committeesLoading.set(true)),
+        switchMap(([project]) => {
+          if (!project) {
+            this.committeesLoading.set(false);
+            return of([]);
+          }
+          return this.committeeService
+            .getCommitteesByProject(project.uid)
+            .pipe(tap(() => this.committeesLoading.set(false)));
+        })
+      ),
+      { initialValue: [] }
+    );
+  }

Also applies to: 20-21, 6-6

🧹 Nitpick comments (17)
apps/lfx-pcc/src/app/modules/project/committees/components/upcoming-committee-meeting/upcoming-committee-meeting.component.html (1)

32-32: Mark decorative icon as aria-hidden for accessibility

The calendar icon is decorative. Hide it from assistive technologies.

-    <i class="fa-light fa-calendar text-xl text-gray-400 mb-2"></i>
+    <i class="fa-light fa-calendar text-xl text-gray-400 mb-2" aria-hidden="true"></i>
docs/architecture/frontend/angular-patterns.md (1)

168-197: Refine guidance: prefer pipes, but allow signals; clarify change-detection note

The blanket “always” statement conflicts with our established use of Angular Signals in templates (memoized; not re-executed each CD cycle). Adjust wording to avoid discouraging signal usage and fix the CD note.

-For data transformation in templates, always use Angular pipes instead of component methods:
+Prefer Angular pipes for data transformation in templates. Angular Signals (e.g., `value()`) are also appropriate for simple, memoized transformations. Avoid invoking arbitrary component methods in templates:
-5. **Change Detection**: Methods are called on every change detection cycle, pipes only when needed
+5. **Change Detection**: Regular component methods are called on every change detection cycle; pipes and signals re-run only when their inputs change

Optional: Add a short note after the GOOD example:

+> Note: When you see calls like `size()` or `styleClass()` in templates across this codebase, those are Angular Signals, not plain methods. Signals are memoized and safe to use in templates.

This aligns with prior learnings about signals usage in templates.

apps/lfx-pcc/src/app/modules/project/committees/components/committee-form/committee-form.component.html (1)

39-52: Add data-testid to new Parent Committee selector (testing guideline).

Per repo guidelines for apps/**/*.html, add a data-testid. Suggest consistent naming: section-component-element.

Apply this diff:

       <lfx-select
         size="small"
         [form]="form()"
         control="parent_uid"
         [options]="parentCommitteeOptions()"
         placeholder="Select a parent committee"
         styleClass="w-full"
         id="parent-committee"
-        [showClear]="true"></lfx-select>
+        [showClear]="true"
+        [attr.data-testid]="'committees-committee-form-parent-select'"></lfx-select>
apps/lfx-pcc/src/app/modules/project/committees/components/committee-form/committee-form.component.ts (3)

51-53: Good addition; consider reusing a typed option interface.

parentCommitteeOptions is clear. If this pattern is reused, consider a shared Option interface to avoid repetition.


179-207: Sort parent options alphabetically (deterministic UX, aligns with filter sorting goal).

Sorting by committee name improves predictability and aligns with the PR’s emphasis on alphabetically sorted options.

Apply this diff:

         // Transform to dropdown options
-          const options = availableCommittees.map((committee) => ({
-            label: committee.name,
-            value: committee.id,
-          }));
+          const options = availableCommittees
+            .map((committee) => ({
+              label: committee.name,
+              value: committee.id,
+            }))
+            .sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: 'base' }));

214-214: Potential type/contract mismatch: parent_uid null vs interface string.

The form sets parent_uid to null for “No Parent Committee”, but Committee.parent_uid is typed as string in packages/shared/src/interfaces/committee.interface.ts. Confirm backend expects null; otherwise map null to '' or omit the field before submit, or update the interface to string | null.

If backend expects empty string or missing property, adjust the submit payload:

// In onSubmit(), before calling the service
const formValue = this.form().value as any;
const payload = {
  ...formValue,
  parent_uid: formValue.parent_uid ?? '', // or: delete parent_uid if null
};

// use payload instead of formValue for create/update

Alternatively, update Committee interface to allow null:

export interface Committee {
  // …
  parent_uid: string | null;
  // …
}
apps/lfx-pcc/src/app/modules/project/committees/components/committee-table/committee-table.component.html (6)

5-6: Add data-testid to table root (testing guideline).

Add a stable selector for E2E and component tests.

Apply this diff:

-  <lfx-table [value]="organizedCommittees()" styleClass="committee-table">
+  <lfx-table [value]="organizedCommittees()" styleClass="committee-table" [attr.data-testid]="'committees-committee-table-root'">

15-17: Rename header to “Committee Type” for consistency with PR objective.

The PR objective renames “Category” to “Committee Type.” Update the column header accordingly.

Apply this diff:

-          <span class="text-xs font-medium text-gray-700">Type</span>
+          <span class="text-xs font-medium text-gray-700">Committee Type</span>

69-71: Prefer ngClass over class interpolation for composability.

Using [ngClass] avoids class string collisions and is more idiomatic.

Apply this diff:

-          <span class="text-xs font-medium {{ committee.category | committeeTypeColor }}">{{ committee.category }}</span>
+          <span class="text-xs font-medium" [ngClass]="committee.category | committeeTypeColor">{{ committee.category }}</span>

38-59: Standardize data-testid naming to guideline format.

Adopt the '[section]-[component]-[element]' convention to improve test readability and searchability.

Apply this diff:

-      <tr class="border-b border-gray-50 hover:bg-gray-50/50 transition-colors" [attr.data-testid]="'committee-table-row-' + committee.id">
+      <tr class="border-b border-gray-50 hover:bg-gray-50/50 transition-colors" [attr.data-testid]="'committees-committee-table-row-' + committee.id">

And for action buttons below (also see lines 124, 133, 142):

-              [attr.data-testid]="'committee-edit-' + committee.id" />
+              [attr.data-testid]="'committees-committee-table-edit-' + committee.id" />
-              [attr.data-testid]="'committee-members-' + committee.id" />
+              [attr.data-testid]="'committees-committee-table-members-' + committee.id" />
-              [attr.data-testid]="'committee-more-' + committee.id" />
+              [attr.data-testid]="'committees-committee-table-more-' + committee.id" />

151-159: Add data-testid to empty state for deterministic assertions.

Provide a stable selector for “no data” assertions.

Apply this diff:

-        <td colspan="8" class="text-center py-8">
+        <td colspan="8" class="text-center py-8" [attr.data-testid]="'committees-committee-table-empty'">

116-143: Consider explicit accessible labels for icon-only buttons.

If lfx-button doesn’t propagate aria-label automatically, add an accessible label to improve a11y and screen reader support.

If supported by lfx-button, add ariaLabel (or set label with visually-hidden text):

-            <lfx-button
+            <lfx-button
               icon="fa-light fa-edit"
               [text]="true"
               [rounded]="true"
               size="small"
               severity="secondary"
               styleClass="h-8 w-8 p-0 text-gray-500 hover:text-gray-700"
               (onClick)="onEdit(committee)"
-              [attr.data-testid]="'committee-edit-' + committee.id" />
+              [attr.data-testid]="'committees-committee-table-edit-' + committee.id"
+              ariaLabel="Edit committee {{ committee.name }}" />

Please apply similarly for Members and More buttons if the API supports it. If not, we can add aria-label via [attr.aria-label].

apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.html (1)

47-49: Optional: Move percent computation into TS to reduce template work

The percent expression invokes computed signals multiple times in template. Moving it into a computed signal (e.g., publicCommitteesPercent) in the component improves readability and reduces redundant calls.

apps/lfx-pcc/src/app/shared/components/treetable/treetable.component.ts (2)

4-14: Enable OnPush change detection for performance

Wrapper components benefit from OnPush to minimize checks.

Apply this diff:

-import { CommonModule } from '@angular/common';
-import { Component, ContentChild, input, output, TemplateRef } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { Component, ContentChild, input, output, TemplateRef, ChangeDetectionStrategy } from '@angular/core';
@@
 @Component({
   selector: 'lfx-treetable',
   standalone: true,
   imports: [CommonModule, TreeTableModule],
   templateUrl: './treetable.component.html',
+  changeDetection: ChangeDetectionStrategy.OnPush,
 })

29-39: Type the expand/collapse outputs to concrete PrimeNG event shapes

Outputs and handlers are typed as any. If available in your PrimeNG version, use the specific event types for TreeTable expand/collapse to improve DX and prevent regressions.

apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts (2)

359-364: Menu item “disabled” won’t react to isDeleting changes

MenuItem.disabled is evaluated at creation time; the runtime signal change won’t update it. Guard in the command instead (or rebuild items on state change).

-        styleClass: 'text-red-500',
-        disabled: this.isDeleting(),
-        command: () => this.deleteCommittee(),
+        styleClass: 'text-red-500',
+        command: () => {
+          if (!this.isDeleting()) {
+            this.deleteCommittee();
+          }
+        },

65-67: Consider extracting a typed FilterOption interface

Multiple places use { label: string; value: string | null }. Define a shared FilterOption for consistency and maintainability (e.g., in packages/shared). This aligns with the repo’s emphasis on type safety.

Also applies to: 91-96

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between caae8fe and 1cc115a.

📒 Files selected for processing (14)
  • apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.html (1 hunks)
  • apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts (10 hunks)
  • apps/lfx-pcc/src/app/modules/project/committees/components/committee-form/committee-form.component.html (1 hunks)
  • apps/lfx-pcc/src/app/modules/project/committees/components/committee-form/committee-form.component.ts (4 hunks)
  • apps/lfx-pcc/src/app/modules/project/committees/components/committee-table/committee-table.component.html (1 hunks)
  • apps/lfx-pcc/src/app/modules/project/committees/components/committee-table/committee-table.component.ts (1 hunks)
  • apps/lfx-pcc/src/app/modules/project/committees/components/upcoming-committee-meeting/upcoming-committee-meeting.component.html (1 hunks)
  • apps/lfx-pcc/src/app/modules/project/committees/components/upcoming-committee-meeting/upcoming-committee-meeting.component.ts (1 hunks)
  • apps/lfx-pcc/src/app/shared/components/treetable/treetable.component.html (1 hunks)
  • apps/lfx-pcc/src/app/shared/components/treetable/treetable.component.ts (1 hunks)
  • apps/lfx-pcc/src/app/shared/pipes/committee-type-colors.pipe.ts (1 hunks)
  • docs/architecture/frontend/angular-patterns.md (1 hunks)
  • packages/shared/src/constants/committees.ts (1 hunks)
  • packages/shared/src/interfaces/committee.interface.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
{apps,packages}/**/*.{ts,tsx,js,jsx,css,scss}

📄 CodeRabbit Inference Engine (CLAUDE.md)

License headers are required on all source files

Files:

  • packages/shared/src/interfaces/committee.interface.ts
  • apps/lfx-pcc/src/app/shared/pipes/committee-type-colors.pipe.ts
  • apps/lfx-pcc/src/app/modules/project/committees/components/upcoming-committee-meeting/upcoming-committee-meeting.component.ts
  • apps/lfx-pcc/src/app/modules/project/committees/components/committee-table/committee-table.component.ts
  • packages/shared/src/constants/committees.ts
  • apps/lfx-pcc/src/app/shared/components/treetable/treetable.component.ts
  • apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts
  • apps/lfx-pcc/src/app/modules/project/committees/components/committee-form/committee-form.component.ts
packages/shared/src/{interfaces,constants,enums}/**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (CLAUDE.md)

All shared types, interfaces, and constants are centralized in @lfx-pcc/shared package

Files:

  • packages/shared/src/interfaces/committee.interface.ts
  • packages/shared/src/constants/committees.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Use TypeScript interfaces instead of union types for better maintainability

Files:

  • packages/shared/src/interfaces/committee.interface.ts
  • apps/lfx-pcc/src/app/shared/pipes/committee-type-colors.pipe.ts
  • apps/lfx-pcc/src/app/modules/project/committees/components/upcoming-committee-meeting/upcoming-committee-meeting.component.ts
  • apps/lfx-pcc/src/app/modules/project/committees/components/committee-table/committee-table.component.ts
  • packages/shared/src/constants/committees.ts
  • apps/lfx-pcc/src/app/shared/components/treetable/treetable.component.ts
  • apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts
  • apps/lfx-pcc/src/app/modules/project/committees/components/committee-form/committee-form.component.ts
packages/shared/src/interfaces/**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Interfaces go into the shared packages

Files:

  • packages/shared/src/interfaces/committee.interface.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • packages/shared/src/interfaces/committee.interface.ts
  • apps/lfx-pcc/src/app/shared/pipes/committee-type-colors.pipe.ts
  • apps/lfx-pcc/src/app/modules/project/committees/components/upcoming-committee-meeting/upcoming-committee-meeting.component.ts
  • apps/lfx-pcc/src/app/modules/project/committees/components/committee-table/committee-table.component.ts
  • packages/shared/src/constants/committees.ts
  • apps/lfx-pcc/src/app/shared/components/treetable/treetable.component.ts
  • apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts
  • apps/lfx-pcc/src/app/modules/project/committees/components/committee-form/committee-form.component.ts
apps/**/src/**/*.html

📄 CodeRabbit Inference Engine (CLAUDE.md)

apps/**/src/**/*.html: Always add data-testid attributes when creating new components for reliable test targeting
Use data-testid naming convention - '[section]-[component]-[element]' for hierarchical structure

Files:

  • apps/lfx-pcc/src/app/modules/project/committees/components/upcoming-committee-meeting/upcoming-committee-meeting.component.html
  • apps/lfx-pcc/src/app/modules/project/committees/components/committee-form/committee-form.component.html
  • apps/lfx-pcc/src/app/shared/components/treetable/treetable.component.html
  • apps/lfx-pcc/src/app/modules/project/committees/components/committee-table/committee-table.component.html
  • apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.html
🧠 Learnings (2)
📚 Learning: 2025-08-06T00:40:54.228Z
Learnt from: asithade
PR: linuxfoundation/lfx-v2-pcc-ui#24
File: apps/lfx-pcc/src/app/shared/components/multi-select/multi-select.component.html:16-18
Timestamp: 2025-08-06T00:40:54.228Z
Learning: In Angular applications, when reviewing template code that uses parentheses syntax like `size()` or `styleClass()`, these may be Angular signals rather than regular methods. Angular signals are memoized and only re-compute when their dependencies change, unlike regular methods which execute on every change detection cycle. Therefore, the performance concerns about avoiding method calls in templates don't apply to signals.

Applied to files:

  • docs/architecture/frontend/angular-patterns.md
📚 Learning: 2025-08-07T16:35:57.360Z
Learnt from: CR
PR: linuxfoundation/lfx-v2-pcc-ui#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-07T16:35:57.360Z
Learning: All PrimeNG components are wrapped in LFX components for UI library independence

Applied to files:

  • apps/lfx-pcc/src/app/shared/components/treetable/treetable.component.ts
🧬 Code Graph Analysis (5)
apps/lfx-pcc/src/app/shared/pipes/committee-type-colors.pipe.ts (1)
packages/shared/src/constants/committees.ts (1)
  • getCommitteeTypeColor (70-72)
apps/lfx-pcc/src/app/modules/project/committees/components/committee-table/committee-table.component.ts (4)
apps/lfx-pcc/src/app/modules/project/committees/components/upcoming-committee-meeting/upcoming-committee-meeting.component.ts (1)
  • Component (16-73)
apps/lfx-pcc/src/app/shared/components/treetable/treetable.component.ts (1)
  • Component (9-40)
apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts (1)
  • Component (27-367)
packages/shared/src/interfaces/committee.interface.ts (1)
  • Committee (4-28)
apps/lfx-pcc/src/app/shared/components/treetable/treetable.component.ts (4)
apps/lfx-pcc/src/app/modules/project/committees/components/committee-table/committee-table.component.ts (1)
  • Component (15-108)
apps/lfx-pcc/src/app/modules/project/committees/components/committee-form/committee-form.component.ts (1)
  • Component (22-227)
apps/lfx-pcc/src/app/modules/project/committees/components/upcoming-committee-meeting/upcoming-committee-meeting.component.ts (1)
  • Component (16-73)
apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts (1)
  • Component (27-367)
apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts (3)
apps/lfx-pcc/src/app/modules/project/committees/components/committee-table/committee-table.component.ts (1)
  • Component (15-108)
apps/lfx-pcc/src/app/modules/project/committees/committee-view/committee-view.component.ts (1)
  • Component (24-223)
packages/shared/src/interfaces/committee.interface.ts (1)
  • Committee (4-28)
apps/lfx-pcc/src/app/modules/project/committees/components/committee-form/committee-form.component.ts (1)
packages/shared/src/interfaces/committee.interface.ts (1)
  • Committee (4-28)
🪛 LanguageTool
docs/architecture/frontend/angular-patterns.md

[grammar] ~164-~164: There might be a mistake here.
Context: ...## 🔄 Data Transformation Best Practices ### Use Pipes Instead of Methods For data tr...

(QB_NEW_EN)

⏰ 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: Code Quality Checks
🔇 Additional comments (15)
apps/lfx-pcc/src/app/modules/project/committees/components/committee-form/committee-form.component.html (1)

39-52: LGTM: Optional parent control wired to Signals and clearable UI.

Binding to a Signal-based options provider and allowing clear maps well to the subcommittee design. The helper text is clear.

apps/lfx-pcc/src/app/shared/pipes/committee-type-colors.pipe.ts (1)

1-15: LGTM: Focused, pure pipe leveraging shared mapping.

  • License header present.
  • Standalone pipe is minimal and reusable.
  • Relies on centralized getCommitteeTypeColor for consistency.
apps/lfx-pcc/src/app/shared/components/treetable/treetable.component.html (1)

1-34: LGTM: Clean content projection with clear contexts.

Header/body/emptymessage templates are guarded and pass a well-structured context. Event wiring is straightforward.

apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.html (1)

120-127: LGTM: Dedicated table component + test id

Good move to encapsulate the table into lfx-committee-table and expose a stable data-testid="committee-dashboard-table" for automation. This aligns with the new component architecture and testability goals.

apps/lfx-pcc/src/app/modules/project/committees/components/committee-table/committee-table.component.ts (2)

42-44: Verify parent_uid nullability vs interface typing

Logic treats “no parent” as falsy (!c.parent_uid), but the shared interface types parent_uid as string (non-null). If backend returns null, the typing is inaccurate; if it returns '', logic still works but is brittle.

Would you confirm the backend payload for committees with no parent?

  • If null is possible/preferred, update the interface to parent_uid: string | null in packages/shared/src/interfaces/committee.interface.ts and keep the truthy checks.
  • If empty string is used, consider normalizing in a mapper to null to avoid edge cases.

80-107: LGTM: Action menu and event outputs

Menu setup is clean; selectedCommittee via signal + command closures is straightforward. View/Delete emitters match the dashboard’s handlers.

apps/lfx-pcc/src/app/shared/components/treetable/treetable.component.ts (1)

9-20: LGTM: PrimeNG wrapped behind LFX façade

This wrapper aligns with the “wrap PrimeNG components” learning. Content projection and event pass-through look good.

apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts (8)

75-79: LGTM: Statistics signals

Computed totals for total/public/voting are clean and feed the dashboard metrics effectively.


113-118: LGTM: Voting status filter handler

Handler updates the signal and resets paging as expected.


120-123: LGTM: Search resets pagination

Keeps UX consistent during search refinement.


144-159: LGTM: Table action wiring

Child component emits are correctly mapped to view/edit/delete flows via selectedCommittee.


231-234: LGTM: Added votingStatus control

Form wiring looks correct and consistent with the new filter.


253-276: LGTM: Committee type options with counts and alphabetical order

Meets the “Committee Type” filter requirement with counts and sorting.


278-291: LGTM: Voting status options with counts

Labels and counts align with objectives; “All Voting Status” default is clear.


315-324: LGTM: Voting status filtering logic

Clear mapping from filter value to boolean flags (enabled/disabled).

- Add conditional check to prevent date pipe failure when updated_at is undefined
- Display '-' as fallback when no updated_at value exists
- Ensures table renders correctly for committees without update timestamps

🤖 Generated with [Claude Code](https://claude.ai/code)

Signed-off-by: Asitha de Silva <[email protected]>
- Add data-testid attributes for all UI elements: New Committee CTA, statistics cards, search input, filters, and Add First Committee button
- Map all 19 committee categories to specific colors based on meeting type color schemes
- Group committees logically: Board/governance (red), Technical (purple/blue), Legal/compliance (amber), Marketing (green), Finance (emerald), Working groups (orange/yellow), Other (gray)
- Remove unused treetable component to reduce bundle size
- Ensure comprehensive test coverage with proper element targeting

🤖 Generated with [Claude Code](https://claude.ai/code)

Signed-off-by: Asitha de Silva <[email protected]>
- Remove subcommittees table section that referenced non-existent data structure
- Remove subcommittees count display from committee stats
- Clean up unused TableComponent import and Injector dependency
- Add TODO comments for future subcommittee implementation
- Fixes TypeScript build errors and reduces bundle size

🤖 Generated with [Claude Code](https://claude.ai/code)

Signed-off-by: Asitha de Silva <[email protected]>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🔭 Outside diff range comments (2)
apps/lfx-pcc/src/app/modules/project/committees/committee-view/committee-view.component.ts (2)

17-17: Add error handling to set error/loading on fetch failures

Network errors from getCommittee/getCommitteeMembers currently surface unhandled, leaving loading/membersLoading stuck. Add catchError to set flags and return null.

Apply:

-import { BehaviorSubject, combineLatest, of, switchMap } from 'rxjs';
+import { BehaviorSubject, combineLatest, of, switchMap, catchError } from 'rxjs';
@@
   private initializeCommittee(): Signal<Committee | null> {
     return toSignal(
       combineLatest([this.route.paramMap, this.refresh]).pipe(
         switchMap(([params]) => {
           const committeeId = params?.get('id');
           if (!committeeId) {
             this.error.set(true);
             return of(null);
           }
 
           return combineLatest([this.committeeService.getCommittee(committeeId), this.committeeService.getCommitteeMembers(committeeId)]).pipe(
             switchMap(([committee, members]) => {
               this.members.set(members);
               this.loading.set(false);
               this.membersLoading.set(false);
               return of(committee);
             })
-          );
+          );
         })
-      ),
+      ),
+      catchError((err) => {
+        console.error('Failed to load committee or members:', err);
+        this.error.set(true);
+        this.loading.set(false);
+        this.membersLoading.set(false);
+        return of(null);
+      }),
     { initialValue: null }
     );
   }

Also applies to: 147-169


171-189: Make actionMenuItems reactive via a computed Signal

The current disabled: this.isDeleting() is evaluated only once at init and won’t update as deleting changes. Convert actionMenuItems into a Signal<MenuItem[]> so its disabled flag stays in sync:

• In committee-view.component.ts:

  • Change
    public actionMenuItems: MenuItem[];
    to
    public readonly actionMenuItems: Signal<MenuItem[]>;
  • Import from @angular/core:
    import { computed, Signal } from '@angular/core';

• Replace your initializeActionMenuItems() to return a computed signal:
diff -private initializeActionMenuItems(): MenuItem[] { - return [ - { label: 'Edit', icon: 'fa-light fa-edit', command: () => this.editCommittee() }, - { separator: true }, - { - label: 'Delete', - icon: 'fa-light fa-trash', - styleClass: 'text-red-500', - disabled: this.isDeleting(), - command: () => this.deleteCommittee(), - }, - ]; -} +private initializeActionMenuItems(): Signal<MenuItem[]> { + return computed(() => [ + { label: 'Edit', icon: 'fa-light fa-edit', command: () => this.editCommittee() }, + { separator: true }, + { + label: 'Delete', + icon: 'fa-light fa-trash', + styleClass: 'text-red-500', + disabled: this.isDeleting(), + command: () => this.deleteCommittee(), + }, + ]); +}
• In the template, call the signal rather than bind it directly:

-<p-menu [model]="actionMenuItems"></p-menu>
+<p-menu [model]="actionMenuItems()"></p-menu>
🧹 Nitpick comments (5)
apps/lfx-pcc/src/app/modules/project/committees/committee-view/committee-view.component.ts (2)

89-91: Set membersLoading to true when refreshing members

On refresh, the loading indicator never re-enables. Flip it to true before triggering the refresh stream.

Apply:

   public refreshMembers(): void {
-    this.refresh.next();
+    this.membersLoading.set(true);
+    this.refresh.next();
   }

191-204: Consider using Angular DatePipe in the template for i18n and consistency

Optional: Replace manual date formatting signals with the built-in date pipe in the template (respects LOCALE_ID, reduces code). Keep if template already consumes these signals widely.

Also applies to: 206-219

packages/shared/src/constants/committees.ts (2)

95-97: Trim input before lookup to avoid accidental defaulting

Guard against trailing/leading spaces from APIs or user input.

Apply:

 export function getCommitteeTypeColor(type: string): string {
-  return COMMITTEE_TYPE_COLORS[type as keyof typeof COMMITTEE_TYPE_COLORS] || DEFAULT_COMMITTEE_TYPE_COLOR;
+  const normalized = (type ?? '').trim();
+  return COMMITTEE_TYPE_COLORS[normalized as keyof typeof COMMITTEE_TYPE_COLORS] || DEFAULT_COMMITTEE_TYPE_COLOR;
 }

85-91: Export a CommitteeType alias for stronger typing in consumers

Expose CommitteeType = keyof typeof COMMITTEE_TYPE_COLORS so component inputs/forms can constrain to known values where appropriate (while still allowing string where backend may be open-ended).

Apply:

 } as const;
 
+export type CommitteeType = keyof typeof COMMITTEE_TYPE_COLORS;
+
 /**
  * Default color scheme for unknown committee types
  */
 export const DEFAULT_COMMITTEE_TYPE_COLOR = 'text-gray-500';
apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.html (1)

23-31: Align data-testid values to the '[section]-[component]-[element]' convention

Ids are present (good), but they don’t follow the standardized naming. Rename to stable, hierarchical selectors and add missing hooks for key values.

Apply:

-        <lfx-button
-          label="New Committee"
-          icon="fa-light fa-plus"
-          severity="primary"
-          (onClick)="openCreateDialog()"
-          size="small"
-          data-testid="committee-new-cta">
+        <lfx-button
+          label="New Committee"
+          icon="fa-light fa-plus"
+          severity="primary"
+          (onClick)="openCreateDialog()"
+          size="small"
+          data-testid="committee-dashboard-header-new-committee-btn">
         </lfx-button>
@@
-      <div class="grid grid-cols-1 md:grid-cols-4 gap-3 w-full">
-        <lfx-card styleClass="bg-white border border-gray-100 shadow-sm h-full" data-testid="stats-total-committees">
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-3 w-full">
+        <lfx-card styleClass="bg-white border border-gray-100 shadow-sm h-full" data-testid="committee-dashboard-stats-total-card">
           <div class="p-3">
             <div class="text-[10px] text-gray-500 font-normal mb-1">Total Committees</div>
             <div class="flex items-center gap-2">
-              <span class="text-[24px] text-gray-900 font-normal">{{ totalCommittees() }}</span>
+              <span class="text-[24px] text-gray-900 font-normal" data-testid="committee-dashboard-stats-total">{{ totalCommittees() }}</span>
               <div class="flex items-center gap-1 text-emerald-600">
                 <i class="fa-light fa-trending-up text-[8px]"></i>
                 <span class="text-[10px] font-medium">+2 this week</span>
               </div>
             </div>
           </div>
         </lfx-card>
@@
-        <lfx-card styleClass="bg-white border border-gray-100 shadow-sm h-full" data-testid="stats-public-committees">
+        <lfx-card styleClass="bg-white border border-gray-100 shadow-sm h-full" data-testid="committee-dashboard-stats-public-card">
           <div class="p-3">
             <div class="text-[10px] text-gray-500 font-normal mb-1">Public Committees</div>
             <div class="flex items-center gap-2">
-              <span class="text-[24px] text-gray-900 font-normal">{{ publicCommittees() }}</span>
+              <span class="text-[24px] text-gray-900 font-normal" data-testid="committee-dashboard-stats-public">{{ publicCommittees() }}</span>
               <div class="inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-blue-100 text-blue-600 border border-blue-200">
-                <span class="text-[9px] font-medium"
-                  >{{ totalCommittees() > 0 ? ((publicCommittees() / totalCommittees()) * 100 | number: '1.0-0') : 0 }}% of total</span
-                >
+                <span class="text-[9px] font-medium" data-testid="committee-dashboard-stats-public-percent">
+                  {{ totalCommittees() > 0 ? ((publicCommittees() / totalCommittees()) * 100 | number: '1.0-0') : 0 }}% of total
+                </span>
               </div>
             </div>
           </div>
         </lfx-card>
@@
-        <lfx-card styleClass="bg-white border border-gray-100 shadow-sm h-full" data-testid="stats-active-voting">
+        <lfx-card styleClass="bg-white border border-gray-100 shadow-sm h-full" data-testid="committee-dashboard-stats-active-voting-card">
           <div class="p-3">
             <div class="text-[10px] text-gray-500 font-normal mb-1">Active Voting</div>
             <div class="flex items-center gap-2">
-              <span class="text-[24px] text-gray-900 font-normal">{{ activeVoting() }}</span>
+              <span class="text-[24px] text-gray-900 font-normal" data-testid="committee-dashboard-stats-active-voting">{{ activeVoting() }}</span>
               <div class="inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-green-100 text-green-600 border border-green-200">
                 <span class="text-[9px] font-medium">Voting enabled</span>
               </div>
             </div>
           </div>
         </lfx-card>
@@
-        <lfx-card styleClass="bg-white border border-gray-100 shadow-sm h-full items-center" data-testid="stats-upcoming-meeting">
+        <lfx-card styleClass="bg-white border border-gray-100 shadow-sm h-full items-center" data-testid="committee-dashboard-stats-upcoming-meeting-card">
           <div class="p-3">
             <div class="text-[10px] text-gray-500 font-normal mb-1">Upcoming Meeting</div>
-            <lfx-upcoming-committee-meeting></lfx-upcoming-committee-meeting>
+            <lfx-upcoming-committee-meeting data-testid="committee-dashboard-stats-upcoming-meeting"></lfx-upcoming-committee-meeting>
           </div>
         </lfx-card>
@@
-            <lfx-input-text
+            <lfx-input-text
+              data-testid="committee-dashboard-filters-search"
               [form]="searchForm"
               control="search"
               placeholder="Search committees..."
               icon="fa-light fa-search"
               styleClass="w-full"
               size="small"
-              data-testid="committee-search-input"></lfx-input-text>
+            ></lfx-input-text>
@@
-            <lfx-select
+            <lfx-select
+              data-testid="committee-dashboard-filters-type-select"
               [form]="searchForm"
               control="category"
               size="small"
               [options]="categories()"
               placeholder="Select Committee Type"
               [showClear]="true"
               styleClass="w-full"
-              (onChange)="onCategoryChange($event.value)"
-              data-testid="committee-type-filter"></lfx-select>
+              (onChange)="onCategoryChange($event.value)"></lfx-select>
@@
-            <lfx-select
+            <lfx-select
+              data-testid="committee-dashboard-filters-voting-select"
               [form]="searchForm"
               control="votingStatus"
               size="small"
               [options]="votingStatusOptions()"
               placeholder="Select Voting Status"
               [showClear]="true"
               styleClass="w-full"
-              (onChange)="onVotingStatusChange($event.value)"
-              data-testid="committee-voting-status-filter"></lfx-select>
+              (onChange)="onVotingStatusChange($event.value)"></lfx-select>
@@
-              <lfx-button
-                label="Add First Committee"
-                icon="fa-light fa-people-group"
-                severity="secondary"
-                (onClick)="openCreateDialog()"
-                data-testid="committee-add-first"></lfx-button>
+              <lfx-button
+                label="Add First Committee"
+                icon="fa-light fa-people-group"
+                severity="secondary"
+                (onClick)="openCreateDialog()"
+                data-testid="committee-dashboard-empty-add-first-btn"></lfx-button>

Also applies to: 33-61, 62-73, 74-79, 88-96, 100-110, 114-124, 147-153

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1cc115a and 243c1d8.

📒 Files selected for processing (6)
  • apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.html (1 hunks)
  • apps/lfx-pcc/src/app/modules/project/committees/committee-view/committee-view.component.html (0 hunks)
  • apps/lfx-pcc/src/app/modules/project/committees/committee-view/committee-view.component.ts (1 hunks)
  • apps/lfx-pcc/src/app/modules/project/committees/components/committee-table/committee-table.component.html (1 hunks)
  • packages/shared/src/constants/committees.ts (1 hunks)
  • packages/shared/src/interfaces/committee.interface.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • apps/lfx-pcc/src/app/modules/project/committees/committee-view/committee-view.component.html
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/lfx-pcc/src/app/modules/project/committees/components/committee-table/committee-table.component.html
🧰 Additional context used
📓 Path-based instructions (6)
{apps,packages}/**/*.{ts,tsx,js,jsx,css,scss}

📄 CodeRabbit Inference Engine (CLAUDE.md)

License headers are required on all source files

Files:

  • apps/lfx-pcc/src/app/modules/project/committees/committee-view/committee-view.component.ts
  • packages/shared/src/constants/committees.ts
  • packages/shared/src/interfaces/committee.interface.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Use TypeScript interfaces instead of union types for better maintainability

Files:

  • apps/lfx-pcc/src/app/modules/project/committees/committee-view/committee-view.component.ts
  • packages/shared/src/constants/committees.ts
  • packages/shared/src/interfaces/committee.interface.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • apps/lfx-pcc/src/app/modules/project/committees/committee-view/committee-view.component.ts
  • packages/shared/src/constants/committees.ts
  • packages/shared/src/interfaces/committee.interface.ts
packages/shared/src/{interfaces,constants,enums}/**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (CLAUDE.md)

All shared types, interfaces, and constants are centralized in @lfx-pcc/shared package

Files:

  • packages/shared/src/constants/committees.ts
  • packages/shared/src/interfaces/committee.interface.ts
packages/shared/src/interfaces/**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Interfaces go into the shared packages

Files:

  • packages/shared/src/interfaces/committee.interface.ts
apps/**/src/**/*.html

📄 CodeRabbit Inference Engine (CLAUDE.md)

apps/**/src/**/*.html: Always add data-testid attributes when creating new components for reliable test targeting
Use data-testid naming convention - '[section]-[component]-[element]' for hierarchical structure

Files:

  • apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.html
🧠 Learnings (2)
📚 Learning: 2025-08-07T16:35:57.360Z
Learnt from: CR
PR: linuxfoundation/lfx-v2-pcc-ui#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-07T16:35:57.360Z
Learning: Applies to apps/**/src/**/*.html : Always add data-testid attributes when creating new components for reliable test targeting

Applied to files:

  • apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.html
📚 Learning: 2025-08-07T16:35:57.360Z
Learnt from: CR
PR: linuxfoundation/lfx-v2-pcc-ui#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-07T16:35:57.360Z
Learning: Applies to apps/**/src/**/*.html : Use data-testid naming convention - '[section]-[component]-[element]' for hierarchical structure

Applied to files:

  • apps/lfx-pcc/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.html
⏰ 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: Code Quality Checks
🔇 Additional comments (3)
packages/shared/src/interfaces/committee.interface.ts (2)

8-8: LGTM: parent_uid nullability enables top-level committees

Making parent_uid nullable reflects top-level committees and prevents circular references. This aligns with the subcommittee model.


8-8: Verify API parent_uid presence across all endpoints

Please confirm with the backend whether the JSON payload for every Committee always includes a parent_uid field (using null for top-level) rather than omitting it.

  • If the API does guarantee parent_uid is always present (possibly null), update the interface to:
    // packages/shared/src/interfaces/committee.interface.ts
    export interface Committee {
      // …
      parent_uid: string | null;
      // remove the `?`
    }
  • Otherwise, leave it optional (parent_uid?: string | null) and ensure all consumers handle both null and undefined.

Current code relies on truthiness (!c.parent_uid, c.parent_uid === parent.id) and the form initializes missing values to null. Adjust only once you’ve confirmed the API’s behavior.

packages/shared/src/constants/committees.ts (1)

52-85: Good coverage and clear mapping to categories

Color mapping covers all defined committee categories with a sensible default and aligns to meeting types. Nice use of as const for type-safe lookup.

@asithade asithade merged commit 88ec9bb into main Aug 14, 2025
7 checks passed
@asithade asithade deleted the feat/LFXV2-256 branch August 14, 2025 23:36
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.

3 participants