Skip to content

Conversation

@asithade
Copy link
Contributor

@asithade asithade commented Nov 3, 2025

Summary

Integrates real Snowflake analytics data into the Board Member Dashboard's organization involvement metrics, with optimized API architecture through endpoint consolidation. This PR replaces hardcoded placeholder data with live organization-level analytics while reducing API complexity from 15 endpoints to 4 consolidated endpoints.

JIRA Ticket

LFXV2-701

Changes

Phase 1: Initial Snowflake Integration

Frontend Updates

  • Board Member Dashboard Component: Refactored to use reactive form pattern with valueChanges subscription and takeUntilDestroyed() for automatic cleanup
  • Organization Involvement Component:
    • Added 5 new analytics data signals for real-time data display
    • Integrated CurrencyPipe for multi-currency event sponsorship formatting
    • Updated all metrics to display connected status with live data
    • Removed conditional "not connected" states

Backend Updates

Created 15 new API endpoints for organization-level analytics across multiple data domains:

  • Organization contributions (maintainers, contributors, technical committee)
  • Segment participation (projects participating, total commits)
  • Board member metrics (membership tier, certified employees, board attendance)
  • Event participation (event attendance, event sponsorships)

Each endpoint:

  • Queries Snowflake tables in ANALYTICS_DEV.DEV_JEVANS_PLATINUM_LFX_ONE schema
  • Implements proper error handling with ResourceNotFoundError
  • Includes comprehensive logging for operations tracking

Phase 2: API Consolidation & Optimization

Refactored 15 individual analytics endpoints into 4 optimized consolidated endpoints:

Consolidated Endpoints

  1. /api/analytics/organization-contributions-overview

    • Combines: maintainers + contributors + technical committee
    • Single database query with LEFT JOINs
    • Reduces 3 API calls → 1 API call
  2. /api/analytics/organization-segment-overview

    • Combines: projects participating + total commits
    • Single database query with LEFT JOINs
    • Reduces 2 API calls → 1 API call
  3. /api/analytics/board-member-dashboard

    • Combines: membership tier + certified employees + board meeting attendance
    • Single database query with LEFT JOINs
    • Reduces 3 API calls → 1 API call
  4. /api/analytics/organization-events-overview

    • Combines: event attendance + event sponsorships
    • Parallel database queries (different tables)
    • Reduces 2 API calls → 1 API call

Backend Refactoring

  • Inlined legacy methods: Removed getEventAttendance and getEventSponsorships wrapper methods
  • Renamed private helpers: Removed "Consolidated" suffix for cleaner naming
    • getOrganizationContributionsConsolidatedgetContributionsData
    • getSegmentContributionsConsolidatedgetSegmentData
    • getBoardMemberDashboardConsolidatedgetDashboardData
  • Removed 10 legacy endpoint handlers from analytics controller
  • Cleaned up JSDoc comments and simplified documentation

Frontend Optimization

  • Removed 10 unused HTTP methods from analytics service
  • Updated component to use 4 consolidated endpoints instead of 10+ individual calls
  • Cleaned up imports: Removed 10 unused response interface imports

Shared Package Cleanup

  • Removed 21 unused interfaces from analytics-data.interface.ts (~450 lines removed, 36% file size reduction)
  • Removed legacy interfaces no longer used after endpoint consolidation:
    • 3 individual API response interfaces
    • 10 Snowflake row interfaces
    • 5 additional response interfaces
    • 3 event sponsorship interfaces

Type Safety

  • Created TypeScript interfaces in @lfx-one/shared package for all analytics responses
  • Added Snowflake row type definitions for database schema mapping
  • Maintained consistency with existing analytics service patterns
  • Consolidated response interfaces for optimized endpoints

Performance Impact

API Efficiency

  • Endpoint reduction: 15 endpoints → 4 endpoints (73% reduction)
  • Database queries: 15 individual queries → 8 consolidated queries (47% reduction)
  • Network requests: Organization dashboard now makes 4 API calls instead of 10+
  • Code reduction: Net -602 lines across 6 files (1,143 deletions vs 541 additions)

Query Optimization

  • Single JOINed queries replace multiple round-trips for related data
  • Parallel execution (Promise.all()) for independent queries on different tables
  • Nullable fields with proper COALESCE handling for partial data scenarios

Files Modified

Phase 1 (8 files)

  • 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
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.html
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
  • apps/lfx-one/src/app/shared/services/analytics.service.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
  • apps/lfx-one/src/server/routes/analytics.route.ts
  • packages/shared/src/interfaces/analytics-data.interface.ts

Phase 2 - Additional Changes (6 files)

  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts - Updated to use consolidated endpoints
  • apps/lfx-one/src/app/shared/services/analytics.service.ts - Removed 10 unused methods
  • apps/lfx-one/src/server/controllers/analytics.controller.ts - Removed 10 legacy handlers
  • apps/lfx-one/src/server/routes/analytics.route.ts - Removed 10 legacy routes
  • apps/lfx-one/src/server/services/organization.service.ts - Inlined methods, renamed helpers
  • packages/shared/src/interfaces/analytics-data.interface.ts - Removed 21 unused interfaces

Technical Details

  • Angular Pattern: Uses Angular 19 reactive forms with takeUntilDestroyed() for memory leak prevention
  • SQL Optimization: LEFT JOINs with COALESCE for flexible NULL handling in consolidated queries
  • Parallel Execution: Promise.all() for independent queries on different Snowflake tables
  • Error Handling: Implements ResourceNotFoundError for missing data scenarios with proper HTTP status codes
  • Type Safety: All API responses and database rows have TypeScript interfaces
  • Consistency: Follows existing analytics service patterns for maintainability
  • Logging: Comprehensive operation logging with metrics tracking

Testing

  • ✅ Linting passed
  • ✅ Type checking passed
  • ✅ Build successful
  • ✅ License headers verified
  • ✅ Pre-commit hooks passed
  • ✅ All consolidated endpoints tested and validated

Migration Notes

  • Frontend components automatically use consolidated endpoints
  • No breaking changes to component interfaces
  • All nullable fields properly handled with default fallbacks
  • Backwards compatible error handling maintained

Generated with Claude Code

- Add 5 new API endpoints for organization-level analytics data
- Integrate real Snowflake data into organization involvement metrics
- Refactor board member dashboard to use reactive form pattern
- Add support for projects participating, total commits, certified employees,
  board meeting attendance, and event sponsorships metrics
- Update organization involvement component to display live analytics data
- Add multi-currency formatting for event sponsorships
- Create TypeScript interfaces in shared package for type safety

LFXV2-701

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

coderabbitai bot commented Nov 3, 2025

Caution

Review failed

The pull request is closed.

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

Consolidates analytics endpoints and interfaces, adds Snowflake-backed organization/user analytics services, removes legacy analytics routes, updates server controllers to delegate to services, introduces ANALYTICS_DEFAULTS, and refactors frontend dashboard components and metrics to use new consolidated signals, CurrencyPipe, and reactive FormGroup subscription.

Changes

Cohort / File(s) Summary
Board Member Dashboard Component Refactor
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
Template form binding switched from accountForm to form; removed (onChange) handler; form and availableAccounts made public; handleAccountChange removed and replaced by subscribing to form control valueChanges (using takeUntilDestroyed) to update selected account.
Organization Involvement Metrics Enhancement
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.html, apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
Template simplified (tier/span, renamed labels), numeric pipe removed; component now provides/injects CurrencyPipe, introduces per-block loading signals and consolidated data signals (contributions, boardMemberDashboard, segment, events); adds transforms (event sponsorship, membership tier) and recomputes metrics from consolidated shapes.
Analytics Service API Expansion (Client)
apps/lfx-one/src/app/shared/services/analytics.service.ts
Removed multiple legacy granular methods and response types; added consolidated typed methods returning Observables: getOrganizationContributionsOverview, getOrganizationSegmentOverview, getBoardMemberDashboard, getOrganizationEventsOverview (each accepts optional accountId) and updated JSDoc and error fallbacks.
Analytics Controller Endpoints (Server)
apps/lfx-one/src/server/controllers/analytics.controller.ts
Controller refactored to use OrganizationService and UserService (constructor-injected); added endpoints delegating to service methods for contributions overview, segment overview, board-member dashboard, and events overview; updated logging payloads and defaulting to ANALYTICS_DEFAULTS when needed.
Analytics Routes
apps/lfx-one/src/server/routes/analytics.route.ts
Removed legacy routes (/organization-maintainers, /organization-contributors, /organization-event-attendance, /organization-technical-committee, /membership-tier); added consolidated routes: /organization-contributions-overview, /organization-segment-overview, /board-member-dashboard, /organization-events-overview.
Analytics Data Interfaces
packages/shared/src/interfaces/analytics-data.interface.ts
Replaced multiple granular interfaces with Snowflake-style row interfaces and consolidated overview/response interfaces (e.g., OrganizationContributionsOverviewResponse, OrganizationSegmentOverviewResponse, BoardMemberDashboardResponse, OrganizationEventsOverviewResponse, sponsorship aggregates); standardized nullable fields and ALL_CAPS row shapes.
Analytics Defaults Constant & Re-exports
packages/shared/src/constants/analytics.constants.ts, packages/shared/src/constants/index.ts
Added exported ANALYTICS_DEFAULTS with fallback IDs (ACCOUNT_ID, PROJECT_ID, SEGMENT_ID); re-exported from constants index.
Organization & User Services: Snowflake-backed Analytics
apps/lfx-one/src/server/services/organization.service.ts, apps/lfx-one/src/server/services/user.service.ts
Added SnowflakeService usage and new analytics methods: organization-level (contributions overview, board-member dashboard data, segment overview, events overview) and user-level (active weeks streak, pull requests merged, code commits, paginated projects); added helpers, mappings to new response shapes, error handling, and JSDoc.
Snowflake & Lock Manager Minor Cleanup
apps/lfx-one/src/server/services/snowflake.service.ts, apps/lfx-one/src/server/utils/lock-manager.ts
Removed runtime informational logging from SnowflakeService constructor and LockManager initialization; changed Bind import to a type-only import to avoid runtime import.
Dashboard UI Constants & Interfaces Update
packages/shared/src/constants/organization-involvement.constants.ts, packages/shared/src/interfaces/dashboard.interface.ts
PRIMARY_INVOLVEMENT_METRICS reworked to be API-driven (removed hard-coded values, added icon for membership metric and TODOs); PrimaryInvolvementMetric type updated (value/subtitle optional, removed annualFee).

Sequence Diagram(s)

sequenceDiagram
    %% Styling: subtle colored notes to highlight new/changed interactions
    participant UI as Frontend Component
    participant Signals as Component Signals
    participant Client as AnalyticsService (HTTP)
    participant API as Analytics Controller
    participant Service as OrganizationService / UserService
    participant DB as Snowflake

    UI->>Signals: init & subscribe
    Signals->>Client: request consolidated data (e.g., board-member-dashboard)
    Client->>API: GET /api/analytics/board-member-dashboard?accountId=...
    API->>Service: delegate call (uses ANALYTICS_DEFAULTS if missing)
    Service->>DB: execute Snowflake query(ies)
    alt success
        DB-->>Service: rows
        Service-->>API: mapped consolidated response
        API-->>Client: JSON response
        Client-->>Signals: emit consolidated signals
        Signals-->>UI: update metrics (CurrencyPipe transforms applied)
    else error/empty
        Service-->>API: fallback default response
        API-->>Client: fallback JSON
        Client-->>Signals: emit fallback
        Signals-->>UI: render fallback values
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas needing extra attention:
    • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts — many new signals, transforms, CurrencyPipe usage.
    • apps/lfx-one/src/server/controllers/analytics.controller.ts — service delegation, use of ANALYTICS_DEFAULTS, logging and error shapes.
    • apps/lfx-one/src/server/services/organization.service.ts and apps/lfx-one/src/server/services/user.service.ts — Snowflake queries, SQL correctness, mapping to shared interfaces.
    • packages/shared/src/interfaces/analytics-data.interface.ts — ensure types align with service/controller responses and DB row shapes.
    • apps/lfx-one/src/app/shared/services/analytics.service.ts — HTTP paths and error fallback handling.

Possibly related PRs

Pre-merge checks and finishing touches

✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and accurately summarizes the main change: integrating Snowflake analytics data into the Board Member Dashboard's organization involvement metrics. It is specific and matches the primary objective of the pull request.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, covering frontend refactoring, backend API endpoints, type safety improvements, and technical details that align with the actual changes made.
Linked Issues check ✅ Passed The pull request successfully implements all coding requirements from LFXV2-701: refactored board member dashboard with reactive forms and takeUntilDestroyed, added analytics signals with CurrencyPipe for sponsorships, created four consolidated API endpoints with proper error handling, and added TypeScript interfaces for type safety.
Out of Scope Changes check ✅ Passed Additional changes appear beyond the five stated endpoints: imports/exports reorganization, constants module creation (ANALYTICS_DEFAULTS), SnowflakeService modifications, lock-manager type-only imports, and service layer refactoring. These align with internal consolidation but weren't explicitly mentioned in LFXV2-701's endpoint list.

📜 Recent 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 8d2a4b5 and e84447e.

📒 Files selected for processing (7)
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.html (2 hunks)
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (6 hunks)
  • apps/lfx-one/src/app/shared/services/analytics.service.ts (2 hunks)
  • apps/lfx-one/src/server/services/organization.service.ts (2 hunks)
  • packages/shared/src/constants/organization-involvement.constants.ts (1 hunks)
  • packages/shared/src/interfaces/analytics-data.interface.ts (1 hunks)
  • packages/shared/src/interfaces/dashboard.interface.ts (1 hunks)

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 adds five new analytics endpoints to provide organization-level metrics for a board member dashboard, including projects participating, total commits, certified employees, board meeting attendance, and event sponsorships.

  • Adds five new Snowflake query interfaces for member dashboard metrics (projects, commits, certifications, meetings, sponsorships)
  • Implements five new API endpoints in the analytics controller with hardcoded defaults for accountId, segmentId, and projectId
  • Creates corresponding frontend service methods and component integration with real-time data transformations

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
packages/shared/src/interfaces/analytics-data.interface.ts Adds 15 new TypeScript interfaces for Snowflake queries and API responses
apps/lfx-one/src/server/routes/analytics.route.ts Registers five new GET routes for organization analytics endpoints
apps/lfx-one/src/server/controllers/analytics.controller.ts Implements five new controller methods with Snowflake queries and error handling
apps/lfx-one/src/app/shared/services/analytics.service.ts Adds five frontend service methods with error handling fallbacks
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts Integrates new data streams, adds CurrencyPipe provider, and transforms data for display with formatting
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.html Removes number pipe formatting from metric values to support pre-formatted strings
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts Refactors form handling to use reactive subscription pattern instead of event handler
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.html Updates template to use refactored form name and removes onChange handler

💡 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

📜 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 dea876e and f13be35.

📒 Files selected for processing (8)
  • apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.html (2 hunks)
  • apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (2 hunks)
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.html (1 hunks)
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (9 hunks)
  • apps/lfx-one/src/app/shared/services/analytics.service.ts (2 hunks)
  • apps/lfx-one/src/server/controllers/analytics.controller.ts (2 hunks)
  • apps/lfx-one/src/server/routes/analytics.route.ts (1 hunks)
  • packages/shared/src/interfaces/analytics-data.interface.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
apps/lfx-one/src/**/*.html

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.html
  • apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.html
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Include required license headers on all source files

Files:

  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.html
  • apps/lfx-one/src/server/routes/analytics.route.ts
  • packages/shared/src/interfaces/analytics-data.interface.ts
  • apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.html
  • apps/lfx-one/src/app/shared/services/analytics.service.ts
  • apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • apps/lfx-one/src/server/routes/analytics.route.ts
  • packages/shared/src/interfaces/analytics-data.interface.ts
  • apps/lfx-one/src/app/shared/services/analytics.service.ts
  • apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • apps/lfx-one/src/server/routes/analytics.route.ts
  • packages/shared/src/interfaces/analytics-data.interface.ts
  • apps/lfx-one/src/app/shared/services/analytics.service.ts
  • apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
packages/shared/src/interfaces/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • packages/shared/src/interfaces/analytics-data.interface.ts
🧠 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/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
🧬 Code graph analysis (4)
apps/lfx-one/src/app/shared/services/analytics.service.ts (1)
packages/shared/src/interfaces/analytics-data.interface.ts (5)
  • OrganizationProjectsParticipatingResponse (433-448)
  • OrganizationTotalCommitsResponse (475-490)
  • OrganizationCertifiedEmployeesResponse (522-537)
  • OrganizationBoardMeetingAttendanceResponse (579-604)
  • OrganizationEventSponsorshipsResponse (703-718)
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (1)
packages/shared/src/interfaces/account.interface.ts (1)
  • Account (8-13)
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (4)
packages/shared/src/constants/organization-involvement.constants.ts (3)
  • CONTRIBUTIONS_METRICS (66-87)
  • IMPACT_METRICS (93-114)
  • PRIMARY_INVOLVEMENT_METRICS (20-60)
packages/shared/src/interfaces/analytics-data.interface.ts (1)
  • OrganizationEventSponsorshipsResponse (703-718)
packages/shared/src/interfaces/dashboard.interface.ts (2)
  • PrimaryInvolvementMetric (63-88)
  • OrganizationInvolvementMetricWithChart (124-167)
packages/shared/src/utils/color.utils.ts (1)
  • hexToRgba (28-56)
apps/lfx-one/src/server/controllers/analytics.controller.ts (1)
packages/shared/src/interfaces/analytics-data.interface.ts (11)
  • MemberDashboardProjectsParticipatingRow (412-427)
  • OrganizationProjectsParticipatingResponse (433-448)
  • MemberDashboardTotalCommitsRow (454-469)
  • OrganizationTotalCommitsResponse (475-490)
  • MemberDashboardCertifiedEmployeesRow (496-516)
  • OrganizationCertifiedEmployeesResponse (522-537)
  • MemberDashboardBoardMeetingAttendanceRow (543-573)
  • OrganizationBoardMeetingAttendanceResponse (579-604)
  • OrganizationEventSponsorshipsAggregateRow (656-671)
  • OrganizationEventSponsorshipsEventCountRow (677-682)
  • OrganizationEventSponsorshipsResponse (703-718)
🔇 Additional comments (1)
packages/shared/src/interfaces/analytics-data.interface.ts (1)

408-718: LGTM! Well-structured interface definitions with comprehensive documentation.

The new analytics interfaces follow the established patterns in this file consistently:

  • Snowflake row interfaces use ALL_CAPS naming convention
  • API response interfaces use camelCase properties
  • All fields are properly typed and documented
  • The separation between raw Snowflake rows and API responses is clear and maintainable

The omission of projectId in the response interfaces (despite PROJECT_ID being present in some row interfaces like MemberDashboardCertifiedEmployeesRow, MemberDashboardBoardMeetingAttendanceRow, and MemberDashboardEventSponsorshipRow) is consistent with other organization-level aggregated responses in this file, indicating the data is aggregated across projects at the backend level.

@github-actions
Copy link

github-actions bot commented Nov 3, 2025

🚀 Deployment Status

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

Deployment Details:

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

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

- Extract hardcoded accountId, projectId, and segmentId to shared constants
- Create ANALYTICS_DEFAULTS constant in shared package for temporary values
- Replace 16 inline hardcoded values in analytics controller with constants
- Fix InvalidPipeArgument crash when Snowflake returns null/empty currency codes
- Add filtering in transformEventSponsorship to handle imperfect data gracefully
- Dashboard now resilient to legacy/draft sponsorship records with missing currency

LFXV2-701

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

🧹 Nitpick comments (1)
packages/shared/src/constants/index.ts (1)

23-23: Verify barrel export compliance with coding guidelines.

The coding guideline states "Do not use barrel exports; always use direct imports for standalone components." While this export is for constants rather than components, clarify whether the guideline applies only to component barrels or to all index.ts files.

📜 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 f13be35 and 77debfe.

📒 Files selected for processing (4)
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (9 hunks)
  • apps/lfx-one/src/server/controllers/analytics.controller.ts (7 hunks)
  • packages/shared/src/constants/analytics.constants.ts (1 hunks)
  • packages/shared/src/constants/index.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/index.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Do not use barrel exports; always use direct imports for standalone components

Files:

  • packages/shared/src/constants/index.ts
packages/shared/src/constants/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Place all reusable constants in the shared package at packages/shared/src/constants

Files:

  • packages/shared/src/constants/index.ts
  • packages/shared/src/constants/analytics.constants.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • packages/shared/src/constants/index.ts
  • packages/shared/src/constants/analytics.constants.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Include required license headers on all source files

Files:

  • packages/shared/src/constants/index.ts
  • packages/shared/src/constants/analytics.constants.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • packages/shared/src/constants/index.ts
  • packages/shared/src/constants/analytics.constants.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
🧠 Learnings (2)
📚 Learning: 2025-09-16T03:32:46.518Z
Learnt from: CR
Repo: linuxfoundation/lfx-v2-ui PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-16T03:32:46.518Z
Learning: Applies to packages/shared/src/constants/**/*.ts : Place all reusable constants in the shared package at packages/shared/src/constants

Applied to files:

  • packages/shared/src/constants/index.ts
📚 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/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
🧬 Code graph analysis (2)
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (4)
packages/shared/src/constants/organization-involvement.constants.ts (3)
  • CONTRIBUTIONS_METRICS (66-87)
  • IMPACT_METRICS (93-114)
  • PRIMARY_INVOLVEMENT_METRICS (20-60)
packages/shared/src/interfaces/analytics-data.interface.ts (1)
  • OrganizationEventSponsorshipsResponse (703-718)
packages/shared/src/interfaces/dashboard.interface.ts (2)
  • PrimaryInvolvementMetric (63-88)
  • OrganizationInvolvementMetricWithChart (124-167)
packages/shared/src/utils/color.utils.ts (1)
  • hexToRgba (28-56)
apps/lfx-one/src/server/controllers/analytics.controller.ts (3)
packages/shared/src/constants/analytics.constants.ts (1)
  • ANALYTICS_DEFAULTS (8-26)
packages/shared/src/interfaces/analytics-data.interface.ts (11)
  • MemberDashboardProjectsParticipatingRow (412-427)
  • OrganizationProjectsParticipatingResponse (433-448)
  • MemberDashboardTotalCommitsRow (454-469)
  • OrganizationTotalCommitsResponse (475-490)
  • MemberDashboardCertifiedEmployeesRow (496-516)
  • OrganizationCertifiedEmployeesResponse (522-537)
  • MemberDashboardBoardMeetingAttendanceRow (543-573)
  • OrganizationBoardMeetingAttendanceResponse (579-604)
  • OrganizationEventSponsorshipsAggregateRow (656-671)
  • OrganizationEventSponsorshipsEventCountRow (677-682)
  • OrganizationEventSponsorshipsResponse (703-718)
apps/lfx-one/src/server/errors/index.ts (1)
  • ResourceNotFoundError (7-7)
⏰ 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: build-and-push
🔇 Additional comments (13)
packages/shared/src/constants/analytics.constants.ts (1)

8-26: LGTM! Temporary defaults well-documented.

The constant structure is clean with clear documentation indicating these are temporary values. The TODO comment appropriately flags the need to replace with dynamic values from user context.

apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (6)

4-35: LGTM! CurrencyPipe integration follows Angular best practices.

The pipe is correctly imported, provided, and injected for programmatic currency formatting.


97-152: LGTM! New data signals follow established patterns.

All five signals use consistent reactive composition with toSignal and switchMap, matching the existing implementation pattern. Initial values align with their respective response interfaces.


189-222: LGTM! Contributions metrics correctly integrate live data.

The computed property properly transforms Snowflake data into display values with appropriate formatting (toLocaleString for commits, toFixed for percentages).


224-263: LGTM! Impact metrics display enriched certification details.

The combined display format for certified employees (showing both certifications count and employee count) provides valuable context.


336-350: LGTM! Empty membership state handling is appropriate.

Treating "no membership" as a connected state (isConnected: true) correctly distinguishes between successfully queried data with no membership versus a data connection failure.


372-402: LGTM! Currency code filtering prevents pipe errors.

The implementation correctly addresses the previous review concern by filtering out null/empty currency codes (line 375) and null pipe results (line 377) before building the display string. This ensures resilience against imperfect Snowflake data.

apps/lfx-one/src/server/controllers/analytics.controller.ts (6)

4-37: LGTM! Centralized defaults improve maintainability.

The import of ANALYTICS_DEFAULTS replaces scattered hardcoded fallback values, addressing previous maintainability concerns.


633-681: LGTM! Projects participating endpoint follows established patterns.

The implementation correctly queries Snowflake with both accountId and segmentId parameters, handles empty results with ResourceNotFoundError, and provides comprehensive logging.


683-731: LGTM! Total commits endpoint implementation is solid.

Consistent error handling, parameterized queries, and logging align with the existing codebase standards.


733-782: LGTM! Certified employees endpoint handles dual metrics correctly.

The endpoint properly returns both certifications count and certifiedEmployees count, providing the granular data needed for the frontend display.


784-845: LGTM! Attendance percentage calculation includes divide-by-zero protection.

The SQL CASE statement (lines 803-806) correctly guards against division by zero when TOTAL_MEETINGS is zero, returning 0 instead.


847-917: LGTM! Dual-query approach correctly handles multi-currency sponsorships.

The two-query strategy (lines 862-872 for per-currency sums, lines 883-888 for total events) properly addresses the distinct aggregation requirements. The frontend currency filtering complements the backend implementation.

Refactored analytics.controller.ts to follow the established Controller → Service → Data Source pattern used by other controllers in the codebase.

Changes:
- Moved 4 user analytics methods to UserService (active weeks streak, pull requests, code commits, projects)
- Moved 10 organization analytics methods to OrganizationService (maintainers, membership tier, contributors, events, technical committee, certifications, board meetings, sponsorships)
- Removed inline SQL queries and business logic from analytics.controller.ts
- Controller now only handles HTTP concerns (validation, logging, response)
- Reduced controller complexity from 930 lines to ~400 lines
- Removed all unused interface imports from controller

LFXV2-701

Generated with [Claude Code](https://claude.com/claude-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: 1

🧹 Nitpick comments (5)
apps/lfx-one/src/server/utils/lock-manager.ts (2)

11-11: Good refactor to type-only import.

Changing to import type is correct since Bind is only used in type annotations (lines 74, 208) and not at runtime. This reduces the bundle size and follows TypeScript best practices.


31-43: Consider retaining initialization logging for observability.

The removal of the initialization log creates an asymmetry with the shutdown log (line 113) and may impact debugging during service startup. While the change aligns with the PR's goal of reducing runtime logging, a simple initialization log (perhaps at debug level) could aid troubleshooting without significant overhead.

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

320-355: Consider extracting shared logic

The getCodeCommits and getPullRequestsMerged methods share nearly identical structure. Consider extracting a generic helper method to reduce duplication:

private async getUserActivityData<T extends { ACTIVITY_DATE: string; DAILY_COUNT: number; TOTAL_COUNT: number }>(
  userEmail: string,
  tableName: string,
  errorMessage: string,
  operation: string
): Promise<{ data: T[]; total: number; totalDays: number }> {
  const query = `
    SELECT
      ACTIVITY_DATE,
      DAILY_COUNT,
      SUM(DAILY_COUNT) OVER () as TOTAL_COUNT
    FROM ${tableName}
    WHERE EMAIL = ?
      AND ACTIVITY_DATE >= DATEADD(DAY, -30, CURRENT_DATE())
    ORDER BY ACTIVITY_DATE ASC
  `;

  const result = await this.snowflakeService.execute<T>(query, [userEmail]);

  if (result.rows.length === 0) {
    throw new ResourceNotFoundError(errorMessage, userEmail, { operation });
  }

  return {
    data: result.rows,
    total: result.rows[0].TOTAL_COUNT,
    totalDays: result.rows.length,
  };
}
apps/lfx-one/src/server/services/organization.service.ts (2)

103-109: Consider explicit column selection

Using SELECT * can lead to performance issues and breaks if the table schema changes. Consider explicitly listing required columns.

-    SELECT *
+    SELECT 
+      MEMBERSHIP_TIER,
+      CURRENT_MEMBERSHIP_START_DATE,
+      CURRENT_MEMBERSHIP_END_DATE,
+      MEMBERSHIP_PRICE,
+      MEMBERSHIP_STATUS,
+      ACCOUNT_ID,
+      PROJECT_ID
     FROM ANALYTICS_DEV.DEV_JEVANS_PLATINUM_LFX_ONE.MEMBER_DASHBOARD_MEMBERSHIP_TIER

235-297: Consider extracting shared pattern

getProjectsParticipating and getTotalCommits share nearly identical structure. Consider a generic helper to reduce duplication:

private async getOrganizationMetricBySegment<TRow, TResponse>(
  accountId: string,
  segmentId: string,
  tableName: string,
  columnName: string,
  operation: string,
  errorMessage: string,
  mapFn: (row: TRow, accountId: string, segmentId: string) => TResponse
): Promise<TResponse> {
  const query = `
    SELECT ACCOUNT_ID, SEGMENT_ID, ${columnName}
    FROM ANALYTICS_DEV.DEV_JEVANS_PLATINUM_LFX_ONE.${tableName}
    WHERE ACCOUNT_ID = ?
      AND SEGMENT_ID = ?
    LIMIT 1
  `;

  const result = await this.snowflakeService.execute<TRow>(query, [accountId, segmentId]);

  if (result.rows.length === 0) {
    throw new ResourceNotFoundError(errorMessage, accountId, { operation });
  }

  return mapFn(result.rows[0], accountId, segmentId);
}
📜 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 77debfe and bec3ebc.

📒 Files selected for processing (5)
  • apps/lfx-one/src/server/controllers/analytics.controller.ts (11 hunks)
  • apps/lfx-one/src/server/services/organization.service.ts (2 hunks)
  • apps/lfx-one/src/server/services/snowflake.service.ts (0 hunks)
  • apps/lfx-one/src/server/services/user.service.ts (2 hunks)
  • apps/lfx-one/src/server/utils/lock-manager.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • apps/lfx-one/src/server/services/snowflake.service.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • apps/lfx-one/src/server/utils/lock-manager.ts
  • apps/lfx-one/src/server/services/user.service.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
  • apps/lfx-one/src/server/services/organization.service.ts
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Include required license headers on all source files

Files:

  • apps/lfx-one/src/server/utils/lock-manager.ts
  • apps/lfx-one/src/server/services/user.service.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
  • apps/lfx-one/src/server/services/organization.service.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • apps/lfx-one/src/server/utils/lock-manager.ts
  • apps/lfx-one/src/server/services/user.service.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
  • apps/lfx-one/src/server/services/organization.service.ts
🧬 Code graph analysis (3)
apps/lfx-one/src/server/services/user.service.ts (5)
apps/lfx-one/src/server/services/nats.service.ts (1)
  • NatsService (13-133)
apps/lfx-one/src/server/services/snowflake.service.ts (1)
  • SnowflakeService (26-400)
packages/shared/src/interfaces/analytics-data.interface.ts (9)
  • ActiveWeeksStreakResponse (25-40)
  • ActiveWeeksStreakRow (10-20)
  • UserPullRequestsResponse (66-81)
  • UserPullRequestsRow (46-61)
  • UserCodeCommitsResponse (107-122)
  • UserCodeCommitsRow (87-102)
  • UserProjectsResponse (168-178)
  • ProjectCountRow (307-309)
  • UserProjectActivityRow (128-163)
apps/lfx-one/src/server/errors/index.ts (1)
  • ResourceNotFoundError (7-7)
packages/shared/src/interfaces/components.interface.ts (1)
  • ProjectItem (368-383)
apps/lfx-one/src/server/controllers/analytics.controller.ts (3)
apps/lfx-one/src/server/services/user.service.ts (1)
  • UserService (33-511)
apps/lfx-one/src/server/services/organization.service.ts (1)
  • OrganizationService (40-425)
packages/shared/src/constants/analytics.constants.ts (1)
  • ANALYTICS_DEFAULTS (8-26)
apps/lfx-one/src/server/services/organization.service.ts (3)
apps/lfx-one/src/server/services/snowflake.service.ts (1)
  • SnowflakeService (26-400)
packages/shared/src/interfaces/analytics-data.interface.ts (21)
  • OrganizationMaintainersResponse (184-199)
  • MemberDashboardMaintainersRow (267-272)
  • MembershipTierResponse (205-235)
  • MembershipTierRow (278-290)
  • OrganizationContributorsResponse (241-261)
  • OrganizationContributorsRow (296-301)
  • OrganizationEventAttendanceResponse (340-365)
  • OrganizationEventAttendanceRow (328-334)
  • OrganizationTechnicalCommitteeResponse (391-406)
  • OrganizationTechnicalCommitteeRow (381-385)
  • OrganizationProjectsParticipatingResponse (433-448)
  • MemberDashboardProjectsParticipatingRow (412-427)
  • OrganizationTotalCommitsResponse (475-490)
  • MemberDashboardTotalCommitsRow (454-469)
  • OrganizationCertifiedEmployeesResponse (522-537)
  • MemberDashboardCertifiedEmployeesRow (496-516)
  • OrganizationBoardMeetingAttendanceResponse (579-604)
  • MemberDashboardBoardMeetingAttendanceRow (543-573)
  • OrganizationEventSponsorshipsResponse (703-718)
  • OrganizationEventSponsorshipsAggregateRow (656-671)
  • OrganizationEventSponsorshipsEventCountRow (677-682)
apps/lfx-one/src/server/errors/index.ts (1)
  • ResourceNotFoundError (7-7)
⏰ 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: build-and-push
🔇 Additional comments (10)
apps/lfx-one/src/server/services/user.service.ts (3)

6-40: LGTM: Service initialization with SnowflakeService

The analytics imports and SnowflakeService initialization are properly structured, following the same pattern as the NatsService integration.


264-274: Verify streak calculation starts at week 0

The current streak calculation assumes result.rows[0] corresponds to WEEKS_AGO = 0. If the query returns data starting at a different week (e.g., no data for week 0), the streak would be incorrect.

Consider adding a verification step:

 // Calculate current streak (consecutive weeks of activity from week 0)
 // Data is ordered by WEEKS_AGO ASC, so index 0 is week 0 (current week)
 let currentStreak = 0;
+
+// Verify data starts at week 0
+if (result.rows[0].WEEKS_AGO !== 0) {
+  // No data for current week, streak is 0
+  return {
+    data: result.rows,
+    currentStreak: 0,
+    totalWeeks: result.rows.length,
+  };
+}

 for (const row of result.rows) {

296-296: Schema inconsistency across analytics methods requires clarification

Lines 296 and 333 query ANALYTICS.PLATINUM_LFX_ONE (production schema), while other methods in the same file use ANALYTICS_DEV.DEV_JEVANS_PLATINUM_LFX_ONE (dev schema). All queries in organization.service.ts consistently use the dev schema. Confirm whether this intentional mixed-schema approach is correct or if standardization is needed.

apps/lfx-one/src/server/controllers/analytics.controller.ts (4)

4-25: LGTM: Clean service layer delegation

The controller properly delegates to domain services (UserService and OrganizationService) following dependency injection principles.


125-147: Missing userEmail parameter in getMyProjects call

The call to this.userService.getMyProjects(page, limit) at line 133 doesn't pass the user's email. This aligns with the missing filter issue identified in user.service.ts (lines 357-441). Once that service method is updated to require userEmail, this controller method must pass it.

Update the service call:

+    const userEmail = req.oidc?.user?.['email'];
+
+    if (!userEmail) {
+      throw new AuthenticationError('User email not found in authentication context', {
+        operation: 'get_my_projects',
+      });
+    }
+
     // Parse pagination parameters
     const page = Math.max(1, parseInt(req.query['page'] as string, 10) || 1);
     const limit = Math.max(1, Math.min(100, parseInt(req.query['limit'] as string, 10) || 10));

-    const response = await this.userService.getMyProjects(page, limit);
+    const response = await this.userService.getMyProjects(userEmail, page, limit);

154-280: Consistent organization analytics pattern

The organization analytics endpoints follow a consistent pattern with proper error handling and logging. Using ANALYTICS_DEFAULTS addresses previous concerns about hardcoded values.


282-425: New organization endpoints implemented consistently

The five new organization analytics endpoints follow the established pattern. The TODO comments (lines 349, 379) about retrieving PROJECT_ID from user profile/session are appropriate reminders for future enhancement.

apps/lfx-one/src/server/services/organization.service.ts (3)

4-47: LGTM: Proper Snowflake integration

The service correctly initializes SnowflakeService and imports all necessary types for organization analytics.


337-372: Correct percentage calculation with zero-division handling

The board meeting attendance query properly handles the edge case where TOTAL_MEETINGS = 0 by returning 0% instead of causing a division error.


374-424: Well-structured event sponsorships aggregation

The two-query approach (currency aggregation + event count) is clear and maintainable. The currency grouping properly handles multi-currency sponsorships.

Consolidate 15 individual analytics endpoints into 4 optimized endpoints:
- getOrganizationContributionsOverview (maintainers + contributors + technical committee)
- getOrganizationSegmentOverview (projects participating + total commits)
- getBoardMemberDashboard (membership tier + certified employees + board attendance)
- getOrganizationEventsOverview (event attendance + event sponsorships)

Backend changes:
- Inline getEventAttendance and getEventSponsorships into getEventsOverview
- Remove 10 legacy endpoint handlers from analytics controller
- Rename private service methods for consistency (remove "Consolidated" suffix)
- Clean up JSDoc comments and simplify method documentation

Frontend changes:
- Remove 10 unused HTTP methods from analytics service
- Update organization-involvement component to use consolidated endpoints

Shared package changes:
- Remove 21 unused interfaces from analytics-data.interface.ts (~450 lines)
- Clean up legacy interfaces no longer used after consolidation

This refactor reduces codebase by ~602 lines while improving API efficiency
through consolidated database queries and parallel execution patterns.

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

Refs: LFXV2-701
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: 3

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

104-104: Consider removing the attribution comment.

The "Generated with [Claude Code]" comment is non-standard for production code and doesn't provide maintenance value. This comment also appears on lines 137, 160, and 198.

-   *
-   * Generated with [Claude Code](https://claude.ai/code)
    */
📜 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 bec3ebc and 8d2a4b5.

📒 Files selected for processing (6)
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (7 hunks)
  • apps/lfx-one/src/app/shared/services/analytics.service.ts (2 hunks)
  • apps/lfx-one/src/server/controllers/analytics.controller.ts (6 hunks)
  • apps/lfx-one/src/server/routes/analytics.route.ts (1 hunks)
  • apps/lfx-one/src/server/services/organization.service.ts (2 hunks)
  • packages/shared/src/interfaces/analytics-data.interface.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • apps/lfx-one/src/app/shared/services/analytics.service.ts
  • apps/lfx-one/src/server/services/organization.service.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
  • apps/lfx-one/src/server/routes/analytics.route.ts
  • packages/shared/src/interfaces/analytics-data.interface.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Include required license headers on all source files

Files:

  • apps/lfx-one/src/app/shared/services/analytics.service.ts
  • apps/lfx-one/src/server/services/organization.service.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
  • apps/lfx-one/src/server/routes/analytics.route.ts
  • packages/shared/src/interfaces/analytics-data.interface.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • apps/lfx-one/src/app/shared/services/analytics.service.ts
  • apps/lfx-one/src/server/services/organization.service.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
  • apps/lfx-one/src/server/routes/analytics.route.ts
  • packages/shared/src/interfaces/analytics-data.interface.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
packages/shared/src/interfaces/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • packages/shared/src/interfaces/analytics-data.interface.ts
🧠 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/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
🧬 Code graph analysis (4)
apps/lfx-one/src/app/shared/services/analytics.service.ts (1)
packages/shared/src/interfaces/analytics-data.interface.ts (4)
  • OrganizationContributionsOverviewResponse (272-306)
  • OrganizationSegmentOverviewResponse (312-332)
  • BoardMemberDashboardResponse (338-377)
  • OrganizationEventsOverviewResponse (385-416)
apps/lfx-one/src/server/services/organization.service.ts (3)
apps/lfx-one/src/server/services/snowflake.service.ts (1)
  • SnowflakeService (26-400)
packages/shared/src/interfaces/analytics-data.interface.ts (9)
  • OrganizationContributionsOverviewResponse (272-306)
  • BoardMemberDashboardResponse (338-377)
  • OrganizationSegmentOverviewResponse (312-332)
  • OrganizationEventsOverviewResponse (385-416)
  • OrganizationEventAttendanceRow (192-198)
  • OrganizationEventSponsorshipsAggregateRow (423-444)
  • OrganizationContributionsConsolidatedRow (233-249)
  • SegmentContributionsConsolidatedRow (256-266)
  • BoardMemberDashboardConsolidatedRow (205-226)
apps/lfx-one/src/server/errors/index.ts (1)
  • ResourceNotFoundError (7-7)
apps/lfx-one/src/server/controllers/analytics.controller.ts (3)
apps/lfx-one/src/server/services/user.service.ts (1)
  • UserService (33-511)
apps/lfx-one/src/server/services/organization.service.ts (1)
  • OrganizationService (28-326)
packages/shared/src/constants/analytics.constants.ts (1)
  • ANALYTICS_DEFAULTS (8-26)
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (3)
packages/shared/src/constants/organization-involvement.constants.ts (3)
  • CONTRIBUTIONS_METRICS (66-87)
  • IMPACT_METRICS (93-114)
  • PRIMARY_INVOLVEMENT_METRICS (20-60)
packages/shared/src/interfaces/dashboard.interface.ts (2)
  • PrimaryInvolvementMetric (63-88)
  • OrganizationInvolvementMetricWithChart (124-167)
packages/shared/src/utils/color.utils.ts (1)
  • hexToRgba (28-56)
⏰ 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: build-and-push
🔇 Additional comments (3)
apps/lfx-one/src/app/shared/services/analytics.service.ts (3)

1-16: LGTM!

The license header and imports are properly structured. The new consolidated response interfaces are correctly imported from the shared package.


109-127: Verify that silent error handling is intentional.

All four new methods silently catch errors and return fallback defaults (zeros/empty strings). While this provides UI resilience, callers cannot distinguish between "no data available" and "request failed", potentially causing misleading UX where errors appear as empty dashboards.

This pattern is consistent with existing methods in the service (e.g., getActiveWeeksStreak, getPullRequestsMerged), suggesting it may be an intentional design choice. Please confirm:

  1. Is this the desired error handling strategy for analytics data?
  2. Should the UI layer handle these scenarios differently (e.g., show a loading skeleton vs. "no data" state)?

Also applies to: 142-150, 165-188, 203-219


139-152: LGTM! Consolidated endpoints follow consistent patterns.

The three new methods (getOrganizationSegmentOverview, getBoardMemberDashboard, getOrganizationEventsOverview) are well-implemented:

  • Consistent method signatures with optional accountId parameters
  • Proper TypeScript interfaces for type safety
  • Fallback defaults correctly match interface structures
  • Clear documentation describing the consolidated nature of these endpoints
  • Follows the established pattern from existing analytics methods

The consolidation approach should reduce API roundtrips and improve performance as documented.

Also applies to: 162-190, 200-221

andrest50
andrest50 previously approved these changes Nov 4, 2025
LFXV2-701

- Refactor SQL queries to use CTE base with LEFT JOINs instead of anchoring on specific tables
- This fixes 404 errors when organizations have partial data (e.g., contributors but no maintainers)
- Remove MEMBERSHIP_PRICE/annual fee field from backend, shared interfaces, and frontend
- Update membership tier card layout to show three clear rows: Tier, Member Since, and Renewal Date

Signed-off-by: Asitha de Silva <asithade@gmail.com>
@asithade asithade merged commit 2a98ab7 into main Nov 4, 2025
5 of 6 checks passed
@asithade asithade deleted the feat/LFXV2-701 branch November 4, 2025 17:05
@github-actions
Copy link

github-actions bot commented Nov 4, 2025

🧹 Deployment Removed

The deployment for PR #140 has been removed.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants