ui(dashboard): table layout, after-hours fix, trend improvements#317
ui(dashboard): table layout, after-hours fix, trend improvements#317sylvainkalache merged 17 commits intomainfrom
Conversation
- Fix trend sorting bug: use ?? instead of || for trendOrder lookup (0 is a valid order value for significantly_worsening) - Swap Trend to left, Risk Level to right in card layout - Add sort toggle (Risk Level / Trend) in header - Add info icons with tooltips explaining metrics - Show "Score: X/100" instead of incident count under Risk Level - Use softer progress bar colors (300-level) to match badge opacity - Change "Needs Attention" label to "Critical" for clarity - Remove unused variables (isGithubEnabled, isSlackEnabled, isLinearEnabled) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile OverviewGreptile SummaryThis PR enhances the Team Members List UI with several improvements:
The changes are well-structured, maintain existing functionality while adding new features, and improve the user experience with clearer information presentation. Confidence Score: 5/5
Important Files Changed
|
Keep softer progress bar colors (300-level) from testing branch. Remove unused getOCHRiskLevel function. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Claude finished @sylvainkalache's task —— View job PR Review AnalysisTodo List:
Issues Found:Potential Logic Error in Trend CalculationFile: const baseline = firstWeeksAvg || 0.1 // Avoid division by zero
const change = ((lastWeeksAvg - firstWeeksAvg) / baseline) * 100Issue: When Fix: Use proper handling for zero baseline cases or document the expected behavior. Missing Error HandlingFile: const trendInfo = calculateUserTrend(member.user_email, individualDailyData)Issue: No error handling if Fix: Add try-catch around trend calculation or validate input data. Type Safety IssueFile: const trendComparison = (trendOrder[trendA.trend] ?? 2) - (trendOrder[trendB.trend] ?? 2);Issue: Fallback value of Fix: Use explicit handling for invalid trend values rather than silent fallback. |
The Jira status endpoint was calling _validate_jira() directly, bypassing the existing Redis-backed validation cache (15-min TTL). This caused a ~1.2s HTTP call to Jira API on every request. Now uses validate_all_integrations(use_cache=True) which checks the cache first, eliminating the external API call for ~90% of requests.
The check_permissions() method was making 4 sequential HTTP calls (users, incidents, services, oncalls), each waiting for the previous to complete. Now uses asyncio.gather() to run all 4 in parallel. Expected improvement: ~2.3s avg → ~0.6-0.8s (limited by slowest call).
Adds indexes identified by New Relic analysis of the 5 slowest endpoints: - user_burnout_reports(email, submitted_at): analyses endpoint survey query - jira_integrations(user_id): /jira/status lookup - jira_workspace_mappings(jira_cloud_id, organization_id): workspace lookup - slack_workspace_mappings(organization_id, status): /slack/status org query - slack_workspace_mappings(owner_user_id, status): /slack/status owner query Uses CREATE INDEX CONCURRENTLY to avoid locking tables during migration. Model files updated to match for new deployments.
Two optimizations in the get_analysis endpoint: 1. Select only email column from UserCorrelation instead of loading full objects (was loading all columns for 10K+ members when only email is needed) 2. Use load_only(id, uuid) on the 404 fallback query to avoid loading the potentially 30MB+ results JSON column just for an error message
The get_notifications_with_counts query was lazy-loading the organization relationship for each notification's to_dict() call (self.organization.name), causing 20 extra queries per page. Adding joinedload(UserNotification.organization) fetches all organization data in a single JOIN, eliminating the N+1 pattern.
…ons' into testing
|
Claude finished @sylvainkalache's task —— View job PR Review AnalysisTodo List:
Issues Found:Potential Division by Zero Edge CaseFile: const baseline = firstWeeksAvg || 0.1 // Avoid division by zeroIssue: When Missing Error Handling for Trend CalculationFile: const trendInfo = calculateUserTrend(member.user_email, individualDailyData)Issue: No error handling if Fallback Value Logic InconsistencyFile: const trendComparison = (trendOrder[trendA.trend] ?? 2) - (trendOrder[trendB.trend] ?? 2);Issue: Fallback value |
|
Claude finished @sylvainkalache's task —— View job PR Review AnalysisIssues Found:Division by Zero Handling IssueFile: const baseline = firstWeeksAvg || 0.1 // Avoid division by zeroIssue: Using Fix: Use proper zero handling: const baseline = firstWeeksAvg === 0 ? 0.1 : firstWeeksAvg || 0.1Missing Error HandlingFile: const trendInfo = calculateUserTrend(member.user_email, individualDailyData)Issue: No error handling if Fix: Add try-catch wrapper: try {
const trendInfo = calculateUserTrend(member.user_email, individualDailyData)
} catch (error) {
const trendInfo = { trend: 'stable', percentage: 0, firstHalfScore: 0, secondHalfScore: 0 }
}Fallback Value InconsistencyFile: const trendComparison = (trendOrder[trendA.trend] ?? 2) - (trendOrder[trendB.trend] ?? 2);Issue: Fallback value Fix: Use explicit validation or log when fallback is used. |
…s calculation - Replace tile grid with table view for team member risk levels (columns: Member, Risk Level, Trend, Incidents, Status, Data Sources) - Fix trend calculation for low scores to avoid misleading percentages (e.g. 0→3 no longer shows "Critical 3143%") - Use stronger bar colors (Tailwind 400 instead of 300) - After-hours activity now based only on voluntary activity (GitHub + Slack), excluding incidents since being paged is not a choice - Remove fake 15% after-hours fallback estimate in GitHub collector - Update landing page button text to "View on GitHub" - Add tests for voluntary-only after-hours and fallback behavior - Fix test_after_hours_detection threshold to match code (>= 17 not >= 18)
|
Claude finished @sylvainkalache's task —— View job PR Review AnalysisTodo List:
Issues Found:Logic Error in Trend ClassificationFile: else if (absDiff >= 5) trend = 'worsening'
else if (absDiff >= 2) trend = 'worsening'Issue: Both conditions assign the same Fix: The second line should likely assign else if (absDiff >= 5) trend = 'significantly_worsening'
else if (absDiff >= 2) trend = 'worsening'Potential Precision IssueFile: const baseline = firstWeeksAvg || 1Issue: Uses logical OR ( Fix: Use nullish coalescing for proper zero handling: const baseline = firstWeeksAvg ?? 1 |
|
Claude finished @sylvainkalache's task —— View job PR Review AnalysisTodo List:
Issues Found:Logic Error in Trend ClassificationFile: else if (absDiff >= 5) trend = 'worsening'
else if (absDiff >= 2) trend = 'worsening'Issue: Both conditions assign the same Fix: The first line should assign else if (absDiff >= 5) trend = 'significantly_worsening'
else if (absDiff >= 2) trend = 'worsening'Potential Division by Zero Edge CaseFile: const baseline = firstWeeksAvg || 1Issue: Using logical OR ( Fix: Use proper zero handling: const baseline = firstWeeksAvg === 0 ? 1 : firstWeeksAvg || 1 |
|
Claude finished @sylvainkalache's task —— View job PR Review AnalysisTodo List:
Issues Found:Logic Error in Trend ClassificationFile: else if (absDiff >= 5) trend = 'significantly_worsening'
else if (absDiff >= 2) trend = 'worsening'Issue: Both conditions assign Fix: The conditions should be properly ordered: else if (absDiff >= 5) trend = 'significantly_worsening'
else if (absDiff >= 2) trend = 'worsening'This appears to be correctly ordered in the current code, but the threshold logic should be verified against requirements. Potential Division by Zero Edge CaseFile: const baseline = firstWeeksAvg === 0 ? 1 : firstWeeksAvg || 1Issue: This handles the exact zero case correctly with explicit comparison, but using logical OR as fallback may still create edge cases if |
Summary
Files changed
frontend/src/components/dashboard/TeamMembersList.tsx— table layout, trend fixes, colorsfrontend/src/components/landing-page.tsx— button textbackend/app/services/unified_burnout_analyzer.py— after-hours uses GitHub + Slack onlybackend/app/services/github_collector.py— removed 15% fallback estimatebackend/tests/test_incident_metrics.py— new and fixed testsTest plan
pytest tests/test_incident_metrics.py(57 pass)