Skip to content

Conversation

@andrest50
Copy link
Contributor

@andrest50 andrest50 commented Sep 26, 2025

Summary

  • Replace inefficient array fetching with dedicated count endpoints across multiple dashboard components
  • Add /api/meetings/count and /api/committees/count endpoints to backend
  • Update frontend services with getMeetingsCountByProject() and getCommitteesCountByProject() methods
  • Optimize project dashboard, meetings dashboard, and committees dashboard to use count endpoints

Performance Improvements

  • Reduced bandwidth: Only fetches count numbers instead of full resource arrays
  • Better scalability: Performance no longer degrades with resource growth
  • Faster loading: Count endpoints are much more efficient than full resource fetching

Changes Made

Backend

  • Add getMeetingsCount() and getCommitteesCount() controller methods
  • Add count routes to meetings and committees routers
  • Utilize existing optimized count service methods

Frontend

  • Add count methods to meeting and committee services
  • Update project dashboard to use count endpoints for total meetings/committees statistics
  • Update meetings dashboard total meetings display to use count endpoint
  • Update committees dashboard total committees display to use count endpoint

Test Plan

  • Verify all dashboards display correct counts
  • Test performance improvement with count endpoints vs full resource fetching
  • Ensure existing functionality remains unchanged
  • Validate error handling and fallback values
  • Run linting and build checks

JIRA References

🤖 Generated with Claude Code

Replace inefficient full resource fetching with dedicated count endpoints
for project metrics. This improves performance by avoiding unnecessary
data transfer when only counts are needed.

- Add getMeetingsCount() method to meeting service
- Add getCommitteesCount() method to committee service
- Add QueryServiceCountResponse interface for count API responses
- Update project controller to use count methods instead of fetching arrays
- Remove TODO comments as optimization is now implemented

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

Signed-off-by: Andres Tobon <[email protected]>
Replace inefficient array fetching with dedicated count endpoints across
multiple dashboard components to improve performance and reduce bandwidth usage.

Frontend changes:
- Add getMeetingsCountByProject() and getCommitteesCountByProject() methods to services
- Update project dashboard to use count endpoints for total statistics
- Update meetings dashboard to use count endpoint for total meetings display
- Update committees dashboard to use count endpoint for total committees display

Backend changes:
- Add /api/meetings/count and /api/committees/count endpoints
- Add getMeetingsCount() and getCommitteesCount() controller methods
- Utilize existing optimized count service methods

Performance improvements:
- Reduced bandwidth by fetching counts instead of full resource arrays
- Better scalability as performance no longer degrades with resource growth
- Faster loading times for dashboard statistics

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

Signed-off-by: Andres Tobon <[email protected]>
@andrest50 andrest50 requested a review from jordane as a code owner September 26, 2025 20:34
Copilot AI review requested due to automatic review settings September 26, 2025 20:34
@coderabbitai
Copy link

coderabbitai bot commented Sep 26, 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

Adds dedicated count endpoints and client count signals: new server routes/controllers/services return numeric counts for meetings and committees via the microservice proxy; frontend services call those endpoints and Angular components use Signal count signals instead of deriving counts from full lists.

Changes

Cohort / File(s) Summary
Frontend components: count signals and usage
apps/lfx-one/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts, apps/lfx-one/src/app/modules/project/meetings/meeting-dashboard/meeting-dashboard.component.ts, apps/lfx-one/src/app/modules/project/meetings/meeting-dashboard/meeting-dashboard.component.html, apps/lfx-one/src/app/modules/project/dashboard/project-dashboard/project.component.ts
Add meetingsCount / committeesCount signals and private initializers; wire signals in constructors; replace array-length derived totals with the new count signals; update template to call meetingsCount() for display.
Frontend services: count API calls
apps/lfx-one/src/app/shared/services/meeting.service.ts, apps/lfx-one/src/app/shared/services/committee.service.ts
Add getMeetingsCountByProject and getCommitteesCountByProject returning Observable<number>; build query with tags=project_uid:..., map { count } response to number, and handle errors by logging and returning 0.
Server routes and controllers: count endpoints
apps/lfx-one/src/server/routes/meetings.route.ts, apps/lfx-one/src/server/routes/committees.route.ts, apps/lfx-one/src/server/controllers/meeting.controller.ts, apps/lfx-one/src/server/controllers/committee.controller.ts
Add GET /meetings/count and GET /committees/count routes; implement controller handlers that call service getMeetingsCount / getCommitteesCount, log operations, respond with { count }, and forward errors to next().
Server services: count lookups via proxy
apps/lfx-one/src/server/services/meeting.service.ts, apps/lfx-one/src/server/services/committee.service.ts
Implement getMeetingsCount and getCommitteesCount to call microservice proxy /query/resources/count (merging query/type), and return numeric count from QueryServiceCountResponse.
Server: project metrics aggregation
apps/lfx-one/src/server/controllers/project.controller.ts
Replace list-based metric retrievals with dedicated getMeetingsCount / getCommitteesCount calls and cast to Number, falling back to 0 on error.
Shared types
packages/shared/src/interfaces/api.interface.ts
Add exported QueryServiceCountResponse interface with count: number and has_more: boolean.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Comp as MeetingDashboardComponent
  participant CliSvc as MeetingService (client)
  participant API as HTTP /api/meetings/count
  participant Router as MeetingsRouter
  participant Ctl as MeetingController.getMeetingsCount
  participant Svc as Server MeetingService.getMeetingsCount
  participant Proxy as Microservice Proxy (/query/resources/count)

  User->>Comp: View dashboard
  Comp->>CliSvc: getMeetingsCountByProject(project.uid)
  CliSvc->>API: GET /meetings/count?tags=project_uid:uid
  API->>Router: route
  Router->>Ctl: invoke
  Ctl->>Svc: getMeetingsCount(req, query, type?)
  Svc->>Proxy: GET /query/resources/count{...}
  Proxy-->>Svc: { count, has_more }
  Svc-->>Ctl: count (number)
  Ctl-->>API: { count }
  API-->>CliSvc: { count }
  CliSvc-->>Comp: number
  Note over Comp: meetingsCount signal updates (0 → response)
Loading
sequenceDiagram
  autonumber
  actor User
  participant Comp as CommitteeDashboardComponent / ProjectComponent
  participant CliSvc as CommitteeService (client)
  participant API as HTTP /api/committees/count
  participant Router as CommitteesRouter
  participant Ctl as CommitteeController.getCommitteesCount
  participant Svc as Server CommitteeService.getCommitteesCount
  participant Proxy as Microservice Proxy (/query/resources/count)

  User->>Comp: View committees
  Comp->>CliSvc: getCommitteesCountByProject(project.uid)
  CliSvc->>API: GET /committees/count?tags=project_uid:uid
  API->>Router: route
  Router->>Ctl: invoke
  Ctl->>Svc: getCommitteesCount(req, query)
  Svc->>Proxy: GET /query/resources/count{ type:'committee', ... }
  Proxy-->>Svc: { count, has_more }
  Svc-->>Ctl: count (number)
  Ctl-->>API: { count }
  API-->>CliSvc: { count }
  CliSvc-->>Comp: number
  Note over Comp: committeesCount signal updates
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "feat(api): add count endpoints for meetings and committees in dashboards" accurately describes the main change in the changeset. The changes introduce new /api/meetings/count and /api/committees/count endpoints in the backend and update multiple dashboard components to use these dedicated count endpoints instead of deriving counts from full array fetches. While the title doesn't capture every detail (such as the frontend service updates or the specific dashboard components modified), it clearly summarizes the primary change from a developer's perspective: adding count endpoints for meetings and committees in the context of dashboards.
Linked Issues Check ✅ Passed The code changes successfully address both linked issues. For LFXV2-585, the PR adds new count endpoints in the BFF through controller methods (getMeetingsCount and getCommitteesCount), service methods (getCommitteesCount and getMeetingsCount), and routes (/api/meetings/count and /api/committees/count) that expose the query-service count capability to the frontend. For LFXV2-589, the PR updates the UI components by adding frontend service methods (getMeetingsCountByProject and getCommitteesCountByProject) and modifying the project dashboard, meetings dashboard, and committees dashboard components to use these new count endpoints for displaying statistics instead of fetching full resource arrays. All coding-related requirements from both issues are met.
Out of Scope Changes Check ✅ Passed All changes in the pull request are directly related to the linked issues' objectives. The new QueryServiceCountResponse interface in the shared package, the backend controller and service methods for count endpoints, the new routes, the frontend service methods for retrieving counts, and the dashboard component updates all serve the stated goals of exposing count endpoints in the BFF (LFXV2-585) and using them in UI components that display statistics (LFXV2-589). There are no changes that appear unrelated to these objectives or that introduce functionality beyond what was requested in the linked issues.
Description Check ✅ Passed The PR description is comprehensive and directly related to the changeset. It provides a detailed summary of the changes including the replacement of array fetching with count endpoints, the addition of new backend routes and controller methods, frontend service updates, and modifications to multiple dashboard components. The description also includes performance improvement justifications, a breakdown of backend and frontend changes, a test plan, and references to the related JIRA issues (LFXV2-585 and LFXV2-589), all of which align with the actual code changes in the pull request.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch andrest50/count-resources

Tip

🧪 Early access (models): enabled

We are currently testing Sonnet 4.5 code review models, which should lead to better review quality. However, this model may result in higher noise levels in the review comments. Please disable the early access features if the noise level causes any inconvenience.

Note:

  • Public repositories are always opted into early access features.
  • You can enable or disable early access features from the CodeRabbit UI or by updating the CodeRabbit configuration file.

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

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 optimizes dashboard performance by replacing inefficient array fetching with dedicated count endpoints for meetings and committees across multiple dashboard components.

  • Add /api/meetings/count and /api/committees/count endpoints to backend with corresponding service methods
  • Update frontend services with getMeetingsCountByProject() and getCommitteesCountByProject() methods
  • Optimize project dashboard, meetings dashboard, and committees dashboard to use count endpoints instead of fetching full arrays

Reviewed Changes

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

Show a summary per file
File Description
packages/shared/src/interfaces/api.interface.ts Add QueryServiceCountResponse interface for count endpoint responses
apps/lfx-one/src/server/services/meeting.service.ts Add getMeetingsCount service method
apps/lfx-one/src/server/services/committee.service.ts Add getCommitteesCount service method
apps/lfx-one/src/server/routes/meetings.route.ts Add /count route endpoint
apps/lfx-one/src/server/routes/committees.route.ts Add /count route endpoint
apps/lfx-one/src/server/controllers/project.controller.ts Replace array length counting with count service calls
apps/lfx-one/src/server/controllers/meeting.controller.ts Add getMeetingsCount controller method
apps/lfx-one/src/server/controllers/committee.controller.ts Add getCommitteesCount controller method
apps/lfx-one/src/app/shared/services/meeting.service.ts Add getMeetingsCountByProject frontend service method
apps/lfx-one/src/app/shared/services/committee.service.ts Add getCommitteesCountByProject frontend service method
apps/lfx-one/src/app/modules/project/meetings/meeting-dashboard/meeting-dashboard.component.ts Use count endpoint for total meetings display
apps/lfx-one/src/app/modules/project/meetings/meeting-dashboard/meeting-dashboard.component.html Update template to use meetingsCount signal
apps/lfx-one/src/app/modules/project/dashboard/project-dashboard/project.component.ts Use count endpoints for project statistics
apps/lfx-one/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts Use count endpoint for total committees display

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@github-actions
Copy link

github-actions bot commented Sep 26, 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: 2

🧹 Nitpick comments (4)
apps/lfx-one/src/app/shared/services/meeting.service.ts (1)

25-80: Replace redundant switchMap with map in count flow.

Wrapping the response in of() and chaining another pipe/switchMap adds an unnecessary hop. Using map keeps the stream synchronous and removes the extra subscription layer.

-import { catchError, defer, Observable, of, switchMap, take, tap, throwError } from 'rxjs';
+import { catchError, defer, map, Observable, of, switchMap, take, tap, throwError } from 'rxjs';
@@
-    return this.http
-      .get<{ count: number }>('/api/meetings/count', { params })
-      .pipe(
-        catchError((error) => {
-          console.error('Failed to load meetings count:', error);
-          return of({ count: 0 });
-        })
-      )
-      .pipe(
-        // Extract just the count number from the response
-        switchMap((response) => of(response.count))
-      );
+    return this.http
+      .get<{ count: number }>('/api/meetings/count', { params })
+      .pipe(
+        catchError((error) => {
+          console.error('Failed to load meetings count:', error);
+          return of({ count: 0 });
+        }),
+        map((response) => response.count)
+      );
apps/lfx-one/src/app/shared/services/committee.service.ts (1)

7-43: Streamline count extraction with map.

Same pattern here—switchMap + of() is redundant. A single map keeps the observable chain cleaner.

-import { catchError, Observable, of, switchMap, take, tap, throwError } from 'rxjs';
+import { catchError, map, Observable, of, switchMap, take, tap, throwError } from 'rxjs';
@@
-    return this.http
-      .get<{ count: number }>('/api/committees/count', { params })
-      .pipe(
-        catchError((error) => {
-          console.error('Failed to load committees count:', error);
-          return of({ count: 0 });
-        })
-      )
-      .pipe(switchMap((response) => of(response.count)));
+    return this.http
+      .get<{ count: number }>('/api/committees/count', { params })
+      .pipe(
+        catchError((error) => {
+          console.error('Failed to load committees count:', error);
+          return of({ count: 0 });
+        }),
+        map((response) => response.count)
+      );
apps/lfx-one/src/server/controllers/project.controller.ts (2)

36-38: Fetch both counts in parallel per project

Slight perf win: run both count calls concurrently and then assign.

-          project.meetings_count = Number(await this.meetingService.getMeetingsCount(req, { tags: `project_uid:${project.uid}` }).catch(() => 0));
-          project.committees_count = Number(await this.committeeService.getCommitteesCount(req, { tags: `project_uid:${project.uid}` }).catch(() => 0));
+          const [meetingsCount, committeesCount] = await Promise.all([
+            this.meetingService.getMeetingsCount(req, { tags: `project_uid:${project.uid}` }).catch(() => 0),
+            this.committeeService.getCommitteesCount(req, { tags: `project_uid:${project.uid}` }).catch(() => 0),
+          ]);
+          project.meetings_count = Number(meetingsCount);
+          project.committees_count = Number(committeesCount);

Also applies to: 87-89


35-39: Consider upstream protection for large project lists

If project lists can be large, cap concurrency to protect the query service (e.g., p-limit). Optional, depending on typical list sizes.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a08bc3a and 56d100c.

📒 Files selected for processing (14)
  • apps/lfx-one/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts (4 hunks)
  • apps/lfx-one/src/app/modules/project/dashboard/project-dashboard/project.component.ts (4 hunks)
  • apps/lfx-one/src/app/modules/project/meetings/meeting-dashboard/meeting-dashboard.component.html (1 hunks)
  • apps/lfx-one/src/app/modules/project/meetings/meeting-dashboard/meeting-dashboard.component.ts (3 hunks)
  • apps/lfx-one/src/app/shared/services/committee.service.ts (2 hunks)
  • apps/lfx-one/src/app/shared/services/meeting.service.ts (1 hunks)
  • apps/lfx-one/src/server/controllers/committee.controller.ts (1 hunks)
  • apps/lfx-one/src/server/controllers/meeting.controller.ts (1 hunks)
  • apps/lfx-one/src/server/controllers/project.controller.ts (2 hunks)
  • apps/lfx-one/src/server/routes/committees.route.ts (1 hunks)
  • apps/lfx-one/src/server/routes/meetings.route.ts (1 hunks)
  • apps/lfx-one/src/server/services/committee.service.ts (2 hunks)
  • apps/lfx-one/src/server/services/meeting.service.ts (2 hunks)
  • packages/shared/src/interfaces/api.interface.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
packages/shared/src/interfaces/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Place all TypeScript interfaces in the shared package at packages/shared/src/interfaces

Files:

  • packages/shared/src/interfaces/api.interface.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript interfaces instead of union types for better maintainability
When defining PrimeNG-related types, reference the official PrimeNG component interfaces

Files:

  • packages/shared/src/interfaces/api.interface.ts
  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • apps/lfx-one/src/app/shared/services/meeting.service.ts
  • apps/lfx-one/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts
  • apps/lfx-one/src/server/controllers/project.controller.ts
  • apps/lfx-one/src/app/modules/project/meetings/meeting-dashboard/meeting-dashboard.component.ts
  • apps/lfx-one/src/server/services/committee.service.ts
  • apps/lfx-one/src/server/services/meeting.service.ts
  • apps/lfx-one/src/server/controllers/committee.controller.ts
  • apps/lfx-one/src/server/routes/meetings.route.ts
  • apps/lfx-one/src/app/modules/project/dashboard/project-dashboard/project.component.ts
  • apps/lfx-one/src/app/shared/services/committee.service.ts
  • apps/lfx-one/src/server/routes/committees.route.ts
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Include required license headers on all source files

Files:

  • packages/shared/src/interfaces/api.interface.ts
  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • apps/lfx-one/src/app/shared/services/meeting.service.ts
  • apps/lfx-one/src/app/modules/project/meetings/meeting-dashboard/meeting-dashboard.component.html
  • apps/lfx-one/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts
  • apps/lfx-one/src/server/controllers/project.controller.ts
  • apps/lfx-one/src/app/modules/project/meetings/meeting-dashboard/meeting-dashboard.component.ts
  • apps/lfx-one/src/server/services/committee.service.ts
  • apps/lfx-one/src/server/services/meeting.service.ts
  • apps/lfx-one/src/server/controllers/committee.controller.ts
  • apps/lfx-one/src/server/routes/meetings.route.ts
  • apps/lfx-one/src/app/modules/project/dashboard/project-dashboard/project.component.ts
  • apps/lfx-one/src/app/shared/services/committee.service.ts
  • apps/lfx-one/src/server/routes/committees.route.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • packages/shared/src/interfaces/api.interface.ts
  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • apps/lfx-one/src/app/shared/services/meeting.service.ts
  • apps/lfx-one/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts
  • apps/lfx-one/src/server/controllers/project.controller.ts
  • apps/lfx-one/src/app/modules/project/meetings/meeting-dashboard/meeting-dashboard.component.ts
  • apps/lfx-one/src/server/services/committee.service.ts
  • apps/lfx-one/src/server/services/meeting.service.ts
  • apps/lfx-one/src/server/controllers/committee.controller.ts
  • apps/lfx-one/src/server/routes/meetings.route.ts
  • apps/lfx-one/src/app/modules/project/dashboard/project-dashboard/project.component.ts
  • apps/lfx-one/src/app/shared/services/committee.service.ts
  • apps/lfx-one/src/server/routes/committees.route.ts
apps/lfx-one/src/**/*.html

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • apps/lfx-one/src/app/modules/project/meetings/meeting-dashboard/meeting-dashboard.component.html
🧬 Code graph analysis (2)
apps/lfx-one/src/server/services/committee.service.ts (1)
packages/shared/src/interfaces/api.interface.ts (1)
  • QueryServiceCountResponse (67-73)
apps/lfx-one/src/server/services/meeting.service.ts (1)
packages/shared/src/interfaces/api.interface.ts (1)
  • QueryServiceCountResponse (67-73)
⏰ 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
🔇 Additional comments (14)
apps/lfx-one/src/server/services/committee.service.ts (1)

53-65: LGTM: lean count endpoint wrapper

Clean params build and typed proxy with QueryServiceCountResponse. Returning the raw count keeps the controller usage simple.

apps/lfx-one/src/server/services/meeting.service.ts (1)

67-79: LGTM: meetings count support

Matches the query-service contract and keeps meetingType consistent with resource type.

apps/lfx-one/src/app/modules/project/meetings/meeting-dashboard/meeting-dashboard.component.ts (1)

58-59: LGTM: introduce meetingsCount signal

New signal cleanly separates total count from list data.

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

75-76: LGTM: totalCommittees derived from backend count

Using the count avoids loading full lists for the KPI.


64-65: LGTM: introduce committeesCount signal

Consistent with the meetings dashboard approach.

apps/lfx-one/src/app/modules/project/dashboard/project-dashboard/project.component.ts (3)

177-194: LGTM: meetings count signal with proper error fallback

Uses project$ and catchError; matches best practice for toSignal sources.


196-214: LGTM: committees count signal with proper error fallback

Pattern mirrors meetings count; solid.


322-340: LGTM: switch stats to backend counts

ProjectStats now uses counts from dedicated endpoints; array-derived stats remain for secondary metrics.

apps/lfx-one/src/app/modules/project/meetings/meeting-dashboard/meeting-dashboard.component.html (1)

145-145: Update meets Angular signals best practices.

The change to use meetingsCount() instead of meetings().length aligns with the performance optimization goal of the PR, enabling dedicated count endpoints without fetching full arrays. This follows Angular signals best practices for reactive data binding.

apps/lfx-one/src/server/routes/committees.route.ts (1)

14-14: Consider route ordering and potential conflicts.

The new /count route is correctly positioned before the /:id route, preventing parameter collision. The route delegation to committeeController.getCommitteesCount follows the established pattern.

packages/shared/src/interfaces/api.interface.ts (1)

63-74: Well-structured interface for count responses.

The QueryServiceCountResponse interface provides a clear contract for count endpoints with:

  • Typed count field for the resource count
  • has_more boolean to indicate if the query scope should be narrowed
  • Comprehensive documentation explaining the fields

This interface properly supports the count-focused API endpoints introduced in the PR.

As per coding guidelines, this interface is correctly placed in the shared package at packages/shared/src/interfaces.

apps/lfx-one/src/server/controllers/committee.controller.ts (1)

39-60: Consistent controller pattern for count endpoint.

The getCommitteesCount method follows the established controller pattern with:

  • Proper logging with Logger.start and Logger.success/Logger.error
  • Consistent error handling that forwards to next()
  • Clear response format { count } matching the API pattern

The implementation correctly delegates to the service layer and maintains consistency with existing controller methods.

apps/lfx-one/src/server/controllers/meeting.controller.ts (1)

69-94: Consistent implementation following established patterns.

The getMeetingsCount method maintains consistency with the existing controller patterns:

  • Proper logging with operation name get_meetings_count
  • Query parameter sanitization for security
  • Standard error handling and response format { count }
  • Clear documentation with route comment

The implementation correctly delegates to the service layer and follows the same structure as other controller methods.

apps/lfx-one/src/server/routes/meetings.route.ts (1)

21-23: No changes needed: count routes are consistent
Both meetings and committees define router.get('/count', …) under their respective mounts, yielding /api/meetings/count and /api/committees/count.

Likely an incorrect or invalid review comment.

…ty extraction

Replace unnecessary switchMap + of pattern with map for extracting count
property from HTTP responses in meeting and committee services.

Changes:
- meetingService.getMeetingsCountByProject(): use map instead of switchMap + of
- committeeService.getCommitteesCountByProject(): use map instead of switchMap + of

This follows RxJS best practices where map should be used for synchronous
transformations and switchMap only when flattening observables.

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

Signed-off-by: Andres Tobon <[email protected]>
@github-actions
Copy link

github-actions bot commented Sep 26, 2025

🚀 Deployment Status

Your branch has been deployed to: https://ui-pr-106.dev.v2.cluster.linuxfound.info

Deployment Details:

  • Environment: Development
  • Namespace: ui-pr-106
  • ArgoCD App: ui-pr-106

The deployment will be automatically removed when this PR is closed.

asithade
asithade previously approved these changes Sep 29, 2025
Copy link
Contributor

@asithade asithade left a comment

Choose a reason for hiding this comment

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

LGTM. Minor nit

… services

- Use QueryServiceCountResponse interface for better type safety in count endpoints
- Remove unnecessary computed() wrapper for totalCommittees signal
- Add proper interface imports for count response types

This ensures consistent typing across count endpoints and eliminates redundant
signal wrapping where direct signal assignment is sufficient.

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

Signed-off-by: Andres Tobon <[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: 1

🧹 Nitpick comments (1)
apps/lfx-one/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts (1)

75-76: Consider count endpoints for filtered statistics to match the performance optimization pattern.

While totalCommittees now uses a dedicated count endpoint, publicCommittees and activeVoting still derive from the full committees array. For consistency with the PR's performance goals, consider adding filtered count endpoints (e.g., getCommitteesCountByProject with query parameters for public and enable_voting filters) to avoid fetching the full array just for statistics.

Would you like me to open an issue to track adding filtered count endpoints for these statistics?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 56d100c and 4552009.

📒 Files selected for processing (3)
  • apps/lfx-one/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts (3 hunks)
  • apps/lfx-one/src/app/shared/services/committee.service.ts (2 hunks)
  • apps/lfx-one/src/app/shared/services/meeting.service.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/lfx-one/src/app/shared/services/committee.service.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript interfaces instead of union types for better maintainability
When defining PrimeNG-related types, reference the official PrimeNG component interfaces

Files:

  • apps/lfx-one/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts
  • apps/lfx-one/src/app/shared/services/meeting.service.ts
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Include required license headers on all source files

Files:

  • apps/lfx-one/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts
  • apps/lfx-one/src/app/shared/services/meeting.service.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • apps/lfx-one/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts
  • apps/lfx-one/src/app/shared/services/meeting.service.ts
🧬 Code graph analysis (1)
apps/lfx-one/src/app/shared/services/meeting.service.ts (1)
packages/shared/src/interfaces/api.interface.ts (1)
  • QueryServiceCountResponse (67-73)
⏰ 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
🔇 Additional comments (2)
apps/lfx-one/src/app/modules/project/committees/committee-dashboard/committee-dashboard.component.ts (1)

263-267: Address the reactivity and error handling issues flagged in previous review.

This method still has the critical issues identified in the previous review:

  1. The project check is evaluated once at construction time rather than reacting to project changes.
  2. Missing error handling that could cause the signal stream to break.

The previous review comment provides a complete solution using this.projectService.project$.pipe() with proper switchMap and catchError operators.

apps/lfx-one/src/app/shared/services/meeting.service.ts (1)

21-21: LGTM! Imports are correct.

The QueryServiceCountResponse interface and map operator are properly imported and necessary for the new count method implementation.

Also applies to: 26-26

Comment on lines +68 to +82
public getMeetingsCountByProject(projectId: string): Observable<number> {
const params = new HttpParams().set('tags', `project_uid:${projectId}`);
return this.http
.get<QueryServiceCountResponse>('/api/meetings/count', { params })
.pipe(
catchError((error) => {
console.error('Failed to load meetings count:', error);
return of({ count: 0 });
})
)
.pipe(
// Extract just the count number from the response
map((response) => response.count)
);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Combine operators into a single pipe call.

The double pipe chaining remains despite the previous review comment being marked as "Fixed." Both catchError and map should be combined into a single .pipe() call for idiomatic RxJS code.

Apply this diff to combine the operators:

 public getMeetingsCountByProject(projectId: string): Observable<number> {
   const params = new HttpParams().set('tags', `project_uid:${projectId}`);
-  return this.http
-    .get<QueryServiceCountResponse>('/api/meetings/count', { params })
-    .pipe(
-      catchError((error) => {
-        console.error('Failed to load meetings count:', error);
-        return of({ count: 0 });
-      })
-    )
-    .pipe(
-      // Extract just the count number from the response
-      map((response) => response.count)
-    );
+  return this.http.get<QueryServiceCountResponse>('/api/meetings/count', { params }).pipe(
+    catchError((error) => {
+      console.error('Failed to load meetings count:', error);
+      return of({ count: 0 });
+    }),
+    map((response) => response.count)
+  );
 }
📝 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.

Suggested change
public getMeetingsCountByProject(projectId: string): Observable<number> {
const params = new HttpParams().set('tags', `project_uid:${projectId}`);
return this.http
.get<QueryServiceCountResponse>('/api/meetings/count', { params })
.pipe(
catchError((error) => {
console.error('Failed to load meetings count:', error);
return of({ count: 0 });
})
)
.pipe(
// Extract just the count number from the response
map((response) => response.count)
);
}
public getMeetingsCountByProject(projectId: string): Observable<number> {
const params = new HttpParams().set('tags', `project_uid:${projectId}`);
return this.http.get<QueryServiceCountResponse>('/api/meetings/count', { params }).pipe(
catchError((error) => {
console.error('Failed to load meetings count:', error);
return of({ count: 0 });
}),
map((response) => response.count)
);
}
🤖 Prompt for AI Agents
In apps/lfx-one/src/app/shared/services/meeting.service.ts around lines 68 to
82, combine the two .pipe() calls into a single .pipe(...) invocation; keep the
existing operator order (catchError(...) then map(...)) so the catchError
returns a QueryServiceCountResponse fallback ({ count: 0 }) which the subsequent
map can extract, i.e. replace the chained .pipe(catchError(...)).pipe(map(...))
with one .pipe(catchError(...), map(response => response.count)).

@andrest50 andrest50 merged commit 56c1599 into main Sep 29, 2025
8 checks passed
@andrest50 andrest50 deleted the andrest50/count-resources branch September 29, 2025 17:37
@github-actions
Copy link

🧹 Deployment Removed

The deployment for PR #106 has been removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants