-
Notifications
You must be signed in to change notification settings - Fork 0
feat(dashboards): add board member persona with snowflake integration #134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit 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. WalkthroughAdds a "board-member" persona and dashboard with new UI components (organization involvement, foundation health, health‑score tag), account context service, client/server organization analytics endpoints, shared constants/interfaces/utils (including color helpers and mock foundation data), Snowflake service and lock-manager updates, and a cSpell word addition. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant UI as Board‑Member Dashboard (UI)
participant BoardComp as BoardMemberDashboardComponent
participant OrgComp as OrganizationInvolvementComponent
participant AnalyticsSvc as AnalyticsService (client)
participant API as AnalyticsController (server)
participant DB as Snowflake
UI->>BoardComp: mount
BoardComp->>OrgComp: render(selected account)
OrgComp->>AnalyticsSvc: request organization analytics
AnalyticsSvc->>API: GET /api/analytics/organization-*
API->>DB: execute queries
DB-->>API: rows
API-->>AnalyticsSvc: JSON responses
AnalyticsSvc-->>OrgComp: observables (or defaults)
OrgComp->>OrgComp: compute metrics & chart datasets
OrgComp-->>BoardComp: present metrics & charts
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro Disabled knowledge base sources:
📒 Files selected for processing (1)
🧰 Additional context used📓 Path-based instructions (3)**/*.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*.{ts,tsx,js,jsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧬 Code graph analysis (1)apps/lfx-one/src/server/services/snowflake.service.ts (2)
⏰ 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)
🔇 Additional comments (6)
Comment |
There was a problem hiding this 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 implements a comprehensive Board Member persona dashboard with three main components: Organization Involvement, Foundation Health, and Pending Actions. The implementation integrates with Snowflake for real-time data retrieval and provides board members with visibility into their organization's engagement and foundation ecosystem health.
Key Changes:
- Added Board Member persona with Snowflake-backed Organization Involvement metrics
- Implemented Foundation Health monitoring across multiple foundations
- Extended analytics service with organization maintainers and membership tier endpoints
Reviewed Changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/shared/src/interfaces/persona.interface.ts | Added 'board-member' to PersonaType union |
| packages/shared/src/interfaces/dashboard.interface.ts | Added comprehensive interfaces for organization involvement and foundation health metrics |
| packages/shared/src/interfaces/analytics-data.interface.ts | Added OrganizationMaintainersResponse and MembershipTierResponse interfaces |
| packages/shared/src/constants/persona.constants.ts | Added board member persona configuration |
| packages/shared/src/constants/organization-involvement.constants.ts | New file with primary involvement, contribution, and impact metric constants |
| packages/shared/src/constants/foundation-health.constants.ts | New file with foundation health data and mock metrics |
| packages/shared/src/constants/action-items.constants.ts | Added board member-specific action items |
| apps/lfx-one/src/server/routes/analytics.route.ts | Added routes for organization maintainers and membership tier |
| apps/lfx-one/src/server/controllers/analytics.controller.ts | Implemented Snowflake query methods for organization metrics |
| apps/lfx-one/src/app/shared/services/analytics.service.ts | Added frontend service methods for new analytics endpoints |
| apps/lfx-one/src/app/modules/dashboards/dashboard.component.ts | Integrated BoardMemberDashboardComponent |
| apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/* | New component with Snowflake integration and Chart.js sparklines |
| apps/lfx-one/src/app/modules/dashboards/components/foundation-health/* | New component displaying foundation health metrics table |
| apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/* | New reusable component for health score badges |
| apps/lfx-one/src/app/modules/dashboards/board-member/* | New board member dashboard component with three-column layout |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
...modules/dashboards/components/organization-involvement/organization-involvement.component.ts
Outdated
Show resolved
Hide resolved
...x-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (4)
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (1)
155-164: Consider adding input validation.The
hexToRgbamethod assumes valid hex format. While colors currently come from constants, adding defensive validation would improve robustness.Apply this diff to add validation:
private hexToRgba(hex: string, alpha: number): string { + if (!hex || !hex.match(/^#[0-9A-Fa-f]{6}$/)) { + console.warn(`Invalid hex color: ${hex}`); + return `rgba(0, 0, 0, ${alpha})`; + } const r = parseInt(hex.slice(1, 3), 16); const g = parseInt(hex.slice(3, 5), 16); const b = parseInt(hex.slice(5, 7), 16); return `rgba(${r}, ${g}, ${b}, ${alpha})`; }apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts (1)
12-49: Consider extracting chart data structures to reusable types.The inline chart data structure definitions (lines 18-41) are verbose and duplicated. If Chart.js types are available in your project, consider referencing them directly. Alternatively, extract a shared
SparklineChartDatainterface to improve maintainability.Example refactor:
interface SparklineChartData { labels: string[]; datasets: { data: number[]; borderColor: string; backgroundColor: string; fill: boolean; tension: number; borderWidth: number; pointRadius: number; }[]; } interface FoundationDisplay extends Foundation { softwareValueFormatted: string; totalMembersFormatted: string; activeContributorsAvg: string; maintainersAvg: string; eventsTotal: number; activeContributorsChartData: SparklineChartData; maintainersChartData: SparklineChartData; // ... rest of fields }packages/shared/src/interfaces/dashboard.interface.ts (2)
59-88: Consider using discriminated unions for better type safety.The
PrimaryInvolvementMetricinterface uses many optional fields to handle both regular metrics and membership tier metrics. A discriminated union would provide better type safety and clearer intent.Example refactor:
interface BasePrimaryInvolvementMetric { title: string; value: string; subtitle: string; } interface RegularMetric extends BasePrimaryInvolvementMetric { type: 'regular'; icon: string; sparklineData?: number[]; sparklineColor?: string; chartType?: 'bar' | 'line'; } interface MembershipTierMetric extends BasePrimaryInvolvementMetric { type: 'membershipTier'; tier: string; tierSince: string; annualFee: string; nextDue: string; } type PrimaryInvolvementMetric = RegularMetric | MembershipTierMetric;
116-161: Consider extracting the chart data structure to a reusable type.The inline
chartDatastructure (lines 130-150) is verbose and could be reused across multiple interfaces. Consider extracting it to a shared type.Example:
export interface SparklineChartDataset { data: number[]; borderColor: string; backgroundColor: string; fill: boolean; tension: number; borderWidth: number; pointRadius: number; } export interface SparklineChartData { labels: string[]; datasets: SparklineChartDataset[]; } export interface OrganizationInvolvementMetricWithChart { title: string; value: string; subtitle: string; icon: string; chartData?: SparklineChartData; // ... rest of fields }
📜 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.
📒 Files selected for processing (27)
.vscode/settings.json(1 hunks)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.scss(1 hunks)apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.html(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.scss(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.html(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.scss(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.ts(1 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.scss(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.ts(2 hunks)apps/lfx-one/src/app/modules/dashboards/dashboard.component.html(1 hunks)apps/lfx-one/src/app/modules/dashboards/dashboard.component.ts(2 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/constants/action-items.constants.ts(1 hunks)packages/shared/src/constants/foundation-health.constants.ts(1 hunks)packages/shared/src/constants/index.ts(1 hunks)packages/shared/src/constants/organization-involvement.constants.ts(1 hunks)packages/shared/src/constants/persona.constants.ts(1 hunks)packages/shared/src/interfaces/analytics-data.interface.ts(1 hunks)packages/shared/src/interfaces/dashboard.interface.ts(1 hunks)packages/shared/src/interfaces/persona.interface.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use TypeScript interfaces instead of union types for better maintainability
When defining PrimeNG-related types, reference the official PrimeNG component interfaces
Files:
apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.tspackages/shared/src/interfaces/analytics-data.interface.tspackages/shared/src/constants/action-items.constants.tspackages/shared/src/constants/index.tspackages/shared/src/interfaces/persona.interface.tsapps/lfx-one/src/app/shared/services/analytics.service.tsapps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.tspackages/shared/src/constants/persona.constants.tspackages/shared/src/constants/foundation-health.constants.tspackages/shared/src/interfaces/dashboard.interface.tsapps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.tsapps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.tsapps/lfx-one/src/app/modules/dashboards/dashboard.component.tspackages/shared/src/constants/organization-involvement.constants.tsapps/lfx-one/src/server/controllers/analytics.controller.tsapps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.tsapps/lfx-one/src/server/routes/analytics.route.ts
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}
📄 CodeRabbit inference engine (CLAUDE.md)
Include required license headers on all source files
Files:
apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.tsapps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.scsspackages/shared/src/interfaces/analytics-data.interface.tsapps/lfx-one/src/app/modules/dashboards/dashboard.component.htmlpackages/shared/src/constants/action-items.constants.tspackages/shared/src/constants/index.tspackages/shared/src/interfaces/persona.interface.tsapps/lfx-one/src/app/shared/services/analytics.service.tsapps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.tsapps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.scsspackages/shared/src/constants/persona.constants.tspackages/shared/src/constants/foundation-health.constants.tspackages/shared/src/interfaces/dashboard.interface.tsapps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.scssapps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.tsapps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.htmlapps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.tsapps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.htmlapps/lfx-one/src/app/modules/dashboards/dashboard.component.tsapps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.htmlpackages/shared/src/constants/organization-involvement.constants.tsapps/lfx-one/src/server/controllers/analytics.controller.tsapps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.tsapps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.htmlapps/lfx-one/src/server/routes/analytics.route.tsapps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.scss
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not nest ternary expressions
Files:
apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.tspackages/shared/src/interfaces/analytics-data.interface.tspackages/shared/src/constants/action-items.constants.tspackages/shared/src/constants/index.tspackages/shared/src/interfaces/persona.interface.tsapps/lfx-one/src/app/shared/services/analytics.service.tsapps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.tspackages/shared/src/constants/persona.constants.tspackages/shared/src/constants/foundation-health.constants.tspackages/shared/src/interfaces/dashboard.interface.tsapps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.tsapps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.tsapps/lfx-one/src/app/modules/dashboards/dashboard.component.tspackages/shared/src/constants/organization-involvement.constants.tsapps/lfx-one/src/server/controllers/analytics.controller.tsapps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.tsapps/lfx-one/src/server/routes/analytics.route.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.tspackages/shared/src/interfaces/persona.interface.tspackages/shared/src/interfaces/dashboard.interface.ts
apps/lfx-one/src/**/*.html
📄 CodeRabbit inference engine (CLAUDE.md)
apps/lfx-one/src/**/*.html: Always add data-testid attributes when creating new Angular components for reliable test targeting
Use data-testid naming convention [section]-[component]-[element]
Files:
apps/lfx-one/src/app/modules/dashboards/dashboard.component.htmlapps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.htmlapps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.htmlapps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.htmlapps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.html
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/action-items.constants.tspackages/shared/src/constants/index.tspackages/shared/src/constants/persona.constants.tspackages/shared/src/constants/foundation-health.constants.tspackages/shared/src/constants/organization-involvement.constants.ts
**/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
🧬 Code graph analysis (10)
apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.ts (1)
packages/shared/src/constants/action-items.constants.ts (1)
BOARD_MEMBER_ACTION_ITEMS(69-86)
packages/shared/src/constants/action-items.constants.ts (1)
packages/shared/src/interfaces/components.interface.ts (1)
PendingActionItem(336-349)
apps/lfx-one/src/app/shared/services/analytics.service.ts (1)
packages/shared/src/interfaces/analytics-data.interface.ts (2)
OrganizationMaintainersResponse(184-199)MembershipTierResponse(205-235)
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (3)
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (1)
Component(10-16)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 (1)
OrganizationInvolvementMetricWithChart(120-161)
packages/shared/src/constants/foundation-health.constants.ts (1)
packages/shared/src/interfaces/dashboard.interface.ts (1)
Foundation(222-251)
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts (3)
packages/shared/src/interfaces/dashboard.interface.ts (2)
Foundation(222-251)OrgDependencyRiskLevel(173-173)apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.ts (1)
Component(8-42)packages/shared/src/constants/foundation-health.constants.ts (1)
FOUNDATION_HEALTH_DATA(31-161)
apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.ts (2)
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts (1)
Component(51-231)packages/shared/src/interfaces/dashboard.interface.ts (1)
FoundationHealthScore(167-167)
packages/shared/src/constants/organization-involvement.constants.ts (1)
packages/shared/src/interfaces/dashboard.interface.ts (3)
PrimaryInvolvementMetric(63-88)ContributionMetric(94-101)ImpactMetric(107-114)
apps/lfx-one/src/server/controllers/analytics.controller.ts (2)
packages/shared/src/interfaces/analytics-data.interface.ts (2)
OrganizationMaintainersResponse(184-199)MembershipTierResponse(205-235)apps/lfx-one/src/server/errors/index.ts (1)
ResourceNotFoundError(7-7)
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (4)
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts (1)
Component(51-231)apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (1)
Component(12-164)apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.ts (1)
Component(12-49)apps/lfx-one/src/app/modules/dashboards/dashboard.component.ts (1)
Component(17-34)
🔇 Additional comments (41)
.vscode/settings.json (1)
28-28: Appropriate spell-check vocabulary update.Adding "sparkline" to the
cSpell.wordsvocabulary is a proper housekeeping change that aligns with the introduction of sparkline chart terminology throughout the new dashboard components in this PR. The word is correctly placed in alphabetical order.apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.scss (1)
1-6: LGTM!The license header is correct, and the inline-block display is appropriate for a tag component.
apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.html (1)
1-6: LGTM!The template correctly implements data-testid attributes following the required naming convention and uses proper Angular bindings.
packages/shared/src/constants/action-items.constants.ts (1)
66-86: LGTM!The new board member action items follow the established pattern and correctly implement the PendingActionItem interface with appropriate values for the board-member persona.
packages/shared/src/constants/foundation-health.constants.ts (2)
13-25: LGTM!The helper function correctly generates smooth time-series data with appropriate clamping and rounding for realistic trend visualization.
31-161: LGTM!The foundation health mock data is well-structured with appropriate time-series data points (365 daily, 12 monthly) and varied health scores for comprehensive UI testing.
apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.ts (2)
8-8: LGTM!The import correctly adds the board member action items from the shared constants package.
34-35: LGTM!The board-member case is correctly integrated into the existing persona-based action item selection pattern.
apps/lfx-one/src/app/modules/dashboards/dashboard.component.html (1)
11-13: LGTM!The board-member dashboard case is correctly integrated into the existing persona-based routing pattern.
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.scss (1)
1-2: LGTM!The license header is correctly included per coding guidelines.
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.scss (1)
1-2: LGTM!The license header is correctly included per coding guidelines.
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.scss (1)
1-6: LGTM!The stylesheet includes the required license header and follows Angular best practices with a minimal host selector rule.
packages/shared/src/interfaces/persona.interface.ts (1)
8-8: LGTM!The addition of 'board-member' to the PersonaType union is appropriate and aligns with the PR objectives. String literal unions are the idiomatic TypeScript pattern for enumeration types like this.
apps/lfx-one/src/app/modules/dashboards/dashboard.component.ts (1)
9-9: LGTM!The import follows the coding guideline to use direct imports rather than barrel exports for standalone components. The change correctly integrates the new board member dashboard component.
Also applies to: 20-20
packages/shared/src/constants/index.ts (1)
20-21: LGTM!The new constant exports follow the established pattern in this index file and are appropriate for a shared constants package.
packages/shared/src/constants/persona.constants.ts (1)
25-29: LGTM!The new board member persona option is structured consistently with existing options and aligns with the expanded PersonaType union.
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.html (1)
1-22: LGTM!The template follows all coding guidelines:
- Includes required license header
- Uses data-testid attributes for reliable test targeting
- Implements responsive layout with Tailwind CSS
- Clean, maintainable structure
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (1)
1-16: LGTM! Clean container component implementation.The component follows Angular best practices by delegating all logic to child components. The empty class body is appropriate for a pure container component.
packages/shared/src/interfaces/analytics-data.interface.ts (2)
180-199: LGTM! Well-documented interface.The interface is properly structured with appropriate types and comprehensive JSDoc documentation.
201-235: LGTM! Well-documented interface.The interface properly defines membership tier data with clear documentation, including date format specifications.
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.html (3)
4-17: LGTM! Good loading state implementation.The loading indicator provides clear feedback to users with both a spinner and descriptive message.
20-80: LGTM! Well-structured responsive grid.The template properly handles different metric types (membership tier vs regular) with appropriate conditional rendering and null-safe chart display.
82-116: LGTM! Clean secondary metrics layout.The contribution and impact metrics are properly structured with helpful tooltips and test attributes for reliable testing.
apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.ts (2)
1-34: LGTM! Type-safe score tag implementation.The component properly uses
input.requiredfor type safety and provides a complete mapping of score levels to CSS classes.
36-42: LGTM! Simple and effective label formatting.The capitalization logic correctly transforms score values for display.
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (3)
1-37: LGTM! Modern Angular reactive patterns.The component effectively uses Angular 19 signals and
toSignalfor reactive data management with a unified loading state.
39-60: LGTM! Appropriate sparkline configuration.The chart options correctly configure minimalist sparklines by disabling unnecessary UI elements.
62-153: LGTM! Robust data merging with null-safety.The computed signal properly handles data from multiple sources with appropriate null-checks and fallback to placeholder data when real data is unavailable.
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.html (3)
4-73: LGTM! Well-structured table with good UX.The table header properly implements sticky columns and helpful tooltips for metric explanations.
74-155: LGTM! Comprehensive foundation metrics display.The template properly handles different data structures with conditional rendering and effectively uses child components for visualizations.
157-178: LGTM! Effective risk visualization.The organization dependency visualization clearly communicates risk levels through color-coding and detailed metrics.
packages/shared/src/constants/organization-involvement.constants.ts (3)
6-14: LGTM! Effective trend data generator.The helper function creates realistic-looking trend data for placeholder sparklines with both linear trend and random variation.
16-60: LGTM! Well-documented placeholder metrics.The constants clearly indicate which values are placeholders to be replaced with real Snowflake data, and provide appropriate sparkline data for visualization.
62-114: LGTM! Clear metric definitions with helpful tooltips.Both contribution and impact metrics are well-structured with descriptive tooltips that explain each metric's meaning.
apps/lfx-one/src/server/controllers/analytics.controller.ts (2)
344-393: LGTM with a note on consistency.The method properly uses parameterized queries and parallel execution for efficiency. The TODO comment appropriately flags the hardcoded
accountIdfor future resolution.Note: Unlike other methods in this controller, this endpoint returns zeros when no data is found rather than throwing a
ResourceNotFoundError. This may be intentional for the board member dashboard use case, but consider documenting this behavior.
395-469: LGTM! Secure and well-structured endpoint.The method properly uses parameterized queries, handles missing data with appropriate 404 errors, and includes a reasonable transformation of tier names. The TODO comment appropriately flags hardcoded IDs for future resolution.
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts (4)
71-89: LGTM - Computed signal is well-structured.The computed foundations signal appropriately filters and transforms the data with good separation of concerns through helper methods. The computation should perform well for the expected data volumes (15 foundations based on the constants file).
152-164: LGTM - Good defensive programming.The edge case handling (lines 158-160) for when all values are equal prevents division by zero and ensures consistent rendering. The minimum height of 10% ensures bars remain visible.
214-220: LGTM - Pie chart angle calculation is correct.The conversion
topPercentage * 3.6correctly maps percentage (0-100) to degrees (0-360), and the two slices properly divide the circle based on the organization dependency percentage.
107-230: LGTM - Helper methods are well-implemented.All helper methods follow good practices:
- Proper use of
Recordtypes for risk level mappings (lines 170-174, 182-186)- Correct mathematical transformations for charts and SVG paths
- Appropriate number formatting and calculations
packages/shared/src/interfaces/dashboard.interface.ts (1)
90-114: LGTM - Well-designed and documented interfaces.The interfaces are clearly structured with appropriate JSDoc documentation. The use of optional vs required fields is well-considered (e.g.,
projectCountandprojectBreakdownbeing optional inFoundationto handle different foundation types).Also applies to: 175-251
🚀 Deployment StatusYour branch has been deployed to: https://ui-pr-134.dev.v2.cluster.linuxfound.info Deployment Details:
The deployment will be automatically removed when this PR is closed. |
There was a problem hiding this 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
♻️ Duplicate comments (6)
packages/shared/src/utils/color.utils.ts (1)
28-55: Good extraction and strict validation.Centralizing hexToRgba with format and alpha checks resolves prior duplication and avoids rgba(NaN,…) pitfalls. Nice.
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts (1)
9-9: Nice reuse of shared color util.Importing hexToRgba resolves the earlier duplication concern.
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (1)
271-279: Avoid throwing whensparklineColoris missing/invalid.
hexToRgba('')throws. Add a guard with a safe fallback.- backgroundColor: hexToRgba(metric.sparklineColor ?? '', 0.1), + backgroundColor: isValidHexColor(metric.sparklineColor ?? '') + ? hexToRgba(metric.sparklineColor as string, 0.1) + : 'rgba(0, 148, 255, 0.1)',apps/lfx-one/src/server/routes/analytics.route.ts (1)
17-21: Route definitions look correct.The new routes follow the existing pattern and are properly integrated. The authorization concern regarding hardcoded organization context in the controllers has already been flagged in the past review.
apps/lfx-one/src/app/shared/services/analytics.service.ts (1)
99-188: Silent error handling masks failures (already flagged).The error handling pattern in these organization-scoped methods returns default empty values, which masks authentication, authorization, and network failures. This issue was comprehensively identified in the previous review.
apps/lfx-one/src/server/controllers/analytics.controller.ts (1)
352-612: Hardcoded organization identifiers (already flagged).All five new controller methods use hardcoded
ACCOUNT_IDandPROJECT_IDvalues instead of extracting them from the authenticated user context. This prevents proper authorization and multi-tenant isolation, as comprehensively identified in the previous review on the routes file.
🧹 Nitpick comments (9)
packages/shared/src/utils/color.utils.ts (1)
9-13: Hoist the regex to a module constant (optional), consider 4/8‑digit hex support.Avoid re-allocating the regex per call and optionally accept #RGBA/#RRGGBBAA if you plan to support embedded alpha.
Apply:
+// Match 3- or 6-digit hex color with # prefix +const HEX_COLOR_REGEX = /^#(?:[A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/; + export function isValidHexColor(hex: string): boolean { - // Match 3-digit or 6-digit hex color with # prefix - const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/; - return hexRegex.test(hex); + return HEX_COLOR_REGEX.test(hex); }packages/shared/src/utils/index.ts (1)
4-4: Confirm barrel export policy for index.ts in utils.Guideline states “Do not use barrel exports; always use direct imports for standalone components.” Since this is a utils index, confirm if barrels are allowed here. If not, remove this re‑export and import from '.../utils/color.utils' directly.
As per coding guidelines.
packages/shared/src/interfaces/dashboard.interface.ts (2)
173-174: Replace string unions with enums for maintainability.Prefer enums (or interface-backed constants) over unions to align with the codebase standard and ease refactors.
Apply:
-export type FoundationHealthScore = 'excellent' | 'healthy' | 'stable' | 'unsteady' | 'critical'; +export enum FoundationHealthScore { + Excellent = 'excellent', + Healthy = 'healthy', + Stable = 'stable', + Unsteady = 'unsteady', + Critical = 'critical', +} -export type OrgDependencyRiskLevel = 'low' | 'moderate' | 'high'; +export enum OrgDependencyRiskLevel { + Low = 'low', + Moderate = 'moderate', + High = 'high', +}Note: Update usages (e.g., inputs and maps) accordingly.
As per coding guidelines.
Also applies to: 179-180
131-133: Makeiconoptional to match actual usage.You often pass
metric.icon ?? ''. Model this in the type to avoid empty strings.- /** Icon class for the metric */ - icon: string; + /** Icon class for the metric (optional for membership tier) */ + icon?: string;apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts (2)
153-165: Handle empty input incalculateBarHeights.
Math.max(...[])→ -Infinity andMath.min(...[])→ Infinity; downstream math yields NaN.- private calculateBarHeights(data: number[]): number[] { + private calculateBarHeights(data: number[]): number[] { + if (!data.length) return []; const maxValue = Math.max(...data); const minValue = Math.min(...data); const range = maxValue - minValue; return data.map((value) => { if (range === 0) { return 50; } const heightPercent = ((value - minValue) / range) * 100; return Math.max(heightPercent, 10); }); }
215-221: ClamptopPercentageto [0, 100] for pie paths.Prevents negative/overflow angles if upstream data is out of range.
- private createPieChartPaths(topPercentage: number): { otherPath: string; topPath: string } { - const otherAngle = 360 - topPercentage * 3.6; + private createPieChartPaths(topPercentage: number): { otherPath: string; topPath: string } { + const pct = Math.max(0, Math.min(100, topPercentage)); + const otherAngle = 360 - pct * 3.6; return { otherPath: this.createPieSlice(0, otherAngle), topPath: this.createPieSlice(otherAngle, 360), }; }apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (3)
19-19: ImportisValidHexColorto guard conversions (used below).To avoid exceptions when colors are missing/invalid.
-import { hexToRgba } from '@lfx-one/shared/utils'; +import { hexToRgba, isValidHexColor } from '@lfx-one/shared/utils';
184-196: Use translucent fill for consistency with other charts.Align backgroundColor with shared hexToRgba for a lighter area fill.
datasets: [ { data: metric.sparklineData ?? [], borderColor: metric.sparklineColor ?? '', - backgroundColor: metric.sparklineColor ?? '', + backgroundColor: hexToRgba(metric.sparklineColor ?? '#0094FF', 0.1), fill: true, tension: 0.4, borderWidth: 2, pointRadius: 0, }, ],
212-224: Same translucent fill for Maintainers.Keep styling consistent across primary metrics.
datasets: [ { data: metric.sparklineData ?? [], borderColor: metric.sparklineColor ?? '', - backgroundColor: metric.sparklineColor ?? '', + backgroundColor: hexToRgba(metric.sparklineColor ?? '#0094FF', 0.1), fill: true, tension: 0.4, borderWidth: 2, pointRadius: 0, }, ],
📜 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.
📒 Files selected for processing (10)
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts(1 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(1 hunks)apps/lfx-one/src/app/shared/services/analytics.service.ts(2 hunks)apps/lfx-one/src/server/controllers/analytics.controller.ts(3 hunks)apps/lfx-one/src/server/routes/analytics.route.ts(1 hunks)packages/shared/src/interfaces/analytics-data.interface.ts(1 hunks)packages/shared/src/interfaces/dashboard.interface.ts(1 hunks)packages/shared/src/utils/color.utils.ts(1 hunks)packages/shared/src/utils/index.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.html
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{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/utils/color.utils.tsapps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.tsapps/lfx-one/src/server/routes/analytics.route.tspackages/shared/src/utils/index.tspackages/shared/src/interfaces/dashboard.interface.tsapps/lfx-one/src/server/controllers/analytics.controller.tspackages/shared/src/interfaces/analytics-data.interface.tsapps/lfx-one/src/app/shared/services/analytics.service.tsapps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.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:
packages/shared/src/utils/color.utils.tsapps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.tsapps/lfx-one/src/server/routes/analytics.route.tspackages/shared/src/utils/index.tspackages/shared/src/interfaces/dashboard.interface.tsapps/lfx-one/src/server/controllers/analytics.controller.tspackages/shared/src/interfaces/analytics-data.interface.tsapps/lfx-one/src/app/shared/services/analytics.service.tsapps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not nest ternary expressions
Files:
packages/shared/src/utils/color.utils.tsapps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.tsapps/lfx-one/src/server/routes/analytics.route.tspackages/shared/src/utils/index.tspackages/shared/src/interfaces/dashboard.interface.tsapps/lfx-one/src/server/controllers/analytics.controller.tspackages/shared/src/interfaces/analytics-data.interface.tsapps/lfx-one/src/app/shared/services/analytics.service.tsapps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts
**/index.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Do not use barrel exports; always use direct imports for standalone components
Files:
packages/shared/src/utils/index.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/dashboard.interface.tspackages/shared/src/interfaces/analytics-data.interface.ts
🧬 Code graph analysis (4)
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (5)
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (1)
Component(10-16)packages/shared/src/interfaces/dashboard.interface.ts (4)
ContributionMetric(94-103)ImpactMetric(109-118)OrganizationInvolvementMetricWithChart(124-167)PrimaryInvolvementMetric(63-88)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 (3)
OrganizationContributorsResponse(241-261)OrganizationMaintainersResponse(184-199)MembershipTierResponse(205-235)packages/shared/src/utils/color.utils.ts (1)
hexToRgba(28-56)
apps/lfx-one/src/server/controllers/analytics.controller.ts (2)
packages/shared/src/interfaces/analytics-data.interface.ts (11)
ProjectCountRow(307-309)MemberDashboardMaintainersRow(267-272)OrganizationMaintainersResponse(184-199)MembershipTierRow(278-290)MembershipTierResponse(205-235)OrganizationContributorsRow(296-301)OrganizationContributorsResponse(241-261)OrganizationEventAttendanceRow(328-334)OrganizationEventAttendanceResponse(340-365)OrganizationTechnicalCommitteeRow(381-385)OrganizationTechnicalCommitteeResponse(391-406)apps/lfx-one/src/server/errors/index.ts (1)
ResourceNotFoundError(7-7)
apps/lfx-one/src/app/shared/services/analytics.service.ts (1)
packages/shared/src/interfaces/analytics-data.interface.ts (5)
OrganizationMaintainersResponse(184-199)OrganizationContributorsResponse(241-261)MembershipTierResponse(205-235)OrganizationEventAttendanceResponse(340-365)OrganizationTechnicalCommitteeResponse(391-406)
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts (4)
packages/shared/src/interfaces/dashboard.interface.ts (2)
Foundation(228-257)OrgDependencyRiskLevel(179-179)apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.ts (1)
Component(8-42)packages/shared/src/constants/foundation-health.constants.ts (1)
FOUNDATION_HEALTH_DATA(31-161)packages/shared/src/utils/color.utils.ts (1)
hexToRgba(28-56)
🔇 Additional comments (1)
packages/shared/src/interfaces/analytics-data.interface.ts (1)
180-406: Well-structured interface definitions.The new analytics interfaces follow consistent patterns: Row interfaces use SCREAMING_SNAKE_CASE for Snowflake raw data, while Response interfaces use camelCase for API contracts. All interfaces are properly documented with JSDoc comments and follow the coding guidelines.
...x-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts
Show resolved
Hide resolved
Implement Board Member persona dashboard with three key components: - Organization Involvement with Snowflake integration - Foundation Health metrics - Pending Actions (persona-aware) Backend changes: - Add organization maintainers endpoint - Add membership tier endpoint - Integrate Snowflake queries with proper error handling Frontend changes: - Create board-member-dashboard component - Create organization-involvement component with loading state - Create foundation-health component - Create health-score-tag component - Add persona routing and navigation Shared package updates: - Add OrganizationMaintainersResponse interface - Add MembershipTierResponse interface - Add organization involvement constants - Add foundation health constants - Update persona configuration LFXV2-687 Generated with [Claude Code](https://claude.ai/code) Signed-off-by: Asitha de Silva <asithade@gmail.com>
- Add organization contributors, event attendance, and technical committee endpoints - Implement visual connection status indicators for live vs placeholder data - Update bar charts for Active Contributors and Maintainers with solid fills and rounded corners - Refactor membership tier to use consolidated dashboard table - Create shared color utility functions with validation - Add comprehensive TypeScript interfaces for Snowflake data LFXV2-687 Signed-off-by: Asitha de Silva <asithade@gmail.com>
Add dynamic organization selection dropdown to board member dashboard that allows users to filter analytics data by different organizations. The dropdown displays 12 predefined organizations and persists the selection to localStorage. Key changes: - Add Account interface and constants with 12 organizations - Create AccountContextService to manage selected organization state - Add organization dropdown to board member dashboard header - Update analytics service methods to accept optional accountId parameter - Modify backend analytics controller to read accountId from query params - Fix reactive data flow using toObservable and RxJS operators - Update membership tier to use correct Snowflake column names (CURRENT_MEMBERSHIP_START_DATE, CURRENT_MEMBERSHIP_END_DATE) The implementation uses Angular signals for reactive state management, automatically refreshing all dashboard metrics when organization changes. Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Jordan Evans <jevans@linuxfoundation.org>
b4a9520 to
f130ddd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (2)
apps/lfx-one/src/app/shared/services/analytics.service.ts (1)
99-198: Error handling pattern is consistent with existing methods.All five new organization analytics methods follow the established error-handling pattern of returning default empty values on failure. As noted in previous reviews, this pattern masks authentication, authorization, network, and backend errors by making them indistinguishable from legitimate empty data.
Since this pattern is consistent with the existing methods in this service (lines 30-94), the trade-off between consistency and error visibility appears intentional. However, for organization-scoped endpoints that require authorization, consider whether proper error propagation would provide better UX for distinguishing between "no data" and "access denied" scenarios.
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts (1)
126-128: Guard against empty arrays incalculateAverage.This issue was previously flagged: when
data.length === 0, the division results inNaN. Add a guard to return a sensible default (e.g., 0) before performing the calculation.Apply this diff to fix:
private calculateAverage(data: number[]): number { + if (!data.length) return 0; return Math.round(data.reduce((sum, val) => sum + val, 0) / data.length); }
🧹 Nitpick comments (5)
packages/shared/src/constants/accounts.constants.ts (1)
10-32: Consider whether account data should be fetched dynamically.The hardcoded list of 12 organizations with Salesforce account IDs creates a maintenance burden if accounts are added, removed, or updated. Any changes to organization names or account IDs will require code modifications and redeployment.
Consider whether this data should be:
- Fetched from a backend endpoint (recommended if the list changes periodically)
- Kept as hardcoded constants (acceptable if the list is truly static and managed by board governance)
If hardcoding is intentional for a fixed board member roster, this is acceptable but should be documented as such.
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (1)
32-38: Consider using proper typing for the event parameter.The
eventparameter is typed asany, which bypasses TypeScript's type safety. While this may work with PrimeNG's select component, consider defining a more specific interface or using PrimeNG's event types if available.Example improvement:
protected handleAccountChange(event: { value: string }): void { const selectedAccountId = event.value; const selectedAccount = this.accountContextService.availableAccounts.find((acc) => acc.accountId === selectedAccountId); if (selectedAccount) { this.accountContextService.setAccount(selectedAccount); } }apps/lfx-one/src/app/shared/services/account-context.service.ts (1)
24-27: Consider validating account membership in setAccount.The
setAccountmethod doesn't verify that the provided account exists inavailableAccounts. While this may be fine for the current use case, adding validation could prevent potential issues if called with invalid account data.Example:
public setAccount(account: Account): void { if (!this.availableAccounts.some(acc => acc.accountId === account.accountId)) { console.warn('Attempted to set invalid account:', account); return; } this.selectedAccount.set(account); this.persistAccount(account); }apps/lfx-one/src/server/controllers/analytics.controller.ts (2)
409-410: Address TODO: HardcodedprojectIdneeds dynamic resolution.The hardcoded
projectIdwith an inline TODO indicates this should be resolved from user profile or session. Until implemented, this limits the endpoint to a single project context.Do you want me to open a new issue to track implementing dynamic
projectIdresolution from user context?
415-415: Consider explicit column selection instead ofSELECT *.While
SELECT *works for a controlled table structure, explicitly listing required columns (MEMBERSHIP_TIER, CURRENT_MEMBERSHIP_START_DATE, CURRENT_MEMBERSHIP_END_DATE, MEMBERSHIP_PRICE, MEMBERSHIP_STATUS, ACCOUNT_ID) would:
- Document the expected schema
- Reduce payload if table schema expands
- Make the query more maintainable
📜 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.
📒 Files selected for processing (33)
.vscode/settings.json(1 hunks)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.scss(1 hunks)apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.html(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.scss(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.html(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.scss(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.ts(1 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.scss(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts(1 hunks)apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.ts(2 hunks)apps/lfx-one/src/app/modules/dashboards/dashboard.component.html(1 hunks)apps/lfx-one/src/app/modules/dashboards/dashboard.component.ts(2 hunks)apps/lfx-one/src/app/shared/services/account-context.service.ts(1 hunks)apps/lfx-one/src/app/shared/services/analytics.service.ts(2 hunks)apps/lfx-one/src/server/controllers/analytics.controller.ts(3 hunks)apps/lfx-one/src/server/routes/analytics.route.ts(1 hunks)packages/shared/src/constants/accounts.constants.ts(1 hunks)packages/shared/src/constants/action-items.constants.ts(1 hunks)packages/shared/src/constants/foundation-health.constants.ts(1 hunks)packages/shared/src/constants/index.ts(1 hunks)packages/shared/src/constants/organization-involvement.constants.ts(1 hunks)packages/shared/src/constants/persona.constants.ts(1 hunks)packages/shared/src/interfaces/account.interface.ts(1 hunks)packages/shared/src/interfaces/analytics-data.interface.ts(1 hunks)packages/shared/src/interfaces/dashboard.interface.ts(1 hunks)packages/shared/src/interfaces/index.ts(1 hunks)packages/shared/src/interfaces/persona.interface.ts(1 hunks)packages/shared/src/utils/color.utils.ts(1 hunks)packages/shared/src/utils/index.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (14)
- .vscode/settings.json
- apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.html
- apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.ts
- apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.scss
- packages/shared/src/constants/foundation-health.constants.ts
- apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.scss
- apps/lfx-one/src/app/modules/dashboards/dashboard.component.html
- packages/shared/src/utils/color.utils.ts
- apps/lfx-one/src/app/modules/dashboards/dashboard.component.ts
- packages/shared/src/utils/index.ts
- packages/shared/src/constants/organization-involvement.constants.ts
- apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.html
- apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.scss
- packages/shared/src/interfaces/dashboard.interface.ts
🧰 Additional context used
📓 Path-based instructions (7)
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/account.interface.tspackages/shared/src/interfaces/index.tspackages/shared/src/interfaces/persona.interface.tspackages/shared/src/interfaces/analytics-data.interface.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use TypeScript interfaces instead of union types for better maintainability
When defining PrimeNG-related types, reference the official PrimeNG component interfaces
Files:
packages/shared/src/interfaces/account.interface.tspackages/shared/src/interfaces/index.tsapps/lfx-one/src/app/shared/services/analytics.service.tspackages/shared/src/interfaces/persona.interface.tsapps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.tsapps/lfx-one/src/server/routes/analytics.route.tspackages/shared/src/constants/accounts.constants.tsapps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.tspackages/shared/src/constants/action-items.constants.tsapps/lfx-one/src/app/shared/services/account-context.service.tsapps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.tsapps/lfx-one/src/server/controllers/analytics.controller.tsapps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.tspackages/shared/src/constants/persona.constants.tspackages/shared/src/interfaces/analytics-data.interface.tspackages/shared/src/constants/index.ts
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}
📄 CodeRabbit inference engine (CLAUDE.md)
Include required license headers on all source files
Files:
packages/shared/src/interfaces/account.interface.tsapps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.scsspackages/shared/src/interfaces/index.tsapps/lfx-one/src/app/shared/services/analytics.service.tsapps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.htmlpackages/shared/src/interfaces/persona.interface.tsapps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.tsapps/lfx-one/src/server/routes/analytics.route.tspackages/shared/src/constants/accounts.constants.tsapps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.tspackages/shared/src/constants/action-items.constants.tsapps/lfx-one/src/app/shared/services/account-context.service.tsapps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.tsapps/lfx-one/src/server/controllers/analytics.controller.tsapps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.tspackages/shared/src/constants/persona.constants.tspackages/shared/src/interfaces/analytics-data.interface.tsapps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.htmlpackages/shared/src/constants/index.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not nest ternary expressions
Files:
packages/shared/src/interfaces/account.interface.tspackages/shared/src/interfaces/index.tsapps/lfx-one/src/app/shared/services/analytics.service.tspackages/shared/src/interfaces/persona.interface.tsapps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.tsapps/lfx-one/src/server/routes/analytics.route.tspackages/shared/src/constants/accounts.constants.tsapps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.tspackages/shared/src/constants/action-items.constants.tsapps/lfx-one/src/app/shared/services/account-context.service.tsapps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.tsapps/lfx-one/src/server/controllers/analytics.controller.tsapps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.tspackages/shared/src/constants/persona.constants.tspackages/shared/src/interfaces/analytics-data.interface.tspackages/shared/src/constants/index.ts
**/index.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Do not use barrel exports; always use direct imports for standalone components
Files:
packages/shared/src/interfaces/index.tspackages/shared/src/constants/index.ts
apps/lfx-one/src/**/*.html
📄 CodeRabbit inference engine (CLAUDE.md)
apps/lfx-one/src/**/*.html: Always add data-testid attributes when creating new Angular components for reliable test targeting
Use data-testid naming convention [section]-[component]-[element]
Files:
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.htmlapps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.html
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/accounts.constants.tspackages/shared/src/constants/action-items.constants.tspackages/shared/src/constants/persona.constants.tspackages/shared/src/constants/index.ts
🧠 Learnings (3)
📚 Learning: 2025-09-16T03:32:46.518Z
Learnt from: CR
PR: linuxfoundation/lfx-v2-ui#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-16T03:32:46.518Z
Learning: Applies to packages/shared/src/interfaces/**/*.ts : Place all TypeScript interfaces in the shared package at packages/shared/src/interfaces
Applied to files:
packages/shared/src/interfaces/index.ts
📚 Learning: 2025-09-16T03:32:46.518Z
Learnt from: CR
PR: linuxfoundation/lfx-v2-ui#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/accounts.constants.tspackages/shared/src/constants/index.ts
📚 Learning: 2025-09-16T03:32:46.518Z
Learnt from: CR
PR: linuxfoundation/lfx-v2-ui#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-16T03:32:46.518Z
Learning: Applies to apps/lfx-one/src/**/*.html : Always add data-testid attributes when creating new Angular components for reliable test targeting
Applied to files:
apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.ts
🧬 Code graph analysis (9)
apps/lfx-one/src/app/shared/services/analytics.service.ts (1)
packages/shared/src/interfaces/analytics-data.interface.ts (5)
OrganizationMaintainersResponse(184-199)OrganizationContributorsResponse(241-261)MembershipTierResponse(205-235)OrganizationEventAttendanceResponse(340-365)OrganizationTechnicalCommitteeResponse(391-406)
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (4)
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (1)
Component(23-309)apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.ts (1)
Component(12-49)apps/lfx-one/src/app/modules/dashboards/dashboard.component.ts (1)
Component(17-34)packages/shared/src/interfaces/account.interface.ts (1)
Account(8-13)
packages/shared/src/constants/accounts.constants.ts (1)
packages/shared/src/interfaces/account.interface.ts (1)
Account(8-13)
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts (3)
packages/shared/src/interfaces/dashboard.interface.ts (2)
Foundation(228-257)OrgDependencyRiskLevel(179-179)packages/shared/src/constants/foundation-health.constants.ts (1)
FOUNDATION_HEALTH_DATA(31-161)packages/shared/src/utils/color.utils.ts (1)
hexToRgba(28-56)
packages/shared/src/constants/action-items.constants.ts (1)
packages/shared/src/interfaces/components.interface.ts (1)
PendingActionItem(336-349)
apps/lfx-one/src/app/shared/services/account-context.service.ts (2)
packages/shared/src/interfaces/account.interface.ts (1)
Account(8-13)packages/shared/src/constants/accounts.constants.ts (2)
ACCOUNTS(10-23)DEFAULT_ACCOUNT(29-32)
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (5)
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts (1)
Component(14-39)packages/shared/src/interfaces/dashboard.interface.ts (4)
ContributionMetric(94-103)ImpactMetric(109-118)OrganizationInvolvementMetricWithChart(124-167)PrimaryInvolvementMetric(63-88)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 (3)
OrganizationContributorsResponse(241-261)OrganizationMaintainersResponse(184-199)MembershipTierResponse(205-235)packages/shared/src/utils/color.utils.ts (1)
hexToRgba(28-56)
apps/lfx-one/src/server/controllers/analytics.controller.ts (2)
packages/shared/src/interfaces/analytics-data.interface.ts (11)
ProjectCountRow(307-309)MemberDashboardMaintainersRow(267-272)OrganizationMaintainersResponse(184-199)MembershipTierRow(278-290)MembershipTierResponse(205-235)OrganizationContributorsRow(296-301)OrganizationContributorsResponse(241-261)OrganizationEventAttendanceRow(328-334)OrganizationEventAttendanceResponse(340-365)OrganizationTechnicalCommitteeRow(381-385)OrganizationTechnicalCommitteeResponse(391-406)apps/lfx-one/src/server/errors/index.ts (1)
ResourceNotFoundError(7-7)
apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.ts (2)
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts (1)
Component(52-222)packages/shared/src/interfaces/dashboard.interface.ts (1)
FoundationHealthScore(173-173)
🔇 Additional comments (18)
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.scss (1)
1-2: License header correctly applied. The required copyright notice and SPDX-License-Identifier are properly formatted per coding guidelines.packages/shared/src/interfaces/analytics-data.interface.ts (1)
180-406: LGTM! Well-structured interface definitions.The new interfaces follow proper conventions:
- Snowflake row interfaces use UPPERCASE field names matching database columns
- API response interfaces use camelCase for JavaScript consumption
- Comprehensive JSDoc documentation for all fields
- Clear separation between raw database rows and transformed API responses
packages/shared/src/interfaces/index.ts (1)
68-69: LGTM! Proper barrel export addition.The new account interface export follows the established pattern and aligns with the coding guideline to place all TypeScript interfaces in the shared package.
packages/shared/src/interfaces/persona.interface.ts (1)
8-8: LGTM! Type extension supports new persona.The addition of 'board-member' to the PersonaType union cleanly enables the new board member dashboard flows.
packages/shared/src/constants/persona.constants.ts (1)
25-29: LGTM! Persona option aligns with type definition.The new board member option is consistent with other persona definitions and properly integrates with the updated PersonaType union.
packages/shared/src/interfaces/account.interface.ts (1)
1-13: LGTM! Clean interface definition.The Account interface is well-documented and follows established patterns for the shared interfaces package.
packages/shared/src/constants/index.ts (1)
20-22: LGTM! Proper constant exports.The new barrel exports follow the established pattern and align with the coding guideline to place all reusable constants in the shared package.
packages/shared/src/constants/action-items.constants.ts (1)
66-86: LGTM!The board member action items follow the same structure and conventions as existing persona action items, with appropriate fields and type-safe implementation.
apps/lfx-one/src/app/modules/dashboards/components/health-score-tag/health-score-tag.component.ts (1)
1-42: LGTM!The component implementation is clean, type-safe, and follows Angular best practices. The CSS class mapping and label formatting logic are straightforward and correct.
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.html (1)
1-184: LGTM!The template is well-structured with proper Angular control flow, comprehensive data-testid attributes for testing, accessibility features (tooltips and help icons), and a responsive layout. The implementation follows all coding guidelines.
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.html (1)
1-149: LGTM!The template provides a comprehensive organization involvement view with proper loading states, data-testid attributes for testing, accessibility features, and responsive layout. The implementation follows Angular best practices and coding guidelines.
apps/lfx-one/src/app/shared/services/account-context.service.ts (1)
40-50: LGTM!The
loadStoredAccountmethod includes proper error handling for JSON parsing errors, safely returning null to fall back to the default account.apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (1)
250-284: LGTM!The membership tier transformation includes proper date parsing, formatting, and null-safe handling with appropriate fallbacks.
apps/lfx-one/src/server/controllers/analytics.controller.ts (5)
261-261: LGTM: Type-safe query result.The change to
ProjectCountRowcorrectly aligns with the query'sTOTAL_PROJECTScolumn and improves type safety.
362-362: Verify the hardcoded fallbackaccountIdpattern.Multiple endpoints (lines 362, 411, 470, 522, 577) use the same hardcoded fallback
accountId: '0014100000Te0OKAAZ'. While this may be acceptable for development with Microsoft Corporation as default, ensure this aligns with production requirements and consider:
- Whether a fallback should exist in production
- If the default should be configurable via environment variable
- Whether missing accountId should return an error instead
465-510: LGTM: Consistent implementation pattern.The endpoint follows the same well-structured pattern as other analytics endpoints with parameterized queries, proper error handling, and comprehensive logging.
517-565: LGTM: Proper SQL aggregation.The endpoint correctly uses SQL aggregation (SUM, COUNT) with appropriate handling for grouped columns via MAX(). The parameterized query, error handling, and logging are all well-implemented.
572-619: LGTM: Well-structured aggregation query.The endpoint follows the established pattern with appropriate SQL aggregation for technical committee statistics. Implementation is consistent with other analytics endpoints.
apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.ts
Show resolved
Hide resolved
...modules/dashboards/components/organization-involvement/organization-involvement.component.ts
Show resolved
Hide resolved
...modules/dashboards/components/organization-involvement/organization-involvement.component.ts
Show resolved
Hide resolved
- Add pool configuration for connection validation (testOnBorrow, evictionRunIntervalMillis, idleTimeoutMillis) - Remove lock TTL buffer to prevent false deduplication hits on first requests - Add comprehensive environment variable validation with clear error messages - Wrap Snowflake SDK errors in MicroserviceError for proper ERROR-level logging - Fix "Unhandled API error" by providing structured error responses Resolves issues: - "Unable to perform operation using terminated connection" errors - False "Query deduplication hit" messages on first-time requests - Missing SNOWFLAKE_USER validation causing unclear error messages - INFO-level logging for errors instead of proper ERROR-level logs LFXV2-687 Generated with [Claude Code](https://claude.ai/code) Signed-off-by: Asitha de Silva <asithade@gmail.com>
There was a problem hiding this 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 (2)
apps/lfx-one/src/server/services/snowflake.service.ts (2)
251-282: LGTM: Comprehensive environment validation.The upfront validation of all required environment variables with detailed error reporting significantly improves debuggability. The
requiredEnvVarsobject approach is clean and makes subsequent usage clear.Consider using a type guard or assertion function to avoid non-null assertions later. For example:
type ValidatedEnvVars = { [K in keyof typeof requiredEnvVars]: string; }; function validateEnvVars(): ValidatedEnvVars { const requiredEnvVars = { SNOWFLAKE_ACCOUNT: process.env['SNOWFLAKE_ACCOUNT'], SNOWFLAKE_USER: process.env['SNOWFLAKE_USER'], // ... rest }; const missingVars = Object.entries(requiredEnvVars) .filter(([, value]) => !value) .map(([key]) => key); if (missingVars.length > 0) { // throw error } return requiredEnvVars as ValidatedEnvVars; }This eliminates the need for
!assertions on lines 284, 292-299.
288-289: Add validation for numeric environment variables.
Number()returnsNaNfor invalid input, which would silently fall back to defaults. Consider validating that parsed values are valid numbers and logging a warning if environment variables are set but invalid.const parseNumericEnv = (key: string, defaultValue: number): number => { const value = process.env[key]; if (!value) return defaultValue; const parsed = Number(value); if (isNaN(parsed)) { serverLogger.warn( { key, value, default: defaultValue }, 'Invalid numeric environment variable, using default' ); return defaultValue; } return parsed; }; const minConnections = parseNumericEnv('SNOWFLAKE_MIN_CONNECTIONS', SNOWFLAKE_CONFIG.MIN_CONNECTIONS); const maxConnections = parseNumericEnv('SNOWFLAKE_MAX_CONNECTIONS', SNOWFLAKE_CONFIG.MAX_CONNECTIONS);
📜 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.
📒 Files selected for processing (2)
apps/lfx-one/src/server/services/snowflake.service.ts(5 hunks)apps/lfx-one/src/server/utils/lock-manager.ts(1 hunks)
🧰 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/services/snowflake.service.tsapps/lfx-one/src/server/utils/lock-manager.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/services/snowflake.service.tsapps/lfx-one/src/server/utils/lock-manager.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not nest ternary expressions
Files:
apps/lfx-one/src/server/services/snowflake.service.tsapps/lfx-one/src/server/utils/lock-manager.ts
🧬 Code graph analysis (1)
apps/lfx-one/src/server/services/snowflake.service.ts (2)
apps/lfx-one/src/server/errors/index.ts (1)
MicroserviceError(6-6)packages/shared/src/constants/snowflake.constant.ts (1)
SNOWFLAKE_CONFIG(7-57)
⏰ 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 (4)
apps/lfx-one/src/server/utils/lock-manager.ts (1)
165-167: LGTM! Immediate lock cleanup is correct for non-caching deduplication.The immediate deletion is safe because the promise has already resolved by the time the finally block executes, ensuring all waiters receive the result. This change reduces memory footprint while maintaining the fetch lock pattern's core benefit: preventing duplicate concurrent executions. The periodic cleanup (lines 225-243) now serves as a safety mechanism for hung queries rather than the primary cleanup path, which is an appropriate design.
apps/lfx-one/src/server/services/snowflake.service.ts (3)
9-9: LGTM: Standardized error handling.The import of
MicroserviceErrorenables consistent error wrapping throughout the service, which aligns with the broader error handling improvements in this PR.
303-316: LGTM: Robust pool configuration.The extended pool options (
testOnBorrow, eviction intervals, timeouts) improve connection health and resource management. SettingtestOnBorrow: trueadds a small latency cost but prevents using stale connections, which is appropriate for production reliability.
336-353: LGTM: Consistent error wrapping pattern.The error handling follows the same MicroserviceError wrapping pattern used in the
executemethod, providing consistent error structure and debugging metadata across the service.Note: The inconsistent use of
process.env['SNOWFLAKE_ACCOUNT']on line 350 (instead ofrequiredEnvVars.SNOWFLAKE_ACCOUNT) was already flagged in an earlier comment.
- Pass originalError to MicroserviceError constructor to preserve full stack traces - Use validated requiredEnvVars instead of direct process.env access in logging - Ensures consistency between logged values and actual configuration used LFXV2-687 Generated with [Claude Code](https://claude.ai/code) Signed-off-by: Asitha de Silva <asithade@gmail.com>
🧹 Deployment RemovedThe deployment for PR #134 has been removed. |
Summary
Implement Board Member persona dashboard with three key components: Organization Involvement, Foundation Health, and Pending Actions. Integrates with Snowflake data warehouse for real-time organization metrics.
Components Implemented
1. Board Member Dashboard
2. Organization Involvement Component
Snowflake Integration:
Primary Metrics (4 compact cards):
Secondary Metrics:
Features:
3. Foundation Health Component
4. Pending Actions Component
Backend Implementation
Analytics Controller
getOrganizationMaintainers(): Query maintainers count and projectsgetMembershipTier(): Fetch membership tier details with pricingRoutes
/api/analytics/organization-maintainers/api/analytics/membership-tierShared Package Updates
Interfaces
OrganizationMaintainersResponseMembershipTierResponseOrganizationInvolvementMetricWithChartFoundationHealthMetricConstants
PRIMARY_INVOLVEMENT_METRICS(4 metrics)CONTRIBUTIONS_METRICS(4 metrics)IMPACT_METRICS(4 metrics)FOUNDATION_HEALTH_METRICS(15 metrics)PERSONA_CONFIGwith board memberTechnical Highlights
toSignaland computed signalsFiles Changed
Backend:
Frontend:
Shared:
Testing
Related Issue
LFXV2-687
Generated with Claude Code