Skip to content

feat(meetings): improve meeting join and registration filtering#198

Merged
asithade merged 2 commits intomainfrom
feat/LFXV2-885
Dec 5, 2025
Merged

feat(meetings): improve meeting join and registration filtering#198
asithade merged 2 commits intomainfrom
feat/LFXV2-885

Conversation

@asithade
Copy link
Contributor

@asithade asithade commented Dec 5, 2025

Summary

  • Allow authenticated users to join restricted meetings with an alternate email address (LFXV2-885)
  • Filter all meetings by registration status for the "my meetings" view (LFXV2-886)

Changes

LFXV2-885: Allow authenticated users to join with alternate email

  • Extract guest form into reusable component (guest-form/)
  • Add error handling for restricted meeting email validation
  • Allow authenticated users to enter alternate email when their SSO email is not registered
  • Prioritize form-submitted email over OIDC user email in backend

LFXV2-886: Filter meetings by registration for my meetings view

  • Filter ALL meetings (public and private) by registration status
  • Writers have API access to all meetings for management, but "my meetings" only shows meetings they're registered for
  • Extract filterMeetingsByRegistration helper method for code reuse

🤖 Generated with Claude Code

LFXV2-885

- Extract guest form into reusable component
- Add error handling for restricted meeting email validation
- Allow authenticated users to enter alternate email when their SSO email is not registered
- Prioritize form-submitted email over OIDC user email in backend

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

Signed-off-by: Asitha de Silva <asithade@gmail.com>
LFXV2-886

- Filter ALL meetings (public and private) by registration status
- Writers have API access to all meetings, but my meetings shows only registered
- Extract filterMeetingsByRegistration helper method for code reuse
- Simplify getUserMeetings by removing writer-specific logic

🤖 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 5, 2025 18:17
Copilot AI review requested due to automatic review settings December 5, 2025 18:17
@coderabbitai
Copy link

coderabbitai bot commented Dec 5, 2025

Walkthrough

This PR introduces a guest form component for meeting join flows and refactors authentication/authorization paths. It removes the fallback join button from the dashboard, adds a new guest form component, revamps meeting join logic to support guest workflows, adjusts email handling priority, and refactors user service meeting filtering by registration status.

Changes

Cohort / File(s) Summary
Guest Form Component
apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.ts, guest-form.component.html
New standalone component for guest form with form controls (Full Name, Email, Organization), conditional submit button bound to joinUrl(), and form validation wiring. Exports public properties for form, joinUrl, loading state, button visibility, and label customization.
Meeting Join Component (UI)
apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.html
Reworked join/RSVP logic with conditional rendering for direct join, error states, and guest form sections. Replaces inline guest form markup with dedicated lfx-guest-form component. Adds error messaging blocks and OR divider for guest form flow.
Meeting Join Component (Logic)
apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
Added guest form workflow with showGuestForm signal, email error handling via initializeEmailError(), and user flow adjustments. Modified auto-join eligibility to skip when guest form active. Changed email form initialization from pre-filled user email to empty. Added onEmailErrorClick() to toggle guest form display.
Dashboard Component
apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.html
Removed else branch providing fallback Join Meeting button with router navigation when direct joinUrl unavailable. Eliminates fallback path; no Join button rendered if joinUrl not available.
Backend Email & Meeting Filtering
apps/lfx-one/src/server/controllers/public-meeting.controller.ts, apps/lfx-one/src/server/services/user.service.ts
Changed email source priority in join URL controller to default to body email before OIDC email. Refactored getUserMeetings to filter all accessible meetings by registration status via new filterMeetingsByRegistration() helper instead of splitting public/private paths.

Sequence Diagrams

sequenceDiagram
    participant User as Guest User
    participant UI as Meeting Join UI
    participant GuestForm as Guest Form Component
    participant Backend as Backend Service
    participant Auth as Join URL Service
    
    User->>UI: Attempts to join meeting (no auth)
    activate UI
    UI->>UI: showGuestForm = true
    UI->>GuestForm: Render guest form
    deactivate UI
    
    User->>GuestForm: Enter name, email, organization
    GuestForm->>GuestForm: Validate form
    
    User->>GuestForm: Click "Join Meeting"
    activate GuestForm
    GuestForm->>Backend: Submit guest info + email
    deactivate GuestForm
    
    activate Backend
    Backend->>Auth: Fetch join URL (guest email source)
    activate Auth
    Auth->>Auth: Check email registration (M2M API)
    Note over Auth: Filters meetings by<br/>registration status
    Auth-->>Backend: Return join URL or error
    deactivate Auth
    
    alt Join URL Available
        Backend-->>GuestForm: joinUrl
        GuestForm->>GuestForm: Open URL in new tab
        GuestForm-->>User: Redirect to meeting
    else Email Not Registered
        Backend-->>UI: joinUrlError (email error)
        UI->>UI: emailError signal = true
        UI->>User: Show error + email action link
        User->>UI: Click email error action
        UI->>GuestForm: Reset and show form again
    end
    deactivate Backend
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • meeting-join.component.ts: Significant logic changes including signal wiring, auto-join flow modifications, and email source reprioritization; requires understanding of new guest form control flow interactions
  • user.service.ts: Refactored meeting filtering logic introducing new private helper with M2M API calls for registration checks; complexity in async filtering logic and error handling paths
  • meeting-join.component.html: Substantial template restructuring with multiple conditional branches and new component integration; verify all conditions and bindings are correctly wired
  • public-meeting.controller.ts: Email source priority inversion may impact existing authenticated flows; verify fallback behavior and error cases

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(meetings): improve meeting join and registration filtering' clearly and concisely summarizes the main changes: adding guest form functionality for alternate email joins (LFXV2-885) and filtering meetings by registration (LFXV2-886).
Description check ✅ Passed The description accurately describes the changeset, covering both linked issues (LFXV2-885 and LFXV2-886), specific changes made, and implementation details aligned with the PR objectives.
Linked Issues check ✅ Passed The PR fully addresses both linked issues: LFXV2-885 implements guest form component with email error handling and alternate email submission; LFXV2-886 introduces filterMeetingsByRegistration helper to filter all meetings by registration status.
Out of Scope Changes check ✅ Passed All changes are within scope of the two linked issues. Minor refactoring in dashboard-meeting-card component (removing else branch) is directly related to the overall join flow improvements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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-885

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

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

🧹 Nitpick comments (4)
apps/lfx-one/src/server/services/user.service.ts (1)

560-608: Consider consolidating the v parameter.

The query object sets v: 1 (number) on line 564, but DEFAULT_QUERY_PARAMS defines v: '1' (string). Since DEFAULT_QUERY_PARAMS is spread afterward, the string version will override the number, but this creates redundancy. Remove the explicit v: 1 since DEFAULT_QUERY_PARAMS already provides it.

         const query = {
-          v: 1,
           type: 'meeting_registrant',
           parent: `meeting:${meeting.uid}`,
           tags_all: [`email:${email}`],
           ...DEFAULT_QUERY_PARAMS,
         };
apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.ts (1)

1-3: Add Claude Code attribution comment.

Per the PR description, this code was generated with Claude Code. As per coding guidelines, prepend the attribution comment.

 // Copyright The Linux Foundation and each contributor to LFX.
 // SPDX-License-Identifier: MIT
+// Generated with Claude Code (https://claude.ai/code)
apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts (2)

571-576: Consider using an error code instead of string matching.

Matching error messages by string content is fragile—if the backend message changes, this detection will silently fail. Consider having the backend return a structured error with a stable error code (e.g., EMAIL_NOT_REGISTERED) that you can check reliably.

If the error format cannot be changed, at minimum extract the expected message to a constant to avoid duplication and make updates easier:

+const EMAIL_NOT_REGISTERED_ERROR = 'email address is not registered for this restricted meeting';
+
 private initializeEmailError(): Signal<boolean> {
   return computed(() => {
-    return this.joinUrlError()?.toLowerCase().includes('email address is not registered for this restricted meeting') ?? false;
+    return this.joinUrlError()?.toLowerCase().includes(EMAIL_NOT_REGISTERED_ERROR) ?? false;
   });
 }

1-3: Add Claude Code attribution per coding guidelines.

Per the coding guidelines, files assisted with Claude Code should include an attribution comment. Since the PR description notes this was generated with Claude Code, consider adding:

 // Copyright The Linux Foundation and each contributor to LFX.
 // SPDX-License-Identifier: MIT
+// Generated with Claude Code (https://claude.ai/code)

Based on coding guidelines.

📜 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 1256a26 and 8d30ddd.

📒 Files selected for processing (7)
  • apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.html (0 hunks)
  • apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.html (1 hunks)
  • apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.ts (1 hunks)
  • apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.html (3 hunks)
  • apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts (9 hunks)
  • apps/lfx-one/src/server/controllers/public-meeting.controller.ts (1 hunks)
  • apps/lfx-one/src/server/services/user.service.ts (4 hunks)
💤 Files with no reviewable changes (1)
  • apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.html
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Always use direct imports for standalone components - no barrel exports
Use TypeScript interfaces instead of union types for better maintainability
Do not nest ternary expressions
Prefer interface for defining object shapes in TypeScript
Use path mappings and import aliases as configured in tsconfig.json for imports

Files:

  • apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.ts
  • apps/lfx-one/src/server/controllers/public-meeting.controller.ts
  • apps/lfx-one/src/server/services/user.service.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
**/*.{html,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always add data-testid attributes when creating new components for reliable test targeting

Files:

  • apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.ts
  • apps/lfx-one/src/server/controllers/public-meeting.controller.ts
  • apps/lfx-one/src/server/services/user.service.ts
  • apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-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
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: License headers are required on all source files
Prepend 'Generated with Claude Code (https://claude.ai/code)' if assisted with the code

Files:

  • apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.ts
  • apps/lfx-one/src/server/controllers/public-meeting.controller.ts
  • apps/lfx-one/src/server/services/user.service.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
**/*.component.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use Angular 19 zoneless change detection with signals for component state management

Files:

  • apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.ts
  • apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
apps/**/**/server/**/*.{ts,js}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/**/**/server/**/*.{ts,js}: Use Pino for structured JSON logs with sensitive data redaction in all backend services
Always use err field for errors to leverage Pino's error serializer - correct: req.log.error({ err: error, ...metadata }, 'message')
Log INFO level for business operation completions (created, updated, deleted) and successful data retrieval
Log WARN level for error conditions leading to exceptions and data quality issues
Log DEBUG level for internal operations, preparation steps, and intent statements
Log ERROR level for system failures, unhandled exceptions, and critical errors

Files:

  • apps/lfx-one/src/server/controllers/public-meeting.controller.ts
  • apps/lfx-one/src/server/services/user.service.ts
apps/**/**/server/**/*controller*.{ts,js}

📄 CodeRabbit inference engine (CLAUDE.md)

All controller functions must use Logger helper methods: Logger.start(), Logger.success(), Logger.error(), Logger.warning(), Logger.validation()

Files:

  • apps/lfx-one/src/server/controllers/public-meeting.controller.ts
**/*.html

📄 CodeRabbit inference engine (CLAUDE.md)

Use data-testid naming convention - [section]-[component]-[element] for hierarchical structure

Files:

  • apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.html
  • apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.html
🧬 Code graph analysis (2)
apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.ts (1)
apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts (1)
  • Component (46-577)
apps/lfx-one/src/server/services/user.service.ts (5)
packages/shared/src/interfaces/meeting.interface.ts (2)
  • Meeting (90-210)
  • MeetingRegistrant (337-380)
apps/lfx-one/src/server/utils/m2m-token.util.ts (1)
  • generateM2MToken (16-110)
packages/shared/src/constants/api.constants.ts (1)
  • DEFAULT_QUERY_PARAMS (12-15)
packages/shared/src/interfaces/api.interface.ts (1)
  • QueryServiceResponse (58-63)
apps/lfx-one/src/server/helpers/logger.ts (1)
  • error (52-65)
⏰ 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: Agent
🔇 Additional comments (14)
apps/lfx-one/src/server/controllers/public-meeting.controller.ts (1)

187-187: Email source priority change looks correct.

The change correctly prioritizes form-submitted email over the OIDC user email, aligning with the guest form feature that allows authenticated users to join with an alternate email address.

apps/lfx-one/src/server/services/user.service.ts (2)

488-549: Refactored filtering logic looks good.

The method now correctly filters all meetings by registration status, ensuring "my meetings" only shows meetings the user is registered for. The M2M token is generated once and reused for all registration checks.


571-576: V1 meeting handling logic is correct.

The conditional correctly handles legacy v1 meetings by switching to the appropriate registrant type and tag format.

apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.ts (1)

16-23: Component implementation follows Angular 19 patterns.

The component correctly uses Angular's new input() signal API for reactive inputs, aligning with zoneless change detection guidelines. The required/optional input pattern is well-structured.

apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.html (1)

1-72: Template follows best practices with proper test IDs and security attributes.

The template correctly uses data-testid attributes following the naming convention, and the external link button properly includes rel="noopener noreferrer" for security.

apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.html (3)

114-148: Join button conditional logic correctly handles guest form state.

The implementation properly shows the join button only when a URL is available and the guest form is not active, with appropriate error handling for restricted meeting email issues.


299-299: Verify form input binding syntax.

The guest form component expects a FormGroup via input.required<FormGroup>(). Here, joinForm is passed directly without invoking it as a signal. Looking at the parent component, joinForm is declared as FormGroup (not a signal), so this binding is correct.


337-342: Guest form integration for unauthenticated users is consistent.

The guest form and error handling mirror the authenticated flow, providing a consistent user experience.

apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts (6)

37-43: LGTM on imports.

The new imports for GuestFormComponent and DialogService/DynamicDialogModule are correctly structured using direct imports (no barrel exports) as per coding guidelines.


108-110: LGTM on signal declarations.

Using WritableSignal for showGuestForm (mutable state) and Signal for emailError (computed/derived) correctly follows Angular 19 signal patterns for zoneless change detection.


183-186: LGTM on onEmailErrorClick.

The method correctly clears the error state before showing the guest form, providing a clean UX when the user opts to enter an alternate email.


220-228: LGTM on auto-join logic.

Correctly prevents automatic join when the user is entering an alternate email via guest form. The comment at line 220 clearly documents this intentional behavior.


304-310: LGTM on empty email initialization.

Defaulting the email field to empty is correct for the guest form workflow. Authenticated users with matching emails auto-join (bypassing the form), while those using the guest form need to enter their alternate email.


423-445: LGTM on authenticated path condition.

Adding !this.showGuestForm() correctly allows authenticated users to fall through to the form-based email path when using an alternate email. This implements the requirement to prioritize form-submitted email over the OIDC email.

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 pull request enhances meeting join functionality for authenticated users and refines the "my meetings" view to show only meetings where users are registered.

Key Changes:

  • Allows authenticated users to join restricted meetings using an alternate email address when their SSO email is not registered
  • Updates meeting filtering to show only registered meetings in "my meetings" view for all users, including writers
  • Extracts guest form into a reusable component for better code organization

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
apps/lfx-one/src/server/services/user.service.ts Refactored getUserMeetings to filter ALL meetings by registration status (not just public ones), extracted filterMeetingsByRegistration helper method, and removed unused MeetingVisibility import
apps/lfx-one/src/server/controllers/public-meeting.controller.ts Changed email priority to use form-submitted email before OIDC user email, enabling authenticated users to specify alternate emails
apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts Added guest form display logic for authenticated users, email error detection, and updated form initialization to not pre-fill email for authenticated users
apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.html Added UI for error handling with alternate email option, integrated guest form for both authenticated and unauthenticated users
apps/lfx-one/src/app/modules/meetings/components/guest-form/ New reusable guest form component for email, name, and organization input with configurable submit button
apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.html Removed fallback join button that redirected to join page when no direct join URL was available

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

@asithade asithade merged commit 519dc3a into main Dec 5, 2025
11 checks passed
@asithade asithade deleted the feat/LFXV2-885 branch December 5, 2025 18:24
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