Skip to content

Conversation

@asithade
Copy link
Contributor

@asithade asithade commented Dec 23, 2025

Summary

  • Add meeting committee manager component with multi-select dropdown for committee associations
  • Enhance meeting registrants display with search, RSVP filtering, and role-based filtering
  • Add feature toggle shared component for form configurations
  • Update committee module UI with table and member card improvements
  • Add server API enhancements for meeting registrants with access control
  • Update dashboard and shared components with avatar/header improvements

Related Tickets

  • LFXV2-926 - Meeting Committee Manager Component
  • LFXV2-927 - Feature Toggle Shared Component
  • LFXV2-928 - Meeting Registrants Display Enhancement
  • LFXV2-929 - Committee Module UI Updates
  • LFXV2-930 - Dashboard and Shared Component Updates
  • LFXV2-931 - Meeting Server API Enhancements

Generated with Claude Code

- Add meeting committee manager component with multi-select dropdown
- Enhance meeting registrants display with search and filtering
- Add feature toggle shared component for form configurations
- Update committee module UI with table and member card improvements
- Add server API enhancements for meeting registrants
- Update dashboard and shared components with avatar/header improvements

LFXV2-926
LFXV2-927
LFXV2-928
LFXV2-929
LFXV2-930
LFXV2-931

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

Signed-off-by: Asitha de Silva <asithade@gmail.com>
@asithade asithade requested a review from jordane as a code owner December 23, 2025 08:52
Copilot AI review requested due to automatic review settings December 23, 2025 08:52
@coderabbitai
Copy link

coderabbitai bot commented Dec 23, 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 "Show Attendees" meeting feature across frontend and backend, a new MeetingCommitteeManager UI, reusable FeatureToggle component, LinkedIn profile support for registrants, committee settings persistence, and a new backend endpoint to return enriched, access-controlled registrants.

Changes

Cohort / File(s) Summary
Feature Toggle Component (New)
apps/lfx-one/src/app/shared/components/feature-toggle/feature-toggle.component.ts, apps/lfx-one/src/app/shared/components/feature-toggle/feature-toggle.component.html
New lfx-feature-toggle component rendering feature cards bound to a form control; used across meeting-related UIs.
Show Attendees UI & Form Propagation
apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/*, apps/lfx-one/src/app/modules/meetings/components/meeting-card/*, apps/lfx-one/src/app/modules/meetings/meeting-join/*, apps/lfx-one/src/app/modules/meetings/meeting-manage/meeting-manage.component.ts, apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
Adds badges/icons, drawer-based registrants view, view-members button, new form control show_meeting_attendees, data mapping in create/update flows, and onDrawerHide handler.
Meeting Committee Manager (New UI + Logic)
apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/*
New component to select committees, manage voting statuses, aggregate/preview committee members, sync with parent form and emit changes.
Registrants Display & Management UI + Client Filtering
apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-display/*, apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/*, apps/lfx-one/src/app/modules/meetings/components/registrant-card/*, apps/lfx-one/src/app/modules/meetings/components/registrant-form/registrant-form.component.html
Adds search and filters (RSVP/Role/Group), card-style registrant list, conditional past/current flows, integrates committee manager and feature toggle, and adds LinkedIn field in registrant form UI.
Shared MeetingService Enhancements
apps/lfx-one/src/app/shared/services/meeting.service.ts
Adds getMyMeetingRegistrants, includes linkedin_profile in shaping, adds createRegistrantFormGroup with LinkedIn validation.
Backend: my-meeting-registrants endpoint & enrichment
apps/lfx-one/src/server/controllers/meeting.controller.ts, apps/lfx-one/src/server/routes/meetings.route.ts, apps/lfx-one/src/server/services/meeting.service.ts
New GET /meetings/:uid/my-meeting-registrants enforcing access, V1/V2 distinction, and enriching committee registrants with committee metadata.
Committee Service & Settings
apps/lfx-one/src/server/services/committee.service.ts
Parallel fetch of member counts and settings; supports show_meeting_attendees and member_visibility on create/update; ETag-aware settings updates.
Shared interfaces, constants & utils
packages/shared/src/interfaces/meeting.interface.ts, packages/shared/src/interfaces/components.interface.ts, packages/shared/src/constants/meeting.constants.ts, packages/shared/src/constants/validation.constants.ts, packages/shared/src/utils/meeting.utils.ts, packages/shared/src/constants/index.ts
Adds show_meeting_attendees, linkedin_profile, committee metadata fields, FeatureConfig interface, new feature constants (RECURRING/RESTRICTED/SHOW_MEETING_ATTENDEES), MEETING_DURATION_OPTIONS, LINKEDIN_PROFILE_PATTERN, and re-exports.
Avatar & small UI/template adjustments
apps/lfx-one/src/app/shared/components/avatar/*, apps/lfx-one/src/app/modules/committees/components/committee-table/*, apps/lfx-one/src/app/modules/committees/components/member-card/*, various dashboard templates, .vscode/settings.json
Renames customClass()styleClass() usage, swaps committee table to lfx-table, minor presentational spacing/icon changes, avatar input API change, and cSpell additions.
Registrant form / registrant flow refactor
apps/lfx-one/src/app/modules/meetings/components/registrant-card/registrant-card.component.ts, apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/*
Centralizes registrant FormGroup creation via MeetingService, includes linkedin_profile in registrant creation payloads, adjusts visible registrants filtering.
Auth middleware & server auth config
apps/lfx-one/src/server/middleware/auth.middleware.ts, apps/lfx-one/src/server/server.ts
Changes extractBearerToken parameter name/semantics to attemptRefresh, simplifies logging and refresh handling; enables silent login middleware for /meetings routes.

Sequence Diagram(s)

mermaid
sequenceDiagram
autonumber
participant User
participant Frontend as UI
participant API as Meeting API
participant CommitteeSvc as Committee Service
participant ProxyDB as Backend Data/Proxy
Note over Frontend,API: User opens attendees drawer / clicks View Members
User->>Frontend: open attendees drawer
Frontend->>API: GET /meetings/:uid/my-meeting-registrants
API->>API: auth check & verify requester is registrant
alt meeting is V2
API->>ProxyDB: proxy request (type=meeting_registrant)
else meeting is V1
API->>ProxyDB: proxy request (type=v1_meeting_registrant)
end
ProxyDB-->>API: registrant list
API->>CommitteeSvc: fetch committee details & member info (parallel for committee items)
CommitteeSvc-->>API: enriched committee metadata
API-->>Frontend: enriched registrants payload (committee metadata, linkedin_profile, access flags)
Frontend-->>User: render registrants list in drawer

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly summarizes the main change: enhancing meeting registrants and committee management functionality.
Description check ✅ Passed The description comprehensively outlines the changes across multiple modules (meetings, committees, dashboards, shared) and references all related tickets, directly relating to the changeset.
Linked Issues check ✅ Passed The code changes implement requirements from all six linked issues: committee manager component LFXV2-926, feature toggle component [LFXV2-927], registrants display enhancements [LFXV2-928], committee UI updates [LFXV2-929], dashboard/shared components [LFXV2-930], and server API enhancements [LFXV2-931].
Out of Scope Changes check ✅ Passed All changes align with the six linked issues. Minor formatting adjustments to spell-check dictionary and component refactoring are within scope as infrastructure/tooling support for the feature implementation.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/LFXV2-928

📜 Recent review details

Configuration used: Organization 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 c9df83b and f50f160.

📒 Files selected for processing (1)
  • apps/lfx-one/src/server/server.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Always include license headers on all source files - run ./check-headers.sh to verify

Files:

  • apps/lfx-one/src/server/server.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Always use async/await for promises instead of .then() chains in TypeScript services
Use TypeScript interfaces instead of union types for better maintainability

Files:

  • apps/lfx-one/src/server/server.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • apps/lfx-one/src/server/server.ts
apps/lfx-one/src/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Shared package uses direct source imports during development for hot reloading

Files:

  • apps/lfx-one/src/server/server.ts
🔇 Additional comments (2)
apps/lfx-one/src/server/server.ts (2)

147-150: Clarify route pattern scope for silent login middleware.

The middleware is applied to the broad /meetings/ pattern, which will match all routes starting with /meetings/ (e.g., /meetings/create, /meetings/:uid/edit, /meetings/:uid/join, etc.). However, the comment states it's "for meeting join pages only."

Verify that applying silent login to all /meetings/* routes is intentional, or consider a more specific pattern if only meeting join pages should have this behavior.


10-10: No issues identified. The attemptSilentLogin middleware is properly available in express-openid-connect 2.19.2, correctly imported at line 10, and appropriately used at line 150 for optional authentication on meeting join pages. The implementation follows all coding guidelines including license headers and avoids nested ternary expressions.


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

Signed-off-by: Asitha de Silva <asithade@gmail.com>
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 enhances meeting management capabilities by adding comprehensive registrant display features, committee integration, and improved UI components. The changes enable meeting organizers to better manage attendees through search, filtering, and role-based access control while introducing a new feature toggle component for consistent configuration across the application.

Key Changes

  • Meeting Registrants Enhancement: Added search functionality, RSVP filtering (accepted/declined/pending), and role-based filtering with enriched committee member information including LinkedIn profiles
  • Committee Integration: New meeting committee manager component with multi-select dropdown for associating committees with meetings, including voting status filtering
  • Access Control: Implemented /my-meeting-registrants endpoint with access control based on show_meeting_attendees setting, ensuring only invited users can view attendee lists

Reviewed changes

Copilot reviewed 47 out of 47 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
packages/shared/src/interfaces/meeting.interface.ts Added show_meeting_attendees field and committee-related fields for meeting registrants (committee_name, committee_role, committee_category, etc.)
packages/shared/src/interfaces/components.interface.ts Added FeatureConfig interface for the new feature toggle component
packages/shared/src/constants/validation.constants.ts Added LinkedIn profile URL validation pattern
packages/shared/src/constants/meeting.constants.ts Added feature toggle configurations for recurring meetings, restricted meetings, and show attendees
apps/lfx-one/src/server/services/meeting.service.ts Enhanced registrant fetching to support both V1 and V2 meetings with proper type detection
apps/lfx-one/src/server/services/committee.service.ts Added committee settings fetch/update methods with support for new show_meeting_attendees and member_visibility fields
apps/lfx-one/src/server/routes/meetings.route.ts Added new /my-meeting-registrants endpoint for access-controlled registrant viewing
apps/lfx-one/src/server/middleware/auth.middleware.ts Reduced authentication logging verbosity from success to debug level
apps/lfx-one/src/server/controllers/meeting.controller.ts Implemented getMyMeetingRegistrants with access control and enrichCommitteeRegistrants for committee data enrichment
apps/lfx-one/src/app/shared/services/meeting.service.ts Added getMyMeetingRegistrants method and LinkedIn profile validation to registrant forms
apps/lfx-one/src/app/shared/components/header/header.component.ts Fixed profile loading to only fetch when user is authenticated
apps/lfx-one/src/app/shared/components/feature-toggle/* New reusable feature toggle component for consistent feature configuration UI
apps/lfx-one/src/app/shared/components/avatar/avatar.component.ts Cleaned up deprecated customClass property, now uses styleClass consistently
apps/lfx-one/src/app/modules/meetings/meeting-manage/* Added show_meeting_attendees field to meeting form and updated navigation flow after creation
apps/lfx-one/src/app/modules/meetings/meeting-join/* Implemented drawer for registrants display with "Show Members" button for invited users
apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/* New component for selecting committees and managing committee member invitations with voting status filtering
apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/* Integrated committee manager and show attendees toggle, updated to hide committee-type registrants from direct guest list
apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-display/* Added search, RSVP filtering, role filtering, and group filtering with enhanced card-based registrant display
apps/lfx-one/src/app/modules/meetings/components/registrant-form/* Added LinkedIn profile field with validation
apps/lfx-one/src/app/modules/meetings/components/meeting-type-selection/* Refactored to use new feature toggle component
apps/lfx-one/src/app/modules/meetings/components/meeting-details/* Moved recurring meeting toggle to use feature toggle component, reorganized form layout
apps/lfx-one/src/app/modules/meetings/components/meeting-platform-features/* Refactored to use feature toggle component for all platform features
apps/lfx-one/src/app/modules/dashboards/components/* Updated dashboard components with icon improvements and show attendees indicator
apps/lfx-one/src/app/modules/committees/components/committee-table/* Migrated from custom table to lfx-table component with pagination support
apps/lfx-one/src/app/modules/committees/components/member-card/* Simplified avatar property usage
apps/lfx-one/src/app/modules/committees/components/member-form/* Updated to use shared LinkedIn validation pattern

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

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: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
apps/lfx-one/src/app/modules/dashboards/components/my-projects/my-projects.component.html (1)

33-38: Inconsistent header padding.

The "Non-Code Activities" header uses py-2 while all other headers use py-4. This appears to be an oversight that creates uneven vertical padding in the header row.

🔎 Proposed fix
-            <th class="text-left py-2 px-4 text-xs font-medium text-gray-500 w-1/4">
+            <th class="text-left py-4 px-4 text-xs font-medium text-gray-500 w-1/4">
apps/lfx-one/src/server/middleware/auth.middleware.ts (3)

112-134: Critical: Undefined variable isOptionalRoute causes ReferenceError.

The function parameter was renamed from isOptionalRoute to attemptRefresh (line 87), but lines 116, 120, and 127 still reference the old isOptionalRoute variable. This will throw a ReferenceError at runtime whenever token refresh fails.

🔎 Proposed fix

You need to either derive isOptionalRoute from attemptRefresh or use the parameter directly. Based on the intended semantics (lines 94-101), attemptRefresh = false corresponds to optional routes:

         } catch (refreshError) {
           // Different handling based on route type:
           // - Optional routes: Log warning and continue without token (no logout)
           // - Required routes: Log error and force logout to re-authenticate
+          const isOptionalRoute = !attemptRefresh;
           if (isOptionalRoute) {
             logger.warning(req, 'token_extraction', 'Token refresh failed on optional route - continuing without token', {

82-86: Update JSDoc to reflect parameter rename.

The JSDoc comment still references the old parameter name isOptionalRoute, but the parameter was renamed to attemptRefresh on line 87.

🔎 Proposed fix
 /**
  * Extracts bearer token from OIDC session if available
  * @param req - Express request object
- * @param isOptionalRoute - Whether this is an optional auth route (affects logout behavior on refresh failure)
+ * @param attemptRefresh - Whether to attempt token refresh if expired (default true)
  */

365-369: Critical: extractBearerToken has undefined variable references and inverted token refresh logic.

The function parameter is named attemptRefresh, but the implementation references undefined variable isOptionalRoute in the error handler (lines 115-127), which will cause a ReferenceError at runtime. Additionally, the call at line 366 passes isOptionalRoute directly, inverting the intended refresh behavior:

  • For optional routes: isOptionalRoute=trueattemptRefresh=true!attemptRefresh=false → refresh IS attempted (contradicts the skip path at line 95)
  • For required routes: isOptionalRoute=falseattemptRefresh=false!attemptRefresh=true → refresh IS skipped (opposite of intention)

Fix: Either rename the parameter to isOptionalRoute and update the skip condition to if (isOptionalRoute), or pass !isOptionalRoute at the call site and ensure the error handler uses the correct parameter name.

🧹 Nitpick comments (10)
apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.html (1)

7-10: Nice improvement – emoji replaced with Font Awesome icon.

The change from emoji to Font Awesome icon improves visual consistency with other icons in the component.

Consider adding aria-hidden="true" to the icon element for better accessibility, since it's decorative and the adjacent text provides the meaning.

🔎 Optional accessibility enhancement
       <h2>
-        <i class="fa-light fa-chart-line text-lg"></i>
+        <i class="fa-light fa-chart-line text-lg" aria-hidden="true"></i>
         Recent Progress
       </h2>
packages/shared/src/interfaces/components.interface.ts (1)

6-27: Well-documented FeatureConfig interface for the feature toggle component.

The interface provides a clean configuration structure. One minor consideration:

Optional type improvement: The trueValue and falseValue properties use any type. Consider using a generic or a union type for better type safety if the value types are known (e.g., boolean | string).

export interface FeatureConfig<T = boolean> {
  // ...existing fields...
  trueValue?: T;
  falseValue?: T;
}

However, any is acceptable here for maximum configuration flexibility.

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

29-29: Consider refining the LinkedIn profile pattern for robustness.

The current regex has several considerations:

  1. Case sensitivity: The subdomain pattern [a-z]{2,3} only matches lowercase letters, which may reject valid URLs like UK.linkedin.com or mixed-case variations that browsers accept.

  2. Protocol security: The pattern allows http:// which is less secure than https://. Modern LinkedIn always uses HTTPS, so consider enforcing it or at least documenting why HTTP is permitted.

  3. Path validation: The wildcard .*$ is permissive and allows any characters including spaces or special characters. Consider using [^\\s]+ or .+ to prevent empty paths and ensure at least one valid character.

  4. Empty path edge case: The pattern technically matches linkedin.com/ with nothing after the slash due to .* (zero or more). The documentation states "must have content after the domain," but the regex allows zero-length content.

Proposed refinement
-export const LINKEDIN_PROFILE_PATTERN = /^(https?:\/\/)?([a-z]{2,3}\.)?linkedin\.com\/.*$/;
+export const LINKEDIN_PROFILE_PATTERN = /^(https?:\/\/)?([a-zA-Z]{2,3}\.)?linkedin\.com\/.+$/i;

Changes:

  • [a-zA-Z] accepts both cases for subdomains
  • .+ requires at least one character after the domain
  • /i flag for case-insensitive matching (optional, but makes the pattern more forgiving)

Or, if you want to enforce HTTPS:

-export const LINKEDIN_PROFILE_PATTERN = /^(https?:\/\/)?([a-z]{2,3}\.)?linkedin\.com\/.*$/;
+export const LINKEDIN_PROFILE_PATTERN = /^(https:\/\/)?([a-zA-Z]{2,3}\.)?linkedin\.com\/.+$/i;
apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.html (1)

67-75: Consider using a distinct icon to avoid confusion.

The "Show Attendees" feature uses the fa-users icon (line 73), which is identical to the "Public Meeting" icon (line 82). This creates visual ambiguity when both features are enabled, making it difficult for users to distinguish between the two at a glance.

Suggested icon alternatives

Consider using a more distinct icon for "Show Attendees", such as:

  • fa-eye or fa-eye-slash to represent visibility/showing
  • fa-user-group for a slight visual distinction
  • fa-users-viewfinder to emphasize the "view attendees" aspect
  • fa-list-check to represent an attendee list

Example:

-                <i class="fa-light fa-users text-xs text-gray-700"></i>
+                <i class="fa-light fa-eye text-xs text-gray-700"></i>
apps/lfx-one/src/app/modules/meetings/components/registrant-form/registrant-form.component.html (1)

127-138: Consider adding validation error messages for LinkedIn profile field.

The LinkedIn Profile field is correctly structured and follows the pattern of other form fields. However, unlike the email field (lines 92-97), it lacks validation error messages. If the LINKEDIN_PROFILE_PATTERN validation is applied in the TypeScript component, users won't receive feedback when they enter an invalid URL.

Add validation error display
         <lfx-input-text
           size="small"
           [form]="form()"
           control="linkedin_profile"
           label="LinkedIn Profile"
           placeholder="Enter LinkedIn profile URL"
           data-testid="registrant-form-linkedin-profile-input">
         </lfx-input-text>
+        @if (form().get('linkedin_profile')?.errors?.['pattern'] && form().get('linkedin_profile')?.touched && form().get('linkedin_profile')?.dirty) {
+          <p class="text-sm text-red-500">Please enter a valid LinkedIn profile URL</p>
+        }
       </div>
packages/shared/src/constants/meeting.constants.ts (1)

431-489: Well-structured feature toggle configurations with good documentation.

The new constants follow the established patterns and include appropriate JSDoc comments. The color references correctly use lfxColors from the shared constants.

One consideration: MEETING_DURATION_OPTIONS mixes number values with a string value ('custom'). This is intentional for UI handling but consider adding a TypeScript type annotation for clarity.

🔎 Optional: Add explicit type annotation
+interface DurationOption {
+  label: string;
+  value: number | 'custom';
+}
+
-export const MEETING_DURATION_OPTIONS = [
+export const MEETING_DURATION_OPTIONS: DurationOption[] = [
   { label: '15 minutes', value: 15 },
   { label: '30 minutes', value: 30 },
   { label: '60 minutes', value: 60 },
   { label: '90 minutes', value: 90 },
   { label: '120 minutes', value: 120 },
   { label: 'Custom...', value: 'custom' },
 ];
apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/meeting-committee-manager.component.html (1)

95-99: Consider defensive check for committees array access.

Accessing committeeForm.value.committees.length directly could throw if the control value is null/undefined.

🔎 Suggested defensive access
-                  @if (committeeForm.value.committees.length > 1) {
+                  @if (committeeForm.value.committees?.length > 1) {

Apply the same pattern at line 121:

-                  @if (committeeForm.value.committees.length > 1) {
+                  @if (committeeForm.value.committees?.length > 1) {
apps/lfx-one/src/server/services/committee.service.ts (1)

381-391: Consider logging the error details for debugging.

The catch block discards the error details. While returning an empty object is the right fallback, logging the actual error (even at debug level) would help with troubleshooting.

🔎 Optional: Include error details in log
-    } catch {
+    } catch (error) {
       logger.debug(req, 'get_committee_settings', 'Failed to fetch committee settings, returning empty', {
         committee_uid: committeeId,
+        error: error instanceof Error ? error.message : String(error),
       });
       return {};
     }
apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-display/meeting-registrants-display.component.ts (1)

214-257: Consider extracting RSVP status logic to a shared utility.

The RSVP matching logic (lines 232-246) duplicates what likely exists in the template. Consider extracting the status determination to a shared utility function for consistency and reusability.

apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/meeting-committee-manager.component.ts (1)

123-123: Remove empty ngOnInit and OnInit implementation.

The ngOnInit method is empty and can be removed along with the OnInit implementation from the class declaration.

🔎 Proposed fix
-import { Component, computed, DestroyRef, inject, input, InputSignal, OnInit, output, OutputEmitterRef, signal, Signal, WritableSignal } from '@angular/core';
+import { Component, computed, DestroyRef, inject, input, InputSignal, output, OutputEmitterRef, signal, Signal, WritableSignal } from '@angular/core';
...
-export class MeetingCommitteeManagerComponent implements OnInit {
+export class MeetingCommitteeManagerComponent {
...
-  public ngOnInit(): void {}
📜 Review details

Configuration used: Organization 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 9430bb6 and 10934f5.

📒 Files selected for processing (47)
  • .vscode/settings.json
  • apps/lfx-one/src/app/modules/committees/components/committee-table/committee-table.component.html
  • apps/lfx-one/src/app/modules/committees/components/committee-table/committee-table.component.ts
  • apps/lfx-one/src/app/modules/committees/components/member-card/member-card.component.html
  • apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.html
  • apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/my-projects/my-projects.component.html
  • apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-card/meeting-card.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-card/meeting-card.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/meeting-committee-manager.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/meeting-committee-manager.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-details/meeting-details.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-details/meeting-details.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-platform-features/meeting-platform-features.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-platform-features/meeting-platform-features.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-display/meeting-registrants-display.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-display/meeting-registrants-display.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-resources-summary/meeting-resources-summary.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-type-selection/meeting-type-selection.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-type-selection/meeting-type-selection.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/registrant-card/registrant-card.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/registrant-form/registrant-form.component.html
  • apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.html
  • apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-manage/meeting-manage.component.html
  • apps/lfx-one/src/app/modules/meetings/meeting-manage/meeting-manage.component.ts
  • apps/lfx-one/src/app/shared/components/avatar/avatar.component.html
  • apps/lfx-one/src/app/shared/components/avatar/avatar.component.ts
  • apps/lfx-one/src/app/shared/components/feature-toggle/feature-toggle.component.html
  • apps/lfx-one/src/app/shared/components/feature-toggle/feature-toggle.component.ts
  • apps/lfx-one/src/app/shared/components/header/header.component.ts
  • apps/lfx-one/src/app/shared/services/meeting.service.ts
  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • apps/lfx-one/src/server/middleware/auth.middleware.ts
  • apps/lfx-one/src/server/routes/meetings.route.ts
  • apps/lfx-one/src/server/services/committee.service.ts
  • apps/lfx-one/src/server/services/meeting.service.ts
  • packages/shared/src/constants/index.ts
  • packages/shared/src/constants/meeting.constants.ts
  • packages/shared/src/constants/validation.constants.ts
  • packages/shared/src/interfaces/components.interface.ts
  • packages/shared/src/interfaces/meeting.interface.ts
  • packages/shared/src/utils/meeting.utils.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx,js,jsx,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Always include license headers on all source files - run ./check-headers.sh to verify

Files:

  • packages/shared/src/interfaces/components.interface.ts
  • apps/lfx-one/src/app/modules/committees/components/committee-table/committee-table.component.ts
  • packages/shared/src/constants/validation.constants.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-card/meeting-card.component.ts
  • apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.ts
  • packages/shared/src/constants/meeting.constants.ts
  • apps/lfx-one/src/server/services/meeting.service.ts
  • apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.ts
  • apps/lfx-one/src/app/shared/components/feature-toggle/feature-toggle.component.ts
  • apps/lfx-one/src/server/routes/meetings.route.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-details/meeting-details.component.ts
  • packages/shared/src/interfaces/meeting.interface.ts
  • packages/shared/src/constants/index.ts
  • apps/lfx-one/src/app/shared/components/header/header.component.ts
  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-platform-features/meeting-platform-features.component.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts
  • apps/lfx-one/src/server/middleware/auth.middleware.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-display/meeting-registrants-display.component.ts
  • packages/shared/src/utils/meeting.utils.ts
  • apps/lfx-one/src/app/modules/meetings/components/registrant-card/registrant-card.component.ts
  • apps/lfx-one/src/server/services/committee.service.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-type-selection/meeting-type-selection.component.ts
  • apps/lfx-one/src/app/shared/components/avatar/avatar.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-resources-summary/meeting-resources-summary.component.ts
  • apps/lfx-one/src/app/shared/services/meeting.service.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/meeting-committee-manager.component.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-manage/meeting-manage.component.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Always use async/await for promises instead of .then() chains in TypeScript services
Use TypeScript interfaces instead of union types for better maintainability

Files:

  • packages/shared/src/interfaces/components.interface.ts
  • apps/lfx-one/src/app/modules/committees/components/committee-table/committee-table.component.ts
  • packages/shared/src/constants/validation.constants.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-card/meeting-card.component.ts
  • apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.ts
  • packages/shared/src/constants/meeting.constants.ts
  • apps/lfx-one/src/server/services/meeting.service.ts
  • apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.ts
  • apps/lfx-one/src/app/shared/components/feature-toggle/feature-toggle.component.ts
  • apps/lfx-one/src/server/routes/meetings.route.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-details/meeting-details.component.ts
  • packages/shared/src/interfaces/meeting.interface.ts
  • packages/shared/src/constants/index.ts
  • apps/lfx-one/src/app/shared/components/header/header.component.ts
  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-platform-features/meeting-platform-features.component.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts
  • apps/lfx-one/src/server/middleware/auth.middleware.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-display/meeting-registrants-display.component.ts
  • packages/shared/src/utils/meeting.utils.ts
  • apps/lfx-one/src/app/modules/meetings/components/registrant-card/registrant-card.component.ts
  • apps/lfx-one/src/server/services/committee.service.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-type-selection/meeting-type-selection.component.ts
  • apps/lfx-one/src/app/shared/components/avatar/avatar.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-resources-summary/meeting-resources-summary.component.ts
  • apps/lfx-one/src/app/shared/services/meeting.service.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/meeting-committee-manager.component.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-manage/meeting-manage.component.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • packages/shared/src/interfaces/components.interface.ts
  • apps/lfx-one/src/app/modules/committees/components/committee-table/committee-table.component.ts
  • packages/shared/src/constants/validation.constants.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-card/meeting-card.component.ts
  • apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.ts
  • packages/shared/src/constants/meeting.constants.ts
  • apps/lfx-one/src/server/services/meeting.service.ts
  • apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.ts
  • apps/lfx-one/src/app/shared/components/feature-toggle/feature-toggle.component.ts
  • apps/lfx-one/src/server/routes/meetings.route.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-details/meeting-details.component.ts
  • packages/shared/src/interfaces/meeting.interface.ts
  • packages/shared/src/constants/index.ts
  • apps/lfx-one/src/app/shared/components/header/header.component.ts
  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-platform-features/meeting-platform-features.component.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts
  • apps/lfx-one/src/server/middleware/auth.middleware.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-display/meeting-registrants-display.component.ts
  • packages/shared/src/utils/meeting.utils.ts
  • apps/lfx-one/src/app/modules/meetings/components/registrant-card/registrant-card.component.ts
  • apps/lfx-one/src/server/services/committee.service.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-type-selection/meeting-type-selection.component.ts
  • apps/lfx-one/src/app/shared/components/avatar/avatar.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-resources-summary/meeting-resources-summary.component.ts
  • apps/lfx-one/src/app/shared/services/meeting.service.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/meeting-committee-manager.component.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-manage/meeting-manage.component.ts
packages/shared/src/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

All shared types, interfaces, and constants must be centralized in @lfx-one/shared package

Files:

  • packages/shared/src/interfaces/components.interface.ts
  • packages/shared/src/constants/validation.constants.ts
  • packages/shared/src/constants/meeting.constants.ts
  • packages/shared/src/interfaces/meeting.interface.ts
  • packages/shared/src/constants/index.ts
  • packages/shared/src/utils/meeting.utils.ts
apps/lfx-one/src/**/*.component.ts

📄 CodeRabbit inference engine (CLAUDE.md)

apps/lfx-one/src/**/*.component.ts: Use zoneless change detection and signals in Angular 19 components instead of zone.js
Use direct imports for standalone components - no barrel exports

Files:

  • apps/lfx-one/src/app/modules/committees/components/committee-table/committee-table.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-card/meeting-card.component.ts
  • apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.ts
  • apps/lfx-one/src/app/shared/components/feature-toggle/feature-toggle.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-details/meeting-details.component.ts
  • apps/lfx-one/src/app/shared/components/header/header.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-platform-features/meeting-platform-features.component.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-display/meeting-registrants-display.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/registrant-card/registrant-card.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-type-selection/meeting-type-selection.component.ts
  • apps/lfx-one/src/app/shared/components/avatar/avatar.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-resources-summary/meeting-resources-summary.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/meeting-committee-manager.component.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-manage/meeting-manage.component.ts
apps/lfx-one/src/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Shared package uses direct source imports during development for hot reloading

Files:

  • apps/lfx-one/src/app/modules/committees/components/committee-table/committee-table.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-card/meeting-card.component.ts
  • apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.ts
  • apps/lfx-one/src/server/services/meeting.service.ts
  • apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.ts
  • apps/lfx-one/src/app/shared/components/feature-toggle/feature-toggle.component.ts
  • apps/lfx-one/src/server/routes/meetings.route.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-details/meeting-details.component.ts
  • apps/lfx-one/src/app/shared/components/header/header.component.ts
  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-platform-features/meeting-platform-features.component.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts
  • apps/lfx-one/src/server/middleware/auth.middleware.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-display/meeting-registrants-display.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/registrant-card/registrant-card.component.ts
  • apps/lfx-one/src/server/services/committee.service.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-type-selection/meeting-type-selection.component.ts
  • apps/lfx-one/src/app/shared/components/avatar/avatar.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-resources-summary/meeting-resources-summary.component.ts
  • apps/lfx-one/src/app/shared/services/meeting.service.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/meeting-committee-manager.component.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-manage/meeting-manage.component.ts
apps/lfx-one/src/**/*.component.html

📄 CodeRabbit inference engine (CLAUDE.md)

Add data-testid attributes with naming convention [section]-[component]-[element] when creating new components

Files:

  • apps/lfx-one/src/app/modules/meetings/meeting-manage/meeting-manage.component.html
  • apps/lfx-one/src/app/shared/components/feature-toggle/feature-toggle.component.html
  • apps/lfx-one/src/app/modules/committees/components/member-card/member-card.component.html
  • apps/lfx-one/src/app/modules/dashboards/components/my-projects/my-projects.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/meeting-committee-manager.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-platform-features/meeting-platform-features.component.html
  • apps/lfx-one/src/app/modules/meetings/components/registrant-form/registrant-form.component.html
  • apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.html
  • apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-card/meeting-card.component.html
  • apps/lfx-one/src/app/modules/committees/components/committee-table/committee-table.component.html
  • apps/lfx-one/src/app/shared/components/avatar/avatar.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-type-selection/meeting-type-selection.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-display/meeting-registrants-display.component.html
  • apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-details/meeting-details.component.html
🧠 Learnings (1)
📚 Learning: 2025-12-10T23:20:29.281Z
Learnt from: asithade
Repo: linuxfoundation/lfx-v2-ui PR: 206
File: apps/lfx-one/src/app/modules/meetings/components/agenda-template-selector/agenda-template-selector.component.ts:11-15
Timestamp: 2025-12-10T23:20:29.281Z
Learning: For Angular 19+ projects, standalone defaults to true for components, directives, and pipes when not explicitly declared. Therefore, components with an imports array in the Component decorator do not require an explicit standalone: true declaration to be standalone. In reviews, verify that a component without an explicit standalone flag and with an imports array will behave as a standalone component according to Angular 19+ defaults. If you need to enforce explicit standalone behavior for clarity or consistency, you can still add standalone: true, but it is not required by default in Angular 19+. Ensure this guidance is considered when reviewing any component.ts files across the codebase.

Applied to files:

  • apps/lfx-one/src/app/modules/committees/components/committee-table/committee-table.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-card/meeting-card.component.ts
  • apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.ts
  • apps/lfx-one/src/app/shared/components/feature-toggle/feature-toggle.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-details/meeting-details.component.ts
  • apps/lfx-one/src/app/shared/components/header/header.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-platform-features/meeting-platform-features.component.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-display/meeting-registrants-display.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/registrant-card/registrant-card.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-type-selection/meeting-type-selection.component.ts
  • apps/lfx-one/src/app/shared/components/avatar/avatar.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-resources-summary/meeting-resources-summary.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/meeting-committee-manager.component.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-manage/meeting-manage.component.ts
🧬 Code graph analysis (14)
apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.ts (1)
packages/shared/src/constants/validation.constants.ts (1)
  • LINKEDIN_PROFILE_PATTERN (29-29)
packages/shared/src/constants/meeting.constants.ts (1)
packages/shared/src/constants/colors.constants.ts (1)
  • lfxColors (9-106)
apps/lfx-one/src/server/services/meeting.service.ts (4)
packages/shared/src/utils/string.utils.ts (1)
  • isUuid (9-11)
apps/lfx-one/src/server/services/logger.service.ts (1)
  • logger (485-485)
packages/shared/src/interfaces/api.interface.ts (1)
  • QueryServiceResponse (58-63)
packages/shared/src/interfaces/meeting.interface.ts (1)
  • MeetingRegistrant (523-578)
apps/lfx-one/src/app/shared/components/feature-toggle/feature-toggle.component.ts (1)
packages/shared/src/interfaces/components.interface.ts (1)
  • FeatureConfig (10-27)
apps/lfx-one/src/app/modules/meetings/components/meeting-details/meeting-details.component.ts (1)
packages/shared/src/constants/meeting.constants.ts (2)
  • MEETING_DURATION_OPTIONS (482-489)
  • RECURRING_MEETING_FEATURE (439-446)
apps/lfx-one/src/server/controllers/meeting.controller.ts (5)
apps/lfx-one/src/server/services/meeting.service.ts (1)
  • MeetingService (38-974)
apps/lfx-one/src/server/services/committee.service.ts (1)
  • CommitteeService (25-429)
packages/shared/src/utils/string.utils.ts (1)
  • isUuid (9-11)
apps/lfx-one/src/server/helpers/validation.helper.ts (1)
  • validateUidParameter (30-49)
apps/lfx-one/src/server/utils/m2m-token.util.ts (1)
  • generateM2MToken (16-108)
apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts (2)
packages/shared/src/interfaces/meeting.interface.ts (2)
  • RegistrantPendingChanges (677-684)
  • MeetingRegistrantWithState (645-654)
packages/shared/src/constants/meeting.constants.ts (1)
  • SHOW_MEETING_ATTENDEES_FEATURE (465-472)
apps/lfx-one/src/server/middleware/auth.middleware.ts (2)
packages/shared/src/interfaces/auth.interface.ts (1)
  • TokenExtractionResult (139-144)
apps/lfx-one/src/server/services/logger.service.ts (1)
  • logger (485-485)
apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-display/meeting-registrants-display.component.ts (2)
apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts (1)
  • Component (25-353)
apps/lfx-one/src/app/modules/meetings/components/registrant-card/registrant-card.component.ts (1)
  • Component (14-90)
apps/lfx-one/src/server/services/committee.service.ts (2)
packages/shared/src/interfaces/committee.interface.ts (3)
  • CommitteeCreateData (68-101)
  • Committee (10-62)
  • CommitteeSettingsData (113-122)
apps/lfx-one/src/server/services/logger.service.ts (2)
  • logger (485-485)
  • etag (289-324)
apps/lfx-one/src/app/modules/meetings/components/meeting-type-selection/meeting-type-selection.component.ts (1)
packages/shared/src/constants/meeting.constants.ts (1)
  • RESTRICTED_MEETING_FEATURE (452-459)
apps/lfx-one/src/app/shared/components/avatar/avatar.component.ts (1)
packages/shared/src/interfaces/components.interface.ts (1)
  • AvatarProps (257-274)
apps/lfx-one/src/app/shared/services/meeting.service.ts (2)
packages/shared/src/interfaces/meeting.interface.ts (1)
  • MeetingRegistrant (523-578)
packages/shared/src/constants/validation.constants.ts (1)
  • LINKEDIN_PROFILE_PATTERN (29-29)
apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/meeting-committee-manager.component.ts (3)
packages/shared/src/interfaces/meeting.interface.ts (1)
  • MeetingCommittee (300-307)
packages/shared/src/interfaces/committee.interface.ts (1)
  • Committee (10-62)
packages/shared/src/constants/committees.constants.ts (2)
  • VOTING_STATUSES (231-237)
  • COMMITTEE_LABEL (17-20)

- Use case-insensitive email comparison for member deduplication
- Add explicit null check for voting status filtering
- Fix token restoration when original token was undefined
- Reduce auth middleware log verbosity (success → debug)

LFXV2-928

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

Signed-off-by: Asitha de Silva <asithade@gmail.com>
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

♻️ Duplicate comments (4)
apps/lfx-one/src/server/controllers/meeting.controller.ts (4)

439-444: Avoid spreading entire meeting object into logs.

Spreading the full meeting object into debug logs could inadvertently log sensitive data. Log only the necessary fields.


460-464: Consider redacting user email in debug logs for privacy.

Logging the raw email address may raise privacy/compliance concerns. Consider logging only has_email or a redacted version.


529-533: Token restoration may leave stale token when original was undefined.

The restoration logic should use delete req.bearerToken when the original token was undefined to avoid leaving the M2M token in place.


1524-1607: Error handling continues on partial failures without client indication.

The method catches errors when fetching committee details or members and logs warnings but continues processing. This could result in incomplete data being returned without any indication that some data is missing.

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

476-533: Consider using try-finally for token restoration.

The current token restoration logic works correctly, but using a try-finally block would more explicitly guarantee cleanup even if errors occur during registrant fetching or enrichment. This is a defensive programming best practice.

🔎 Proposed refactor using try-finally
       // Save original token and setup M2M token for privileged access
       const originalToken = req.bearerToken;
-      const m2mToken = await generateM2MToken(req);
-      req.bearerToken = m2mToken;
-
-      // Use tags_all to filter by both meeting_uid and email
-      logger.debug(req, 'get_my_meeting_registrants', 'Checking if user is a registrant', {
-        meeting_uid: uid,
-        user_email: userEmail,
-      });
-      const userRegistrantCheck = await this.meetingService.getMeetingRegistrantsByEmail(req, uid, userEmail);
-
-      logger.debug(req, 'get_my_meeting_registrants', 'User registrant check complete', {
-        meeting_uid: uid,
-        user_email: userEmail,
-        registrant_count: userRegistrantCheck.resources?.length || 0,
-      });
-
-      // Step 6: If user is not a registrant, return empty array
-      if (!userRegistrantCheck.resources || userRegistrantCheck.resources.length === 0) {
-        logger.success(req, 'get_my_meeting_registrants', startTime, {
+      try {
+        const m2mToken = await generateM2MToken(req);
+        req.bearerToken = m2mToken;
+
+        // Use tags_all to filter by both meeting_uid and email
+        logger.debug(req, 'get_my_meeting_registrants', 'Checking if user is a registrant', {
           meeting_uid: uid,
           user_email: userEmail,
-          is_registrant: false,
-          registrant_count: 0,
         });
-        res.json([]);
-        return;
-      }
-
-      // Step 7: User is a registrant, fetch all registrants using M2M token
-      logger.debug(req, 'get_my_meeting_registrants', 'User is a registrant, setting up M2M token', {
-        meeting_uid: uid,
-        user_email: userEmail,
-        include_rsvp: includeRsvp,
-      });
-
-      logger.debug(req, 'get_my_meeting_registrants', 'M2M token generated, fetching all registrants', {
-        meeting_uid: uid,
-        has_m2m_token: !!m2mToken,
-      });
-
-      const registrants = await this.meetingService.getMeetingRegistrants(req, uid, includeRsvp);
-
-      logger.debug(req, 'get_my_meeting_registrants', 'Fetched all registrants, enriching committee data', {
-        meeting_uid: uid,
-        registrant_count: registrants.length,
-      });
-
-      // Enrich committee registrant data with committee details and member info
-      const enrichedRegistrants = await this.enrichCommitteeRegistrants(req, registrants);
-
-      // Restore original token (delete if it was undefined to avoid leaving M2M token)
+        const userRegistrantCheck = await this.meetingService.getMeetingRegistrantsByEmail(req, uid, userEmail);
+
+        logger.debug(req, 'get_my_meeting_registrants', 'User registrant check complete', {
+          meeting_uid: uid,
+          user_email: userEmail,
+          registrant_count: userRegistrantCheck.resources?.length || 0,
+        });
+
+        // Step 6: If user is not a registrant, return empty array
+        if (!userRegistrantCheck.resources || userRegistrantCheck.resources.length === 0) {
+          logger.success(req, 'get_my_meeting_registrants', startTime, {
+            meeting_uid: uid,
+            user_email: userEmail,
+            is_registrant: false,
+            registrant_count: 0,
+          });
+          res.json([]);
+          return;
+        }
+
+        // Step 7: User is a registrant, fetch all registrants using M2M token
+        logger.debug(req, 'get_my_meeting_registrants', 'User is a registrant, setting up M2M token', {
+          meeting_uid: uid,
+          user_email: userEmail,
+          include_rsvp: includeRsvp,
+        });
+
+        logger.debug(req, 'get_my_meeting_registrants', 'M2M token generated, fetching all registrants', {
+          meeting_uid: uid,
+          has_m2m_token: !!m2mToken,
+        });
+
+        const registrants = await this.meetingService.getMeetingRegistrants(req, uid, includeRsvp);
+
+        logger.debug(req, 'get_my_meeting_registrants', 'Fetched all registrants, enriching committee data', {
+          meeting_uid: uid,
+          registrant_count: registrants.length,
+        });
+
+        // Enrich committee registrant data with committee details and member info
+        const enrichedRegistrants = await this.enrichCommitteeRegistrants(req, registrants);
+
+        logger.success(req, 'get_my_meeting_registrants', startTime, {
+          meeting_uid: uid,
+          user_email: userEmail,
+          is_registrant: true,
+          registrant_count: enrichedRegistrants.length,
+          include_rsvp: includeRsvp,
+        });
+
+        // Send the registrants data to the client
+        res.json(enrichedRegistrants);
+      } finally {
+        // Restore original token (delete if it was undefined to avoid leaving M2M token)
-      if (originalToken !== undefined) {
-        req.bearerToken = originalToken;
-      } else {
-        delete req.bearerToken;
+        if (originalToken !== undefined) {
+          req.bearerToken = originalToken;
+        } else {
+          delete req.bearerToken;
+        }
       }
-
-      logger.success(req, 'get_my_meeting_registrants', startTime, {
-        meeting_uid: uid,
-        user_email: userEmail,
-        is_registrant: true,
-        registrant_count: enrichedRegistrants.length,
-        include_rsvp: includeRsvp,
-      });
-
-      // Send the registrants data to the client
-      res.json(enrichedRegistrants);
     } catch (error) {
📜 Review details

Configuration used: Organization 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 10934f5 and c9df83b.

📒 Files selected for processing (5)
  • apps/lfx-one/src/app/modules/committees/components/committee-table/committee-table.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/meeting-committee-manager.component.ts
  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • apps/lfx-one/src/server/middleware/auth.middleware.ts
  • apps/lfx-one/src/server/server.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/lfx-one/src/app/modules/meetings/components/meeting-committee-manager/meeting-committee-manager.component.ts
  • apps/lfx-one/src/app/modules/committees/components/committee-table/committee-table.component.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Always include license headers on all source files - run ./check-headers.sh to verify

Files:

  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • apps/lfx-one/src/server/server.ts
  • apps/lfx-one/src/server/middleware/auth.middleware.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Always use async/await for promises instead of .then() chains in TypeScript services
Use TypeScript interfaces instead of union types for better maintainability

Files:

  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • apps/lfx-one/src/server/server.ts
  • apps/lfx-one/src/server/middleware/auth.middleware.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • apps/lfx-one/src/server/server.ts
  • apps/lfx-one/src/server/middleware/auth.middleware.ts
apps/lfx-one/src/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Shared package uses direct source imports during development for hot reloading

Files:

  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • apps/lfx-one/src/server/server.ts
  • apps/lfx-one/src/server/middleware/auth.middleware.ts
🧬 Code graph analysis (1)
apps/lfx-one/src/server/controllers/meeting.controller.ts (5)
packages/shared/src/utils/string.utils.ts (1)
  • isUuid (9-11)
apps/lfx-one/src/server/helpers/validation.helper.ts (1)
  • validateUidParameter (30-49)
apps/lfx-one/src/server/utils/m2m-token.util.ts (1)
  • generateM2MToken (16-108)
packages/shared/src/interfaces/meeting.interface.ts (1)
  • MeetingRegistrant (523-578)
packages/shared/src/interfaces/committee.interface.ts (1)
  • Committee (10-62)
🔇 Additional comments (3)
apps/lfx-one/src/server/controllers/meeting.controller.ts (1)

1593-1594: LGTM: Case-insensitive email comparison.

Using case-insensitive email comparison when matching committee members to registrants is the correct approach, as email addresses are case-insensitive per RFC 5321.

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

130-130: LGTM: Silent login enabled.

Enabling attemptSilentLogin allows the application to attempt authentication without user interaction when possible, improving the user experience. This aligns with the PR objectives to enhance the authentication flow.

apps/lfx-one/src/server/middleware/auth.middleware.ts (1)

88-88: LGTM: Logging improvements.

The logging changes simplify the authentication flow logging by:

  • Using Date.now() directly instead of logger.startOperation for consistency
  • Changing routine token operations from success-level to debug-level logs to reduce noise
  • Clarifying log messages for better readability

These changes improve observability without altering authentication behavior.

Also applies to: 100-100, 131-131, 144-147, 332-332, 378-383

Add attemptSilentLogin middleware specifically for /meetings/ routes
to enable SSO session detection from other LFX applications. This
allows users who are already logged into another LFX app to be
automatically authenticated when accessing meeting join pages.

LFXV2-928

Signed-off-by: Asitha de Silva <asithade@gmail.com>
@asithade asithade merged commit a41caad into main Dec 23, 2025
6 checks passed
@asithade asithade deleted the feat/LFXV2-928 branch December 23, 2025 18:01
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