-
Notifications
You must be signed in to change notification settings - Fork 0
feat(architecture): foundation navigation and dashboard enhancements #151
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
Major refactoring to support foundation-based architecture with enhanced dashboards, improved navigation, and better project selector functionality. Key Changes: - Refactored layout architecture with header per layout - Implemented foundation-based project selection with mega menu - Migrated analytics from project-ID to foundation-slug - Enhanced dashboard UI with filtering and icons - Improved meetings UI with context awareness - Updated shared types and constants - Added new branding assets Related Tickets: - LFXV2-732: Architecture refactoring - LFXV2-733: Foundation frontend components - LFXV2-734: Foundation services and backend - LFXV2-735: Dashboard simplification - LFXV2-736: Recent progress enhancement - LFXV2-737: Organization involvement enhancement - LFXV2-738: Meetings UI improvements - LFXV2-739: Shared package updates - LFXV2-740: Component cleanup - LFXV2-741: Branding and documentation Additional Fix: - Fixed project selector search to show child projects with parent foundations - Refactored computed properties to follow project architecture pattern Generated with [Claude Code](https://claude.ai/code) Signed-off-by: Asitha de Silva <[email protected]>
|
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. WalkthroughMoves header out of app root into specific layouts; converts analytics and dashboard flows from projectId to projectSlug; introduces persona-aware selection and filtering; redesigns sidebar and project selector; modifies meeting-type selection and several dashboard templates; updates progress metrics and related interfaces; adds small content and style tweaks. Changes
Sequence Diagram(s)sequenceDiagram
participant U as User (Maintainer)
participant UI as RecentProgressComponent
participant PC as ProjectContextService
participant AS as AnalyticsService
participant S as Server (analytics.controller)
U->>UI: select filter
UI->>UI: set selectedFilter, reset scroll
UI->>PC: resolve projectSlug (foundation?.slug || project?.slug)
UI->>AS: getProjectIssuesResolution(projectSlug)
AS->>S: GET /analytics/issues?projectSlug=...
S-->>AS: issues resolution data (slug-based)
AS-->>UI: return formatted data
UI-->>U: render filtered items and charts
sequenceDiagram
participant U as User (switcher)
participant Persona as PersonaService
participant PC as ProjectContextService
participant Sidebar as SidebarComponent
U->>Persona: setPersona('board-member')
Persona->>PC: clearProject()
Persona-->>U: navigate to root
U->>Sidebar: load projects
Sidebar->>PC: getProjects() -> foundationProjects (prefers 'tlf')
Sidebar-->>U: render sidebar with foundation selection
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Points needing extra attention:
Possibly related PRs
Suggested labels
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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 major architectural refactoring to support foundation-based navigation with enhanced dashboards and improved project selection. The changes migrate from project-ID to foundation-slug based analytics, introduce a hierarchical project selector with search functionality, and enhance the UI with icons, filtering capabilities, and persona-aware features.
Key Changes:
- Migrated analytics queries from project-ID to foundation-slug with CTE-based hierarchy resolution
- Implemented foundation-aware project selector with mega menu and search
- Enhanced dashboard components with filtering, icons, and improved visual design
- Refactored layouts to include header per layout instead of globally
Reviewed Changes
Copilot reviewed 35 out of 37 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/shared/src/interfaces/components.interface.ts | Added category and icon fields to ProgressItemWithChart interface |
| packages/shared/src/constants/progress-metrics.constants.ts | Updated maintainer metrics with icons, categories, and revised chart configurations |
| packages/shared/src/constants/persona.constants.ts | Removed 'projects' persona option |
| packages/shared/src/constants/organization-involvement.constants.ts | Updated icons and colors for involvement metrics |
| apps/lfx-one/src/server/services/project.service.ts | Migrated from projectId to projectSlug with CTE-based foundation queries |
| apps/lfx-one/src/server/controllers/analytics.controller.ts | Updated controller to use projectSlug instead of projectId |
| apps/lfx-one/src/app/shared/services/analytics.service.ts | Updated service methods to accept projectSlug parameters |
| apps/lfx-one/src/app/shared/services/project-context.service.ts | Added clearProject method with localStorage safety checks |
| apps/lfx-one/src/app/shared/components/sidebar/sidebar.component.ts | Enhanced with foundation/project selection logic and persona filtering |
| apps/lfx-one/src/app/shared/components/sidebar/sidebar.component.html | Redesigned UI with updated styling and persona selector integration |
| apps/lfx-one/src/app/shared/components/project-selector/project-selector.component.ts | Implemented hierarchical project selector with search and filtering |
| apps/lfx-one/src/app/shared/components/project-selector/project-selector.component.html | Added search input and mega menu with foundation/child project display |
| apps/lfx-one/src/app/shared/components/persona-selector/persona-selector.component.ts | Added foundation context setting for board-member persona |
| apps/lfx-one/src/app/shared/components/header/header.component.html | Simplified header to use lfx-one-logo.svg |
| apps/lfx-one/src/app/modules/project/meetings/components/meeting-type-selection/meeting-type-selection.component.ts | Added meeting type filtering and project writer permission check |
| apps/lfx-one/src/app/modules/meetings/meetings-dashboard/meetings-dashboard.component.ts | Added persona and project context awareness |
| apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.ts | Removed project selector in favor of sidebar-based selection |
| apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts | Added category-based filtering for maintainer persona |
| apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.html | Added icons to metrics display |
| apps/lfx-one/src/app/layouts/main-layout/main-layout.component.ts | Simplified navigation items |
| apps/lfx-one/src/app/layouts/main-layout/main-layout.component.html | Updated layout spacing and sidebar width |
| apps/lfx-one/src/app/layouts/project-layout/project-layout.component.ts | Added header component import |
| apps/lfx-one/src/app/layouts/profile-layout/profile-layout.component.ts | Added header component import |
| apps/lfx-one/src/app/app.component.ts | Removed global header in favor of layout-specific headers |
| apps/lfx-one/public/images/lfx-one-logo.svg | Added new LFX One logo SVG |
| apps/lfx-one/public/images/lfx-logo.svg | Removed old LFX logo |
| CLAUDE.md | Added note about JIRA sprint field configuration |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
apps/lfx-one/src/app/shared/components/persona-selector/persona-selector.component.ts
Show resolved
Hide resolved
apps/lfx-one/src/app/shared/components/project-selector/project-selector.component.html
Outdated
Show resolved
Hide resolved
apps/lfx-one/src/app/shared/components/project-selector/project-selector.component.html
Show resolved
Hide resolved
...dules/project/meetings/components/meeting-type-selection/meeting-type-selection.component.ts
Show resolved
Hide resolved
...dules/project/meetings/components/meeting-type-selection/meeting-type-selection.component.ts
Show resolved
Hide resolved
apps/lfx-one/src/app/shared/components/project-selector/project-selector.component.ts
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: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/lfx-one/src/server/services/project.service.ts (1)
582-653: Bug:foundation_slugalias can’t be used in WHERE in SnowflakeIn the daily issues query you define
foundation_slugas a SELECT alias:COALESCE(t.grandparents_slug, t.parent_slug, t.slug) as foundation_slug ... WHERE foundation_slug = ?Snowflake (and standard SQL) do not allow using a SELECT alias in the
WHEREclause of the same query, so this will fail at runtime with an invalid identifier error. You need to repeat the expression (or move the alias into the CTE) in the WHERE predicate.A minimal fix keeping the current structure would be:
- SELECT - pisd.PROJECT_ID, - pisd.PROJECT_NAME, - pisd.PROJECT_SLUG, - pisd.METRIC_DATE, - pisd.OPENED_ISSUES_COUNT, - pisd.CLOSED_ISSUES_COUNT, - COALESCE(t.grandparents_slug, t.parent_slug, t.slug) as foundation_slug - FROM ANALYTICS.PLATINUM_LFX_ONE.PROJECT_ISSUES_RESOLUTION_DAILY pisd - INNER JOIN project_segments t ON pisd.project_slug = t.slug - WHERE foundation_slug = ? + SELECT + pisd.PROJECT_ID, + pisd.PROJECT_NAME, + pisd.PROJECT_SLUG, + pisd.METRIC_DATE, + pisd.OPENED_ISSUES_COUNT, + pisd.CLOSED_ISSUES_COUNT, + COALESCE(t.grandparents_slug, t.parent_slug, t.slug) as foundation_slug + FROM ANALYTICS.PLATINUM_LFX_ONE.PROJECT_ISSUES_RESOLUTION_DAILY pisd + INNER JOIN project_segments t ON pisd.project_slug = t.slug + WHERE COALESCE(t.grandparents_slug, t.parent_slug, t.slug) = ?The parameter arrays (
params/aggregatedParams) don’t need to change.
🧹 Nitpick comments (15)
packages/shared/src/constants/organization-involvement.constants.ts (2)
60-60: Verify the icon change aligns with UX intent.The icon changed from
fa-badge-check(suggesting status/verification) tofa-dollar-sign(suggesting financial/cost). While the dollar sign may be appropriate if membership tiers are primarily cost-based, it could be confusing if tiers represent status, benefits, or achievement levels. Please confirm this change aligns with the product's design intent and user mental model.
68-68: Verify color consistency across metrics.The sparkline colors now vary across metrics: Active Contributors and Maintainers use
#93c5fd(lighter blue), while Event Attendees, Event Speakers, and Certified Employees retain#0094FF(bright blue). If this color differentiation represents intentional semantic grouping (e.g., contributor-related vs. event-related metrics), consider adding inline comments to document the categorization strategy for future maintainability.Also applies to: 76-76
apps/lfx-one/src/app/shared/components/header/header.component.html (1)
19-21: Logo swap looks good; optional alt-text tweakThe new
lfx-one-logo.svgusage and sizing look fine, and the button’saria-labelalready provides accessible text. If you want to be extra explicit, you could change thealtto something like"LFX One"to match the product name, but it’s not strictly necessary.apps/lfx-one/src/app/shared/services/project-context.service.ts (1)
66-70: Nice hardening of persistToStorage for non‑browser contextsAdding the
typeof localStorage !== 'undefined'guard aroundsetItemavoids crashes when this service is constructed outside the browser. If this pattern spreads further, you might consider a tiny internal helper to centralize storage access, but it’s fine as is.packages/shared/src/constants/progress-metrics.constants.ts (1)
364-616: Maintainer metrics metadata and chart tweaks look consistentThe added
iconandcategoryfields, the reworked “Critical Security Issues” series, and the adjusted “Unique Contributors per Week” dataset all line up with the intendedcode/projectHealthfiltering and keep label/data lengths consistent for Chart.js. This should plug in cleanly to the updated Recent Progress UI.If you find yourself adjusting chart options further, you could consider reusing the shared
PROGRESS_*_CHART_OPTIONSconstants here instead of inlining similar options for each metric, but that’s purely a maintainability nicety.apps/lfx-one/src/app/shared/components/project-selector/project-selector.component.ts (1)
5-148: Foundation/child grouping and search logic are sound; only minor refactor opportunitiesThe signal-based state (
searchQuery) and the computed initializers for display name/logo, foundations, and childProjectsMap are consistent with the new foundation-first UX, and the parent/child detection viaparent_uid+validProjectIdsis correct.If you want to tighten things further (optional):
- Factor out the
validProjectIds+querycalculation used in bothinitializeFoundationsandinitializeChildProjectsMapinto a small private helper to avoid duplication and keep both computeds in sync if the normalization changes.- Optionally annotate the initializer methods with explicit return types (e.g.
private initializeFoundations(): Signal<Project[]>) to make the public surface clearer when scanning the class.These are purely readability/maintainability nits; behavior is fine as-is.
apps/lfx-one/src/app/shared/components/sidebar/sidebar.component.html (2)
27-31: Track function in@forloops may be fragile if labels changeThe
@forblocks track items byitem.label. If labels are not unique or change over time, Angular’s diffing may behave unexpectedly (e.g., reuse DOM for the wrong item).If you have a stable identifier on
SidebarMenuItem(e.g.,idortestId), consider tracking by that instead:@for (item of itemsWithTestIds(); track item.testId) { ... } @for (item of footerItemsWithTestIds(); track item.testId) { ... }Also applies to: 41-44
51-93: Menu item templates are consistent; consider deduping common classesThe routerLink, external URL, and command button variants all share a long identical base class list and markup structure (icon container, label, optional badge), differing mainly in element type and disabled handling. This is good for UX consistency, but it does introduce duplication that’s easy to get out of sync.
If this template keeps evolving, consider extracting the shared class string into a directive or a small helper (e.g.,
sidebar-itemcomponent/directive) so future visual tweaks happen in one place.Also applies to: 96-115
apps/lfx-one/src/app/shared/components/sidebar/sidebar.component.ts (4)
36-55: Default foundation selection logic vs commentThe comment says “Only set default if no foundation is selected and projects exist”, but the condition is:
const foundationExists = loadedProjects.some((p) => p.uid === currentFoundation?.projectId); if (loadedProjects.length > 0 && (!foundationExists || !currentFoundation)) { // set default foundation 'tlf' or first project }This will also reset the foundation when
currentFoundationexists but does not match any loaded project (e.g., stale context), not only when there is “no foundation”. That might be intentional to repair invalid state, but it diverges from the comment.If you only want to set a default when nothing is selected, tighten the condition to:
if (loadedProjects.length > 0 && !currentFoundation) { ... }Otherwise, consider updating the comment to reflect that you also normalize invalid foundations.
62-78: Board-member demo logic is hard-coded totlf
isBoardMemberandfoundationProjects/selectedProjectspecial-case slug'tlf'with TODO comments marking this as demo behavior. For now this is fine, but the hard-coded slug will be brittle once you introduce real permissions or multiple board-member foundations.When you implement proper permissions, consider:
- Moving the foundation slug(s) into a config or service rather than literals.
- Dropping the special casing in
selectedProjectand relying onselectedFoundation.slugso persona only influences what’s selectable, not the computed selection itself.
95-130: Foundation vs project classification relies on parent presence
onProjectChangedistinguishes foundation vs non-foundation projects with:const allProjects = this.projects(); const validProjectIds = new Set(allProjects.map((p) => p.uid)); const isFoundation = !project.parent_uid || project.parent_uid === '' || !validProjectIds.has(project.parent_uid);If
parent_uidexists but the parent is not inallProjects(e.g., partial list, data mismatch), the project will be treated as a foundation, callingsetFoundationandclearProject()instead ofsetProject. That might be acceptable, but it’s worth confirming that:
getProjects()always includes all relevant parent projects, andparent_uidis reliably populated for non-foundation entries.If not guaranteed, consider a more explicit marker for foundations (e.g., a flag on
Project) or handling the “unknown parent” case separately.
133-137: Prefer Angular Router overwindow.location.hreffor logo navigation
onLogoClickcurrently useswindow.location.href = '/', which forces a full reload and ignores Angular routing nuances (e.g., a non-rootbaseHref).Since this is an SPA, it’s cleaner to inject
Routerand navigate:-import { Component, computed, inject, input } from '@angular/core'; +import { Component, computed, inject, input } from '@angular/core'; +import { Router } from '@angular/router'; ... export class SidebarComponent { + private readonly router = inject(Router); ... protected onLogoClick(): void { - // Navigate to home page - window.location.href = '/'; + this.router.navigateByUrl('/'); } }Combined with wiring
(click)="onLogoClick()"in the template, this will give you SPA navigation without a hard reload.apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts (3)
57-59: Slug-based analytics wiring looks good; fallback branch could be clearerSwitching from project ID to
projectSlugderived fromselectedFoundation()?.slugand piping it throughtoObservable(this.projectSlug).pipe(switchMap(...))forgetProjectIssuesResolutionandgetProjectPullRequestsWeeklyis a clean way to keep analytics tied to foundation context.In the “no slug” branch you return a bare array:
if (!projectSlug) { this.loadingState.update(...); return [{ data: [], ... }]; }RxJS treats arrays as
ObservableInput, so this works, but it’s non-obvious and can confuse readers or type inference. Consider usingof(defaultValue)instead:import { of } from 'rxjs'; if (!projectSlug) { this.loadingState.update((state) => ({ ...state, projectIssuesResolution: false })); return of({ data: [], totalOpenedIssues: 0, totalClosedIssues: 0, resolutionRatePct: 0, medianDaysToClose: 0, totalDays: 0, }); }(and similarly for
projectPullRequestsWeekly).That makes it explicit you’re returning a single emission with default data.
Also applies to: 451-501
67-99: Filter state and persona-gated filtering work, but typing could be tightenedThe filtering logic:
- Uses
selectedFilter(default'all'),filteredProgressItemscomputed, andsetFilterto reset scroll.- Applies filtering only when persona is
'maintainer'; others always see all items.This matches the requirements and is implemented cleanly. Two small refinements you might consider:
- Stronger typing for filters
type ProgressFilter = 'all' | 'code' | 'projectHealth'; protected readonly selectedFilter = signal<ProgressFilter>('all'); protected setFilter(filter: ProgressFilter): void { ... }This guards against accidental unsupported filter IDs.
- Re-use
currentPersonainfilteredProgressItemsYou already have
currentPersonacomputed; reusing it instead of callingthis.personaService.currentPersona()again would keep things DRY:const persona = this.currentPersona();Functionally everything is correct; these are just quality-of-life improvements.
Also applies to: 510-541
245-273: Issues trend metric now tagged ascode; verify categories for other metrics
transformProjectIssuesResolutionnow adds:icon: 'fa-light fa-chart-line', category: 'code', borderColor: '#0094FF', backgroundColor: 'rgba(0, 148, 255, 0.1)',This aligns with the new filtering and visual spec. However, in
initializeProgressItems()you fully replacemetricwhen labels match, so anycategory/icondefined inMAINTAINER_PROGRESS_METRICS/CORE_DEVELOPER_PROGRESS_METRICSare lost for those transformed metrics unless you explicitly set them here (like you do for issues).Please double-check that all metrics intended to be filterable (e.g., “Code Commits”, “PR Review & Merge Velocity”, any project health cards) set
categorysomewhere in the finalProgressItemWithChart, otherwise they’ll never appear when filters like'code'or'projectHealth'are applied.Also applies to: 279-281
📜 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 ignored due to path filters (2)
apps/lfx-one/public/images/lfx-logo.svgis excluded by!**/*.svgapps/lfx-one/public/images/lfx-one-logo.svgis excluded by!**/*.svg
📒 Files selected for processing (35)
CLAUDE.md(1 hunks)apps/lfx-one/src/app/app.component.html(1 hunks)apps/lfx-one/src/app/app.component.ts(1 hunks)apps/lfx-one/src/app/layouts/main-layout/main-layout.component.html(2 hunks)apps/lfx-one/src/app/layouts/main-layout/main-layout.component.ts(1 hunks)apps/lfx-one/src/app/layouts/profile-layout/profile-layout.component.html(1 hunks)apps/lfx-one/src/app/layouts/profile-layout/profile-layout.component.ts(2 hunks)apps/lfx-one/src/app/layouts/project-layout/project-layout.component.html(1 hunks)apps/lfx-one/src/app/layouts/project-layout/project-layout.component.ts(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/components/organization-involvement/organization-involvement.component.html(2 hunks)apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.html(3 hunks)apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts(7 hunks)apps/lfx-one/src/app/modules/dashboards/core-developer/core-developer-dashboard.component.html(1 hunks)apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.html(1 hunks)apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.ts(2 hunks)apps/lfx-one/src/app/modules/meetings/meetings-dashboard/meetings-dashboard.component.html(1 hunks)apps/lfx-one/src/app/modules/meetings/meetings-dashboard/meetings-dashboard.component.ts(4 hunks)apps/lfx-one/src/app/modules/project/meetings/components/meeting-type-selection/meeting-type-selection.component.html(4 hunks)apps/lfx-one/src/app/modules/project/meetings/components/meeting-type-selection/meeting-type-selection.component.ts(2 hunks)apps/lfx-one/src/app/shared/components/header/header.component.html(1 hunks)apps/lfx-one/src/app/shared/components/persona-selector/persona-selector.component.ts(3 hunks)apps/lfx-one/src/app/shared/components/project-selector/project-selector.component.html(2 hunks)apps/lfx-one/src/app/shared/components/project-selector/project-selector.component.scss(1 hunks)apps/lfx-one/src/app/shared/components/project-selector/project-selector.component.ts(1 hunks)apps/lfx-one/src/app/shared/components/sidebar/sidebar.component.html(3 hunks)apps/lfx-one/src/app/shared/components/sidebar/sidebar.component.ts(4 hunks)apps/lfx-one/src/app/shared/services/analytics.service.ts(2 hunks)apps/lfx-one/src/app/shared/services/project-context.service.ts(2 hunks)apps/lfx-one/src/server/controllers/analytics.controller.ts(2 hunks)apps/lfx-one/src/server/services/project.service.ts(4 hunks)packages/shared/src/constants/organization-involvement.constants.ts(1 hunks)packages/shared/src/constants/persona.constants.ts(0 hunks)packages/shared/src/constants/progress-metrics.constants.ts(6 hunks)packages/shared/src/interfaces/components.interface.ts(1 hunks)
💤 Files with no reviewable changes (1)
- packages/shared/src/constants/persona.constants.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-21T21:19:13.599Z
Learnt from: andrest50
Repo: linuxfoundation/lfx-v2-ui PR: 125
File: apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts:345-350
Timestamp: 2025-10-21T21:19:13.599Z
Learning: In the Angular meeting card component (apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts), when selecting between `summary.summary_data.edited_content` and `summary.summary_data.content`, the logical OR operator (`||`) is intentionally used instead of nullish coalescing (`??`) because empty string edited_content should fall back to the original content rather than being displayed as empty.
Applied to files:
apps/lfx-one/src/app/modules/meetings/meetings-dashboard/meetings-dashboard.component.htmlapps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.htmlapps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.htmlapps/lfx-one/src/app/modules/meetings/meetings-dashboard/meetings-dashboard.component.tsapps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.tsapps/lfx-one/src/app/modules/project/meetings/components/meeting-type-selection/meeting-type-selection.component.htmlapps/lfx-one/src/app/modules/project/meetings/components/meeting-type-selection/meeting-type-selection.component.ts
🧬 Code graph analysis (8)
apps/lfx-one/src/server/controllers/analytics.controller.ts (1)
apps/lfx-one/src/server/errors/index.ts (1)
ServiceValidationError(7-7)
apps/lfx-one/src/app/shared/components/project-selector/project-selector.component.ts (2)
apps/lfx-one/src/app/shared/components/sidebar/sidebar.component.ts (1)
Component(17-139)packages/shared/src/interfaces/project.interface.ts (1)
Project(54-103)
apps/lfx-one/src/app/shared/services/analytics.service.ts (1)
packages/shared/src/interfaces/analytics-data.interface.ts (2)
ProjectIssuesResolutionResponse(484-514)ProjectPullRequestsWeeklyResponse(550-570)
apps/lfx-one/src/app/layouts/project-layout/project-layout.component.ts (1)
apps/lfx-one/src/app/layouts/profile-layout/profile-layout.component.ts (1)
Component(19-236)
apps/lfx-one/src/app/layouts/main-layout/main-layout.component.ts (1)
packages/shared/src/interfaces/components.interface.ts (1)
SidebarMenuItem(267-288)
apps/lfx-one/src/server/services/project.service.ts (2)
packages/shared/src/constants/api.constants.ts (1)
NATS_CONFIG(28-43)packages/shared/src/interfaces/analytics-data.interface.ts (3)
ProjectIssuesResolutionResponse(484-514)ProjectPullRequestsWeeklyResponse(550-570)ProjectPullRequestsWeeklyRow(520-545)
apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts (1)
apps/lfx-one/src/app/shared/components/filter-pills/filter-pills.component.ts (1)
FilterOption(7-10)
apps/lfx-one/src/app/shared/components/sidebar/sidebar.component.ts (1)
packages/shared/src/interfaces/project.interface.ts (2)
Project(54-103)ProjectContext(167-174)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Agent
🔇 Additional comments (37)
CLAUDE.md (1)
146-146: Well-placed documentation for JIRA sprint field automation.This addition properly documents the JIRA sprint field (
customfield_10020) in the commit workflow section, making it easy for developers to reference when creating tickets. The guidance aligns with LFXV2-741 and improves workflow clarity for automated ticket processes.apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.html (2)
61-64: Verify icon property existence and fallback handling.The template assumes
metric.iconis always provided and contains a valid Font Awesome class string (e.g.,'fa-light fa-users'). Ensure the component's metric objects are always initialized with an icon property and have a sensible fallback or validation.Also applies to: 89-92
94-94: Chart height increase aligns with PR objectives.The height adjustment from
h-8toh-16improves readability for the charts, consistent with LFXV2-737 (increase chart height for readability).Also applies to: 94-94
apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.html (3)
65-66: Chart height aligns with design requirements.The change to
h-16(64px) for the chart container aligns with LFXV2-736 requirement for "bigger charts (64px)". Verify that chart rendering is correct at the new height and that no content is clipped.
49-56: Verify filtered data source and conditional icon rendering.The iteration now uses
filteredProgressItems()instead ofprogressItems(), and icons are conditionally rendered. Ensure:
filteredProgressItems()returns expected data structure with optionaliconproperty (aligns with LFXV2-739)- Empty filtered state is handled gracefully (e.g., no items when filters are applied)
- Icon class strings are valid Font Awesome classes (e.g.,
'fa-light fa-code-commit')
6-12: All required signals and methods are properly exported.Verification confirms the TypeScript component correctly defines all template requirements:
selectedFilter(signal),filteredProgressItems(computed),showFilterPills(computed),setFilter(method), andfilterOptions(array). All exports are properly marked asprotectedfor template access and the filtering logic is aligned with the expected implementation.apps/lfx-one/src/app/shared/services/project-context.service.ts (1)
42-50: clearProject implementation is consistent and SSR‑safeNulling the
selectedProjectsignal and guardinglocalStorage.removeItemwith atypeof localStorage !== 'undefined'check is a good pattern and aligns with howloadFromStorageis already defensive.apps/lfx-one/src/app/app.component.ts (1)
13-18: Header removal from root imports aligns with layout‑owned headerDropping
HeaderComponentfromimportshere is consistent with moving the header into individual layouts; the remaining imports are sufficient for this component.apps/lfx-one/src/server/services/project.service.ts (2)
304-308: Adding an explicit NATS request timeout is a good reliability winUsing
NATS_CONFIG.REQUEST_TIMEOUTon theEMAIL_TO_USERNAMErequest keeps this call from hanging indefinitely and lines up with the existing timeout‑based error handling below.
660-717: Slug‑based PR velocity query and default slug fallback look soundThe optional
projectSlugwith fallback to the first project’s slug and theproject_segmentsCTE/COALESCE(...) = ?filter give you a consistent “foundation‑level via slug hierarchy” behavior for PR metrics. The placeholder/parameter counts also line up correctly.apps/lfx-one/src/server/controllers/analytics.controller.ts (2)
282-307: projectSlug‑based issues resolution endpoint is consistent and validatedReading
projectSlugfrom the query, enforcing it viaServiceValidationError.forField, and passing it through toProjectService.getProjectIssuesResolutionaligns with the new slug‑first analytics flow. The updated logging payload (project_slug) matches the new parameter.
317-341: PR‑weekly endpoint correctly migrated to required projectSlugThe weekly PR endpoint now requires
projectSlug, validates it, and forwards it togetProjectPullRequestsWeekly, with logging updated toproject_slug. This matches the server/service changes and avoids the old projectId coupling.apps/lfx-one/src/app/modules/project/meetings/components/meeting-type-selection/meeting-type-selection.component.ts (2)
48-68: LGTM! Well-structured computed options with filtering.The filtered meeting type options are cleanly computed and augmented with metadata. The explicit filtering to MAINTAINERS, TECHNICAL, and OTHER aligns with the PR objectives for role-based meeting type selection.
147-147: LGTM! Proper access control filtering.The additional
project.writerfilter ensures users only see child projects where they have write permissions, which is appropriate for meeting creation.apps/lfx-one/src/app/modules/project/meetings/components/meeting-type-selection/meeting-type-selection.component.html (1)
78-96: LGTM! Clean Meeting Access section.The new Meeting Access section is well-structured with clear labeling and appropriate use of the toggle component for the restricted meeting control.
apps/lfx-one/src/app/layouts/project-layout/project-layout.component.ts (1)
11-11: LGTM! Header integration aligned with layout refactor.The HeaderComponent import and inclusion in the standalone imports array properly enables the header in the project layout, consistent with the PR's objective to move header control to individual layouts.
Also applies to: 19-19
apps/lfx-one/src/app/layouts/project-layout/project-layout.component.html (1)
4-5: LGTM! Header placement correct.The header component is properly positioned at the top of the project layout template, consistent with the layout refactoring objectives.
apps/lfx-one/src/app/app.component.html (1)
5-5: LGTM! Root template simplified appropriately.Removing the header from the root component and simplifying to just the router outlet aligns perfectly with the PR's objective to move header control to individual layouts.
packages/shared/src/interfaces/components.interface.ts (1)
334-337: LGTM! Interface extended for dashboard filtering and icons.The optional
categoryandiconproperties are well-typed and support the PR's objectives to add filtering capabilities and icon display to progress metrics. The optional nature ensures backward compatibility.apps/lfx-one/src/app/layouts/profile-layout/profile-layout.component.ts (1)
12-12: LGTM! Consistent header integration.The HeaderComponent import and inclusion follows the same pattern as the project layout, maintaining consistency across the layout refactoring.
Also applies to: 22-22
apps/lfx-one/src/app/shared/components/persona-selector/persona-selector.component.ts (1)
36-43: Code is properly marked with TODO comments, but verify alternative tracking mechanism is in place.The hardcoded foundation for board-member persona is correctly marked with a clear TODO comment. Related demo code patterns are consistent across multiple components (sidebar.component.ts also has matching TODOs). However, GitHub issues are disabled in this repository, making the suggested tracking approach infeasible.
Before production release, ensure you have an alternative tracking mechanism (JIRA, ADO, or other) in place for this demo code removal, or document where this is being tracked.
apps/lfx-one/src/app/layouts/profile-layout/profile-layout.component.html (1)
4-5: LGTM! Header integration aligns with architecture goals.The addition of the
lfx-headercomponent to the profile layout follows the pattern established in other layouts and aligns with the PR objective to move headers from the global app to individual layout components.apps/lfx-one/src/app/modules/dashboards/board-member/board-member-dashboard.component.html (1)
6-10: LGTM! Conditional rendering improves UX.The foundation header is now appropriately guarded behind
selectedFoundation(), ensuring it only displays when a foundation context exists. The use of optional chaining onselectedFoundation()?.nameis defensive and follows best practices.apps/lfx-one/src/app/modules/meetings/meetings-dashboard/meetings-dashboard.component.html (1)
8-16: LGTM! Conditional button rendering aligns with project context.The Create Meeting button is appropriately gated behind maintainer status and non-foundation project selection. The optional chaining and fallback in the route path (
project()?.slug || '') provides defensive handling, thoughisNonFoundationProjectSelected()likely ensures a valid project exists.apps/lfx-one/src/app/shared/components/project-selector/project-selector.component.scss (1)
11-11: LGTM! Shadow styling enhances panel visual design.The switch to
shadow-lgaligns with the updated panel design and provides a cleaner, more modern appearance.apps/lfx-one/src/app/modules/dashboards/core-developer/core-developer-dashboard.component.html (1)
6-10: LGTM! Consistent conditional rendering pattern.The foundation header guard matches the implementation in other dashboards and appropriately handles the absence of a selected foundation.
apps/lfx-one/src/app/layouts/main-layout/main-layout.component.html (1)
4-33: LGTM! Coordinated layout adjustments for tighter sidebar.The changes systematically update sidebar width from 72 to 64 units across desktop and mobile views, with matching adjustments to main content margins and padding. The removal of the top offset (6rem → 0) aligns with the header relocation to individual layouts.
apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.html (1)
6-10: LGTM! Consistent foundation header handling.The conditional rendering of the foundation header follows the established pattern across all dashboard components, ensuring a consistent user experience.
apps/lfx-one/src/app/layouts/main-layout/main-layout.component.ts (2)
28-45: LGTM! Navigation updates improve clarity and accessibility.The sidebar navigation changes enhance the user experience:
- "Overview" is more descriptive than "Home"
- Icon updates (grid for overview, calendar for meetings, folder for projects) provide better visual semantics
- New "Projects" item improves direct access to project management
- All items follow the
SidebarMenuIteminterface correctly
47-60: LGTM! Footer navigation streamlined to essential items.The footer now focuses on user-centric actions (Settings and Profile), creating a cleaner navigation experience. The removal of Documentation, Submit a Ticket, and Changelog suggests these may be available through other means.
apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.ts (1)
4-23: Maintainer dashboard simplification looks clean and aligned with foundation contextUsing
inject(ProjectContextService)with a simpleselectedFoundationcomputed alias keeps this component lean and aligned with the new foundation-driven architecture. No issues spotted with the imports or signal wiring.apps/lfx-one/src/app/shared/services/analytics.service.ts (1)
200-244: Slug-based analytics methods look correct; just ensure backend contract matchesSwitching
getProjectIssuesResolutionandgetProjectPullRequestsWeeklyto acceptprojectSlugand sending{ projectSlug }as query params is consistent with the PR’s slug migration. The error fallbacks remain intact and safe.Please just double-check that the server endpoints now expect
projectSlug(and not the oldprojectId) in the query string so we don’t get silent empty datasets.apps/lfx-one/src/app/modules/meetings/meetings-dashboard/meetings-dashboard.component.ts (1)
13-55: Persona/project context wiring for meetings looks correct and matches the new UXUsing
project = computed(() => selectedProject() || selectedFoundation())gives the dashboard a unified project context, whileisNonFoundationProjectSelectedcorrectly keys offselectedProject()to distinguish foundation vs child projects.isMaintainerderived fromPersonaService.currentPersona()cleanly supports persona-based gating in the template.This lines up with the requirement to show “Create Meeting” only when a maintainer has a specific (non-foundation) project selected.
apps/lfx-one/src/app/shared/components/sidebar/sidebar.component.html (1)
5-47: Sidebar layout structure looks solidThe full-height sidebar with top logo, project selector, main nav, and bottom persona/footer sections is logically organized and aligns with the described architecture changes. No functional issues spotted in this structural refactor.
apps/lfx-one/src/app/shared/components/sidebar/sidebar.component.ts (1)
8-11: Persona and selector integration wiring looks correctImports and DI for
PersonaService,PersonaSelectorComponent, andProjectSelectorComponentare correctly set up and match how the template uses them. No issues with the standalone component configuration.Also applies to: 20-21, 25-28
apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts (2)
11-12: Filter pills integration is wired correctlyImporting
FilterPillsComponent/FilterOptionand addingFilterPillsComponenttoimportsis consistent with the new filtering logic. No issues here.Also applies to: 37-38
87-99: Scroll reset on filter change is a nice UX touchResetting
scrollLeftto 0 insetFilterguarded byif (this.progressScrollContainer)is a simple and effective way to keep the carousel aligned when filters change. No issues here.
...dules/dashboards/components/organization-involvement/organization-involvement.component.html
Show resolved
Hide resolved
...lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.html
Show resolved
Hide resolved
...les/project/meetings/components/meeting-type-selection/meeting-type-selection.component.html
Show resolved
Hide resolved
apps/lfx-one/src/app/shared/components/project-selector/project-selector.component.html
Show resolved
Hide resolved
Signed-off-by: Asitha de Silva <[email protected]>
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 (1)
apps/lfx-one/src/app/shared/components/project-selector/project-selector.component.html (1)
94-97: SVG duplication persists.The inline default project logo SVG is repeated across the template (also at lines 15-16, 126-127). Extract to a shared component or constant for maintainability.
🧹 Nitpick comments (1)
apps/lfx-one/src/app/shared/components/sidebar/sidebar.component.ts (1)
132-135: Consider using Angular Router instead of window.location.Using
window.location.href = '/'forces a full page reload, which loses Angular's SPA benefits and may cause unnecessary re-initialization. Unless a full reload is specifically required for state reset, consider using Angular Router for navigation:protected onLogoClick(): void { this.router.navigate(['/']); }Note: The Router is already injected in related services (PersonaService), so it's available for use here as well.
📜 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 (5)
apps/lfx-one/src/app/shared/components/project-selector/project-selector.component.html(2 hunks)apps/lfx-one/src/app/shared/components/sidebar/sidebar.component.ts(4 hunks)apps/lfx-one/src/app/shared/services/persona.service.ts(2 hunks)apps/lfx-one/src/app/shared/services/project-context.service.ts(3 hunks)apps/lfx-one/src/server/services/project.service.ts(4 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
apps/lfx-one/src/app/shared/components/sidebar/sidebar.component.ts (2)
apps/lfx-one/src/server/services/project.service.ts (1)
ProjectService(32-770)packages/shared/src/interfaces/project.interface.ts (2)
Project(54-103)ProjectContext(167-174)
apps/lfx-one/src/app/shared/services/persona.service.ts (2)
apps/lfx-one/src/app/shared/services/project-context.service.ts (1)
Injectable(7-95)packages/shared/src/interfaces/persona.interface.ts (1)
PersonaType(8-8)
apps/lfx-one/src/server/services/project.service.ts (2)
packages/shared/src/constants/api.constants.ts (1)
NATS_CONFIG(28-43)packages/shared/src/interfaces/analytics-data.interface.ts (3)
ProjectIssuesResolutionResponse(484-514)ProjectPullRequestsWeeklyResponse(550-570)ProjectPullRequestsWeeklyRow(520-545)
🔇 Additional comments (10)
apps/lfx-one/src/app/shared/components/project-selector/project-selector.component.html (2)
41-42: Signal binding correctly implemented.The binding now preserves the signal instance by reading with
searchQuery()and updating viasearchQuery.set(), avoiding the critical issue flagged in previous reviews where[(ngModel)]would have overwritten the signal object.
15-16: LFX One branding correctly applied.The fallback logo now uses the new LFX One branding asset, aligning with the updated brand identity.
apps/lfx-one/src/server/services/project.service.ts (3)
307-307: NATS subject updated for email resolution.The subject change from
EMAIL_TO_SUBtoEMAIL_TO_USERNAMEaligns with updated NATS topic naming while maintaining backward-compatible return value semantics for backend operations.
616-634: Same slug validation concern applies here.Like the daily query, this aggregated query will silently return empty results if the
projectSlugdoesn't exist inactive_segments. The default fallback values (lines 646-651) will mask the difference between "no data available" and "invalid slug."
688-708: Slug validation concern applies; fallback logic helps when slug is optional.While the same empty-result issue exists for invalid slugs, the upstream fallback logic (lines 670-683) that retrieves the first project when no slug is provided adds some resilience for the optional parameter case.
apps/lfx-one/src/app/shared/services/persona.service.ts (1)
34-38: Board-member persona correctly clears child project context.Clearing the child project selection when switching to board-member persona ensures board members operate exclusively at the foundation level, as intended by the architecture changes.
apps/lfx-one/src/app/shared/services/project-context.service.ts (2)
29-42: Foundation and project selection are now mutually exclusive.The updated
setFoundationandsetProjectmethods enforce mutual exclusivity by clearing the opposite selection, ensuring only one context (foundation or child project) is active at a time. This aligns with the foundation-based architecture.
47-62: Clear methods properly clean up state.The new
clearProject()andclearFoundation()methods correctly reset both the signal state and localStorage, with appropriate SSR-safe guards.apps/lfx-one/src/app/shared/components/sidebar/sidebar.component.ts (2)
37-60: Default foundation selection enhances UX.Automatically selecting a default foundation (preferring 'tlf', falling back to the first available) when none is selected provides a better initial experience and prevents empty-state scenarios.
105-127: Foundation vs. child project detection logic is sound.The logic correctly distinguishes foundation-level projects (no parent or orphaned parent) from child projects, then routes them to the appropriate context storage method. This maintains the foundation-based architecture integrity.
Signed-off-by: Asitha de Silva <[email protected]>
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts (1)
48-48: Update stale comment.The comment references "project ID" but line 57 actually retrieves the project or foundation slug, not an ID.
Apply this diff to correct the comment:
- // Get project ID from context service + // Get project or foundation slug from context service
🧹 Nitpick comments (1)
apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.ts (1)
22-22: Consider renaming for clarity.The computed property is named
selectedProjectbut returnsselectedFoundation() || selectedProject(), prioritizing the foundation over the project. This naming could confuse future maintainers who might expect it to return only a project. Consider renaming toselectedContextordisplayedEntityto better reflect that it can return either a foundation or a project.Apply this diff to improve naming clarity:
- public readonly selectedProject = computed(() => this.projectContextService.selectedFoundation() || this.projectContextService.selectedProject()); + public readonly selectedContext = computed(() => this.projectContextService.selectedFoundation() || this.projectContextService.selectedProject());Don't forget to update the template reference from
selectedProject()toselectedContext()inmaintainer-dashboard.component.html.
📜 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 (3)
apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts(7 hunks)apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.html(1 hunks)apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.ts(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-21T21:19:13.599Z
Learnt from: andrest50
Repo: linuxfoundation/lfx-v2-ui PR: 125
File: apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts:345-350
Timestamp: 2025-10-21T21:19:13.599Z
Learning: In the Angular meeting card component (apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts), when selecting between `summary.summary_data.edited_content` and `summary.summary_data.content`, the logical OR operator (`||`) is intentionally used instead of nullish coalescing (`??`) because empty string edited_content should fall back to the original content rather than being displayed as empty.
Applied to files:
apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.tsapps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.html
🧬 Code graph analysis (1)
apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts (1)
apps/lfx-one/src/app/shared/components/filter-pills/filter-pills.component.ts (1)
FilterOption(7-10)
🔇 Additional comments (7)
apps/lfx-one/src/app/modules/dashboards/maintainer/maintainer-dashboard.component.html (1)
6-10: Foundation guard implementation looks good.The conditional rendering correctly implements the foundation existence guard as specified in LFXV2-735, ensuring the header only displays when a project or foundation is selected.
apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts (6)
57-57: LGTM: Slug-based identification.The computed property correctly prioritizes foundation slug over project slug and properly handles undefined values in the data initialization methods.
85-91: LGTM: Persona-aware filter UI.The filter pills are correctly scoped to the maintainer persona and the filter options align with the requirements.
93-99: LGTM: Filter state management with scroll reset.The method correctly updates the filter state and provides a good user experience by resetting the scroll position. The defensive null-check prevents potential runtime errors.
265-280: LGTM: Icon, category, and color consistency.The additions of the icon and category properties support the new filtering feature, and the color change to
#0094FFfor "Opened Issues" aligns with the blue theme used for code-related metrics.
451-476: LGTM: Reactive slug-based data fetching.The data initialization correctly uses
toObservableto reactively watch forprojectSlugchanges and handles null/undefined values gracefully by returning empty data. The migration fromprojectIdtoprojectSlugaligns with the PR objectives.
478-501: LGTM: Consistent reactive pattern.The data initialization follows the same sound reactive pattern as
initializeProjectIssuesResolutionData, ensuring consistent slug-based data fetching across both project-level metrics.
| protected readonly selectedFilter = signal<string>('all'); | ||
| protected readonly filteredProgressItems = computed(() => { | ||
| const items = this.progressItems(); | ||
| const filter = this.selectedFilter(); | ||
| const persona = this.personaService.currentPersona(); | ||
|
|
||
| // Only apply filtering for maintainer persona | ||
| if (persona !== 'maintainer') { | ||
| return items; | ||
| } | ||
|
|
||
| if (filter === 'all') { | ||
| return items; | ||
| } | ||
|
|
||
| return items.filter((item) => item.category === filter); | ||
| }); |
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.
🧩 Analysis chain
Verify category coverage for all filter options.
The filtering logic is correct and appropriately restricts filtering to the maintainer persona. However, ensure that metrics have the appropriate category property assigned to support all filter options ('code' and 'projectHealth').
Currently, only 'Open vs Closed Issues Trend' has a category assigned (line 272). Verify that other metrics either belong to one of these categories or are intentionally excluded from filtered views.
Run the following script to check which metrics have categories assigned:
🏁 Script executed:
#!/bin/bash
# Description: Search for category assignments in progress metrics
# Search for category property assignments in this component
rg -n "category:" apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts
# Search for category definitions in shared constants
rg -n "category" packages/shared/src/lib/constants/progress-metrics.constants.tsLength of output: 131
🏁 Script executed:
#!/bin/bash
# Find where progressItems signal is initialized or populated
rg -n "progressItems\s*=" apps/lfx-one/src/app/modules/dashboards/components/recent-progress/ -A 5
# Search for all metric definitions in the component directory
rg -n "category" apps/lfx-one/src/app/modules/dashboards/components/recent-progress/ -B 2 -A 2
# Find files related to progress metrics
fd "progress.*metric" apps/lfx-one/
# Search for projectHealth references
rg -n "projectHealth" apps/lfx-one/src/app/modules/dashboards/components/recent-progress/ -C 3Length of output: 3697
🏁 Script executed:
#!/bin/bash
# Find the initializeProgressItems method implementation
ast-grep --pattern $'protected initializeProgressItems() {
$$$
}'
# Also search with rg as backup
rg -n "initializeProgressItems" apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts -A 200 | head -250Length of output: 9759
🏁 Script executed:
#!/bin/bash
# Find where MAINTAINER_PROGRESS_METRICS and CORE_DEVELOPER_PROGRESS_METRICS are defined
rg -n "MAINTAINER_PROGRESS_METRICS|CORE_DEVELOPER_PROGRESS_METRICS" apps/lfx-one/src/app/modules/dashboards/components/recent-progress/ -B 2 -A 15
# Find transformProjectPullRequestsWeekly to check if it has category
rg -n "transformProjectPullRequestsWeekly" apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts -A 80 | head -100Length of output: 9518
🏁 Script executed:
#!/bin/bash
# Find the constants file with MAINTAINER_PROGRESS_METRICS and CORE_DEVELOPER_PROGRESS_METRICS
fd -type f "constants" packages/shared/src/lib/ | head -20
# Search more broadly for these constants
rg -n "MAINTAINER_PROGRESS_METRICS\s*=" packages/shared/ -A 20Length of output: 170
🏁 Script executed:
#!/bin/bash
# Search for the constants definitions more broadly
rg -n "MAINTAINER_PROGRESS_METRICS\s*=" . -A 20
# Also search for where these are exported
rg -n "export.*MAINTAINER_PROGRESS_METRICS" . -A 20
# Find all .ts files in shared constants
find packages/shared/src/lib -name "*.ts" -type f | grep -i constant | head -20Length of output: 2176
🏁 Script executed:
#!/bin/bash
# Get complete MAINTAINER_PROGRESS_METRICS definition
rg -n "export const MAINTAINER_PROGRESS_METRICS" ./packages/shared/src/constants/progress-metrics.constants.ts -A 300 | head -400
# Get complete CORE_DEVELOPER_PROGRESS_METRICS definition
rg -n "export const CORE_DEVELOPER_PROGRESS_METRICS" ./packages/shared/src/constants/progress-metrics.constants.ts -A 200Length of output: 13829
Fix missing category properties in transform methods to support filtering.
The filtering logic is correctly scoped to maintainers, but it fails because transform methods strip category assignments from metrics. Only transformProjectIssuesResolution (line 272) includes a category; the other four methods return objects without category properties, breaking filtering entirely.
For maintainers:
- 'code' filter shows only 'Open vs Closed Issues Trend' (1/3 code metrics)
- 'projectHealth' filter shows no results (0/3 project health metrics)
Add category property to the return objects of:
transformActiveWeeksStreak(lines 111-151)transformPullRequestsMerged(lines 153-197)transformCodeCommits(lines 199-243)transformProjectPullRequestsWeekly(lines 328-407)
Align categories with constants: 'Active Weeks Streak' → 'code', 'Pull Requests Merged' → 'code', 'Code Commits' → 'code', 'PR Review & Merge Velocity' → 'code'.
Additionally, CORE_DEVELOPER_PROGRESS_METRICS (packages/shared/src/constants/progress-metrics.constants.ts, lines 203-359) lack categories entirely, so filtering won't work for core developers either.
Summary
Major refactoring to support foundation-based architecture with enhanced dashboards, improved navigation, and better project selector functionality.
Key Changes
Related Tickets
This PR addresses the following JIRA tickets:
Additional Improvements
Test Plan
Generated with Claude Code