Skip to content

Conversation

@asithade
Copy link
Contributor

@asithade asithade commented Nov 19, 2025

Summary

Refactored pending actions component to accept data via input signals and integrated backend API for querying pending survey responses from Snowflake analytics database.

Frontend Changes

  • Converted pending actions component from computed signal with PersonaService to required input signal
  • Updated all dashboards (core-developer, maintainer, board-member) to pass pending actions as inputs
  • Implemented reactive data fetching with toSignal pattern for board member dashboard survey actions
  • Added support for clickable button links in pending actions
  • Added empty state display matching my-meetings component pattern

Backend Changes

  • Added GET /api/projects/pending-action-surveys endpoint
  • Implemented Snowflake query for MEMBER_DASHBOARD_PENDING_ACTION_SURVEYS table
  • Added data transformation from survey rows to PendingActionItem format
  • Query filters: survey_cutoff_date > CURRENT_DATE(), response_type = 'non_response', committee_category = 'Board'
  • Uses parameterized queries with email (from OIDC) and projectSlug (from query params)

Interfaces

  • Added PendingSurveyRow interface for Snowflake query results
  • Updated PendingActionItem to include optional buttonLink field

JIRA: LFXV2-764

Signed-off-by: Asitha de Silva <[email protected]>
- Convert pending actions component to use required input signal
- Remove PersonaService dependency for cleaner architecture
- Update all dashboards (core-developer, maintainer, board-member) to pass actions as inputs
- Add backend endpoint GET /api/projects/pending-action-surveys
- Implement Snowflake query for pending survey responses
- Add data transformation from survey rows to PendingActionItem format
- Support clickable survey links with buttonLink property
- Add empty state display when no pending actions available
- Use toSignal pattern for reactive data fetching in board member dashboard

Signed-off-by: Asitha de Silva <[email protected]>
@asithade asithade requested a review from jordane as a code owner November 19, 2025 06:43
Copilot AI review requested due to automatic review settings November 19, 2025 06:43
@github-actions github-actions bot requested a review from andrest50 November 19, 2025 06:44
@coderabbitai
Copy link

coderabbitai bot commented Nov 19, 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 end-to-end pending‑action surveys: server route and service to fetch pending surveys, client ProjectService call, new signals/inputs on dashboards to bind pending actions, refactors PendingActionsComponent to accept a required input, and several UI/template adjustments.

Changes

Cohort / File(s) Summary
Pending Actions Component Refactor
apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.html, apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.ts
Converted persona/computed-based logic to a required pendingActions input; removed viewAll output and PersonaService; updated template for empty state, per-item link vs click button, and styling adjustments.
Board Member Dashboard
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.html, apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts
Added selectedProject computed signal and boardMemberActions signal initialized via ProjectService.getPendingActionSurveys (signals↔observable pipeline with catch/fallback). Template now binds [pendingActions]="boardMemberActions()".
Core Developer & Maintainer Dashboards
apps/lfx-one/src/app/modules/dashboards/core-developer/..., apps/lfx-one/src/app/modules/dashboards/maintainer/...
Introduced coreDevActions and maintainerActions signals (initialized from constants) and bound them to lfx-pending-actions via [pendingActions].
Client ProjectService
apps/lfx-one/src/app/shared/services/project.service.ts
Added getPendingActionSurveys(projectSlug: string): Observable<PendingActionItem[]> calling backend /api/projects/pending-action-surveys with error handling returning an empty array.
Server Project Service
apps/lfx-one/src/server/services/project.service.ts
New getPendingActionSurveys(email: string, projectSlug: string): Promise<PendingActionItem[]> executing a Snowflake query and mapping rows to PendingActionItem objects (including formatted due dates and buttonLink).
Server Controller & Route
apps/lfx-one/src/server/controllers/project.controller.ts, apps/lfx-one/src/server/routes/projects.route.ts
Added GET /pending-action-surveys route and controller handler validating user email and projectSlug, delegating to service and returning items. Note: controller file contains a duplicated getPendingActionSurveys method declaration.
Shared Interfaces
packages/shared/src/interfaces/components.interface.ts, packages/shared/src/interfaces/project.interface.ts
Added optional buttonLink?: string to PendingActionItem; added new PendingSurveyRow interface describing DB row fields.
UI/UX & Misc
apps/lfx-one/src/app/shared/components/meeting-rsvp-details/meeting-rsvp-details.component.html, apps/lfx-one/src/app/shared/components/meeting-card/meeting-card.component.ts, apps/lfx-one/src/app/shared/components/header/header.component.ts, apps/lfx-one/angular.json
Reworked RSVP progress bars (past vs upcoming), changed SummaryModal to non-modal/non-closable in MeetingCard, removed AutocompleteComponent and PersonaSelectorComponent from header imports, and expanded allowedCommonJsDependencies + adjusted build budget warnings in angular.json.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Dashboard as BoardMemberDashboard
    participant ClientService as ProjectService (client)
    participant API as Projects API
    participant ServerService as ProjectService (server)
    participant DB as Database

    User->>Dashboard: open dashboard / select project
    Dashboard->>Dashboard: update selectedProject signal
    Dashboard->>ClientService: request pending actions (projectSlug)
    ClientService->>API: GET /api/projects/pending-action-surveys?projectSlug=X
    API->>ServerService: projectController.getPendingActionSurveys(req)
    ServerService->>DB: query pending surveys for user+project
    DB-->>ServerService: rows
    ServerService-->>API: [PendingActionItem...]
    API-->>ClientService: HTTP 200 [PendingActionItem...]
    ClientService-->>Dashboard: observable emits items
    Dashboard->>Dashboard: boardMemberActions signal updated
    Dashboard-->>User: render pending actions
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas needing extra attention:
    • Duplicate getPendingActionSurveys method in apps/lfx-one/src/server/controllers/project.controller.ts (deduplicate).
    • SQL query correctness and mapping in apps/lfx-one/src/server/services/project.service.ts (types, date formatting, null handling).
    • Signals ↔ Observable interop and error fallback in board-member-dashboard.component.ts.
    • Template branches in pending-actions.component.html (link vs click, empty state) and updated inputs/outputs in component TS file.
    • Angular build config changes (allowedCommonJsDependencies) for potential bundling impacts.

Possibly related PRs

Suggested labels

deploy-preview

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR addresses all primary objectives from LFXV2-764: refactored pending actions to input signals, updated dashboards, implemented backend API, added Snowflake integration, and updated interfaces. However, the project.controller.ts contains a duplicate method declaration which violates the correctness requirement. Remove the duplicate getPendingActionSurveys method declaration in project.controller.ts to ensure a valid class structure and prevent runtime issues.
Out of Scope Changes check ⚠️ Warning Most changes align with stated objectives. However, header.component.ts removes AutocompleteComponent and PersonaSelectorComponent imports without explicit mention in PR objectives, and meeting-card.component.ts changes dialog modal settings (modal: false, closable: false) which appear unrelated to pending actions API. Clarify or document the purpose of changes in header.component.ts and meeting-card.component.ts, or move them to separate PRs if they are independent refactorings not related to LFXV2-764.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding a pending action surveys API. It is concise, clear, and reflects the primary objective of the changeset.
Description check ✅ Passed The description is comprehensive and directly related to the changeset. It clearly outlines frontend refactoring, backend API implementation, and interface changes that match the code modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/LFXV2-764

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 refactors the pending actions component to use input signals and adds backend support for fetching pending survey responses from a Snowflake analytics database. The changes enable the board member dashboard to display real-time survey actions while maintaining static action items for other dashboard personas.

Key Changes

  • Converted pending actions component from computed persona-based logic to input signals for better data flow control
  • Added new GET /api/projects/pending-action-surveys endpoint that queries Snowflake for pending board member surveys
  • Implemented reactive data fetching in board member dashboard using RxJS patterns (toSignal/toObservable)

Reviewed Changes

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

Show a summary per file
File Description
packages/shared/src/interfaces/project.interface.ts Added PendingSurveyRow interface for Snowflake query results with survey metadata
packages/shared/src/interfaces/components.interface.ts Extended PendingActionItem with optional buttonLink field for external survey links
apps/lfx-one/src/server/services/project.service.ts Implemented getPendingActionSurveys method to query and transform survey data
apps/lfx-one/src/server/routes/projects.route.ts Added route for pending-action-surveys endpoint
apps/lfx-one/src/server/controllers/project.controller.ts Added controller method with OIDC email and projectSlug validation
apps/lfx-one/src/app/shared/services/project.service.ts Added frontend service method to call the API endpoint
apps/lfx-one/src/app/modules/dashboards/components/pending-actions/* Refactored to accept pendingActions as required input signal; added empty state and buttonLink support
apps/lfx-one/src/app/modules/dashboards/board-member/* Integrated reactive survey data fetching with error handling
apps/lfx-one/src/app/modules/dashboards/maintainer/* Updated to pass static MAINTAINER_ACTION_ITEMS via signal
apps/lfx-one/src/app/modules/dashboards/core-developer/* Updated to pass static CORE_DEVELOPER_ACTION_ITEMS via signal
apps/lfx-one/src/app/shared/components/meeting-rsvp-details/* Updated progress bar logic to show attended vs not attended for past meetings
apps/lfx-one/src/app/shared/components/meeting-card/meeting-card.component.ts Changed summary modal to non-modal, non-closable, non-dismissable
apps/lfx-one/src/app/shared/components/header/header.component.ts Removed unused imports (PersonaSelectorComponent, AutocompleteComponent)
.github/workflows/docker-build-tag.yml Changed AWS IAM role ARN to different account

💡 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: 2

🧹 Nitpick comments (3)
apps/lfx-one/src/app/shared/components/meeting-rsvp-details/meeting-rsvp-details.component.html (1)

51-51: Consider extracting width calculations into component methods.

The width calculation (count / meetingRegistrantCount()) * 100 is repeated five times across different bar segments. This duplicates logic and reduces maintainability.

For improved clarity and DRY, extract width calculations into component methods:

// In component class:
getAttendedWidth(): number {
  return (this.attendedCount() / this.meetingRegistrantCount()) * 100;
}

getNotAttendedWidth(): number {
  return ((this.meetingRegistrantCount() - this.attendedCount()) / this.meetingRegistrantCount()) * 100;
}

getAcceptedWidth(): number {
  return (this.acceptedCount() / this.meetingRegistrantCount()) * 100;
}

getMaybeWidth(): number {
  return (this.maybeCount() / this.meetingRegistrantCount()) * 100;
}

getDeclinedWidth(): number {
  return (this.declinedCount() / this.meetingRegistrantCount()) * 100;
}

Then update template:

-        @if (attendedCount() > 0) {
-          <div class="h-[5.25px] transition-all duration-300 bg-blue-500" [style.width.%]="(attendedCount() / meetingRegistrantCount()) * 100"></div>
+        @if (attendedCount() > 0) {
+          <div class="h-[5.25px] transition-all duration-300 bg-blue-500" [style.width.%]="getAttendedWidth()"></div>

This pattern also provides a single place to add null-safety guards if needed.

Also applies to: 56-56, 61-61, 64-64, 67-67

apps/lfx-one/src/app/shared/components/meeting-card/meeting-card.component.ts (1)

252-265: Confirm UX/close behavior after making SummaryModal non‑modal and non‑closable

You’ve changed the dynamic dialog config for SummaryModalComponent to:

  • modal: false
  • closable: false
  • dismissableMask: false

This removes the PrimeNG‑level close affordances (no X button, no mask click, and potentially no focus trap), and the dialog no longer blocks interaction with the background. Closing now depends entirely on SummaryModalComponent exposing its own “Close/Cancel/Save” control that calls ref.close(...).

Please verify both:

  1. SummaryModalComponent has a clear, keyboard‑accessible way to close the dialog wired to DynamicDialogRef.close.
  2. The switch to non‑modal behavior is intentional from a UX/accessibility perspective, given this component is reused from multiple dashboards.

If the main goal was just to avoid accidental outside‑click closes while keeping it modal, consider instead keeping modal: true, closable: true and only setting dismissableMask: false (and optionally closeOnEscape: false) to preserve a conventional modal with explicit close controls.

apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.html (1)

7-95: Pending actions template correctly handles input, link behavior, and empty state

The refactor to drive everything from the pendingActions() input, including the @if/@for blocks, color‑based styling, and the link vs. button split with target="_blank"/rel="noopener noreferrer", looks solid and matches the new API shape. The empty state block with a dashed border and test id is also in line with the “my‑meetings” pattern. Only minor nit (optional): track item.text may misbehave if texts are duplicated; if that becomes an issue, consider tracking by a more stable key when one becomes available.

📜 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 156ddfa and 517cfae.

📒 Files selected for processing (17)
  • apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.html (1 hunks)
  • apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (4 hunks)
  • apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.html (1 hunks)
  • apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.ts (1 hunks)
  • apps/lfx-one/src/app/modules/dashboards/core-developer/core-developer-dashboard.component.html (1 hunks)
  • apps/lfx-one/src/app/modules/dashboards/core-developer/core-developer-dashboard.component.ts (2 hunks)
  • apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.html (1 hunks)
  • apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.ts (2 hunks)
  • apps/lfx-one/src/app/shared/components/header/header.component.ts (1 hunks)
  • apps/lfx-one/src/app/shared/components/meeting-card/meeting-card.component.ts (1 hunks)
  • apps/lfx-one/src/app/shared/components/meeting-rsvp-details/meeting-rsvp-details.component.html (1 hunks)
  • apps/lfx-one/src/app/shared/services/project.service.ts (2 hunks)
  • apps/lfx-one/src/server/controllers/project.controller.ts (1 hunks)
  • apps/lfx-one/src/server/routes/projects.route.ts (1 hunks)
  • apps/lfx-one/src/server/services/project.service.ts (2 hunks)
  • packages/shared/src/interfaces/components.interface.ts (1 hunks)
  • packages/shared/src/interfaces/project.interface.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-21T21:19:13.599Z
Learnt from: andrest50
Repo: linuxfoundation/lfx-v2-ui PR: 125
File: apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts:345-350
Timestamp: 2025-10-21T21:19:13.599Z
Learning: In the Angular meeting card component (apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts), when selecting between `summary.summary_data.edited_content` and `summary.summary_data.content`, the logical OR operator (`||`) is intentionally used instead of nullish coalescing (`??`) because empty string edited_content should fall back to the original content rather than being displayed as empty.

Applied to files:

  • apps/lfx-one/src/app/shared/components/meeting-rsvp-details/meeting-rsvp-details.component.html
  • apps/lfx-one/src/app/shared/components/meeting-card/meeting-card.component.ts
  • apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.ts
  • apps/lfx-one/src/app/modules/dashboards/core-developer/core-developer-dashboard.component.ts
🧬 Code graph analysis (7)
apps/lfx-one/src/app/shared/services/project.service.ts (1)
packages/shared/src/interfaces/components.interface.ts (1)
  • PendingActionItem (344-359)
apps/lfx-one/src/server/controllers/project.controller.ts (1)
apps/lfx-one/src/server/errors/index.ts (1)
  • ServiceValidationError (7-7)
apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.ts (1)
packages/shared/src/constants/action-items.constants.ts (1)
  • MAINTAINER_ACTION_ITEMS (39-64)
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (1)
packages/shared/src/interfaces/components.interface.ts (1)
  • PendingActionItem (344-359)
apps/lfx-one/src/app/modules/dashboards/core-developer/core-developer-dashboard.component.ts (1)
packages/shared/src/constants/action-items.constants.ts (1)
  • CORE_DEVELOPER_ACTION_ITEMS (9-34)
apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.ts (4)
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (1)
  • Component (21-86)
apps/lfx-one/src/app/modules/dashboards/core-developer/core-developer-dashboard.component.ts (1)
  • Component (13-25)
apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.ts (1)
  • Component (13-25)
packages/shared/src/interfaces/components.interface.ts (1)
  • PendingActionItem (344-359)
apps/lfx-one/src/server/services/project.service.ts (2)
packages/shared/src/interfaces/components.interface.ts (1)
  • PendingActionItem (344-359)
packages/shared/src/interfaces/project.interface.ts (1)
  • PendingSurveyRow (180-225)
🔇 Additional comments (18)
apps/lfx-one/src/app/shared/components/meeting-rsvp-details/meeting-rsvp-details.component.html (1)

48-69: Refactored progress bar logic looks correct.

The restructured conditional for past vs. upcoming meetings is clear and aligns well with the summary text above. Each bar segment correctly guards against empty renders, and the width calculations are consistent across all states.

apps/lfx-one/src/app/shared/components/header/header.component.ts (1)

25-25: Good dependency cleanup; template verified clean.

Removing AutocompleteComponent and PersonaSelectorComponent is safe. Template verification confirms no references to the removed components, and the component uses PrimeNG's autocomplete directly, making the custom wrapper unnecessary.

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

176-225: LGTM!

The PendingSurveyRow interface is well-documented and comprehensive, covering all necessary fields for survey data from the analytics database. The uppercase naming convention appropriately reflects database column naming.

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

357-359: LGTM!

The optional buttonLink field is a clean, non-breaking addition to the PendingActionItem interface that enables clickable action buttons as described in the PR objectives.

apps/lfx-one/src/app/modules/dashboards/core-developer/core-developer-dashboard.component.html (1)

20-20: LGTM!

The binding correctly references the coreDevActions() signal defined in the TypeScript component (line 24 of core-developer-dashboard.component.ts), maintaining consistency with the reactive pattern applied across other dashboards.

apps/lfx-one/src/app/modules/dashboards/core-developer/core-developer-dashboard.component.ts (2)

4-6: LGTM!

The imports are correct and align with the new signal-based reactive pattern for providing pending actions to the dashboard.


24-24: LGTM!

The coreDevActions signal is properly initialized with the constant data. This pattern is consistent with the maintainer dashboard (static data from constants) while differing from the board-member dashboard which fetches data from the API.

apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.html (1)

20-20: No issues found—implementation is correct.

The verification confirms:

  • maintainerActions signal exists at line 24 of maintainer-dashboard.component.ts and is properly initialized with MAINTAINER_ACTION_ITEMS
  • MAINTAINER_ACTION_ITEMS constant is properly exported in packages/shared/src/constants/action-items.constants.ts with correct type annotation (PendingActionItem[])
  • Import statement is correct and references the proper export path

The code is ready as is.

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

21-22: Controller method verified and OIDC authentication properly implemented.

Verification confirms the getPendingActionSurveys controller method exists and correctly extracts user email from OIDC context with proper error handling. The method validates that req.oidc?.user?.['email'] is present (line 448) and returns a ServiceValidationError if missing. The route's access to req.oidc confirms OIDC authentication middleware is configured at the application level.

apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.html (1)

40-40: No issues found — signal implementation is properly structured.

The boardMemberActions signal is correctly implemented with:

  • Proper reactive pattern using toObservable(), switchMap(), and toSignal()
  • Appropriate data fetching via projectService.getPendingActionSurveys()
  • Comprehensive error handling with logging and fallback to empty array
  • Safe initialization with initialValue: []
  • Correct null handling for missing project selection
apps/lfx-one/src/app/shared/services/project.service.ts (1)

56-65: Backend endpoint implementation verified and properly authenticated.

The verification confirms that the backend endpoint is fully implemented and properly protected. The route exists at projects.route.ts:21 and the controller method at project.controller.ts:443 validates OIDC authentication by requiring req.oidc?.user?.['email'] before processing requests. The endpoint is mounted in the protected API routes section with appropriate error handling for missing authentication context or parameters.

apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.ts (1)

4-7: Maintainer actions signal wiring looks consistent and type‑safe

Using signal(MAINTAINER_ACTION_ITEMS) to expose maintainerActions mirrors the core‑developer dashboard pattern and cleanly feeds static data into PendingActionsComponent. No issues spotted with imports or typing here.

Also applies to: 23-25

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

440-491: Controller endpoint for pending survey actions is well‑structured

Validation of OIDC email and projectSlug, use of ServiceValidationError.forField(...), and delegation to projectService.getPendingActionSurveys all align with existing controller patterns and the stated API contract. Logging includes useful context (email, slug, survey_count), and errors are correctly routed through next.

apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.ts (1)

5-6: Input/output refactor cleanly decouples pending actions from internal persona logic

Switching to pendingActions = input.required<PendingActionItem[]>() and actionClick = output<PendingActionItem>() nicely turns this into a pure presentational component that relies entirely on its callers for data, while preserving the actionClick output semantics. The imports and standalone imports: [CommonModule] list are consistent with this lean surface. Just ensure all dashboard templates now bind [pendingActions] so the required input is always satisfied.

Also applies to: 12-13, 18-23

apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (4)

5-5: LGTM! Imports properly support reactive pattern.

The added imports (toObservable, toSignal, RxJS operators, ProjectService, and PendingActionItem interface) are all necessary for the reactive data fetching implementation.

Also applies to: 8-9, 15-15


30-30: LGTM! Service injection and computed signals properly structured.

The ProjectService injection and computed signals follow Angular best practices. The fallback logic in selectedProject appropriately handles both project and foundation contexts.

Also applies to: 39-40


45-59: LGTM! Constructor properly initializes reactive data flow.

The constructor cleanly separates account selection handling from pending actions initialization, with clear comments documenting each responsibility.


61-85: Implementation verified—no issues found.

The frontend service correctly abstracts the backend complexity. While the backend service requires both email and projectSlug parameters, the frontend service signature properly exposes only projectSlug. The email is correctly extracted from the OIDC context in the backend controller (req.oidc?.user?.['email']) before calling the service. The component's call to getPendingActionSurveys(project.slug) correctly matches the frontend service signature. This follows proper layered architecture.

Signed-off-by: Asitha de Silva <[email protected]>
- Add CommonJS dependencies to allowedCommonJsDependencies list
- Increase component style budget from 4kB to 6kB for production and staging
- Eliminates CommonJS optimization bailout warnings
- Accommodates FullCalendar component styles (5.41 KB)

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

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.html (1)

69-77: Add accessibility indicator for external links.

External links opening in a new tab should include an accessibility indicator to inform users. Consider adding an aria-label attribute that mentions the link opens in a new tab, or include a visual indicator (icon or text).

Apply this diff to add an aria-label:

               <a
                 [href]="item.buttonLink"
                 target="_blank"
                 rel="noopener noreferrer"
                 class="w-full h-8 rounded-md px-3 text-sm font-medium border border-gray-300 bg-white text-gray-700 hover:bg-slate-100 transition-colors flex items-center justify-center"
-                data-testid="dashboard-pending-actions-button">
+                data-testid="dashboard-pending-actions-button"
+                [attr.aria-label]="item.buttonText + ' (opens in new tab)'">
                 {{ item.buttonText }}
               </a>
🧹 Nitpick comments (1)
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (1)

74-77: Consider using a logging service instead of console.error.

Direct console.error calls may not be appropriate for production environments where structured logging, log aggregation, or log levels are important.

If a logging service exists in the codebase, apply this pattern:

           return this.projectService.getPendingActionSurveys(project.slug).pipe(
             catchError((error) => {
-              console.error('Failed to fetch survey actions:', error);
+              this.logger.error('Failed to fetch survey actions', { error, projectSlug: project.slug });
               // Return empty array on error
               return of([]);
             })
📜 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 517cfae and c6a1971.

📒 Files selected for processing (2)
  • apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (4 hunks)
  • apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.html (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (1)
packages/shared/src/interfaces/components.interface.ts (1)
  • PendingActionItem (344-359)
🔇 Additional comments (1)
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (1)

60-84: Reactive pattern implementation looks solid.

The implementation correctly uses Angular's signal-observable interop to create a reactive data flow that automatically updates when the selected project changes. The use of switchMap prevents race conditions, and error handling gracefully degrades to an empty state.

Consider whether silent error handling is the desired UX. Currently, errors are logged but users see an empty state with no indication that a fetch failed. If this is intentional to avoid error noise, the current implementation is fine. Otherwise, consider adding user-facing error feedback.

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

📜 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 c6a1971 and 2a24cd4.

📒 Files selected for processing (1)
  • apps/lfx-one/angular.json (3 hunks)
🔇 Additional comments (1)
apps/lfx-one/angular.json (1)

80-80: Budget increase is justified—FullCalendar component styles require 5.41 KB, exceeding the original 4kB limit.

The anyComponentStyle budget increase (4kB → 6kB) is documented and necessary. The PR integrates the FullCalendar library, whose compiled styles are 5.41 kB—above the previous threshold. The new 6kB limit accommodates this with a reasonable buffer. Style optimization concerns do not apply to external library CSS; this is a required tradeoff for new functionality. The commit message (LFXV2-764) explicitly documents this justification.

@dealako dealako merged commit f15f8bb into main Nov 19, 2025
6 checks passed
@dealako dealako deleted the feat/LFXV2-764 branch November 19, 2025 15:15
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