Skip to content

Commit 08a4c44

Browse files
authored
feat(dashboards): refactor metrics to individual signals and update ui (#187)
* feat(dashboards): refactor metrics to individual signals and update ui LFXV2-836 LFXV2-837 - Refactor foundation-health, organization-involvement, and recent-progress components to use individual computed signals per metric card - Add private initialization methods for computed signals - Add per-card loading states instead of global loading - Update metric-card component to support loading property - Update Ask LFX Lens button to use gradient styling - Fix responsive layout issues in dashboard components 🤖 Generated with [Claude Code](https://claude.ai/code) Signed-off-by: Asitha de Silva <[email protected]> * fix(ui): prevent NaN in health scores and simplify hover - Add guard for maxCount === 0 to prevent NaN in heightPx calculation - Remove redundant hover:border and hover:border-solid classes 🤖 Generated with [Claude Code](https://claude.ai/code) Signed-off-by: Asitha de Silva <[email protected]> --------- Signed-off-by: Asitha de Silva <[email protected]>
1 parent 8285184 commit 08a4c44

19 files changed

+692
-451
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ <h1>{{ selectedFoundation()?.name }} Overview</h1>
1111

1212
<!-- Organization Selector -->
1313
@if (showOrganizationSelector()) {
14-
<div class="mb-6 flex items-center gap-4" data-testid="organization-selector">
14+
<div class="mb-6 flex flex-wrap items-center gap-4" data-testid="organization-selector">
1515
<label for="organization-select" class="text-sm font-semibold text-gray-700">Organization:</label>
1616
<lfx-select
1717
[form]="form"
@@ -23,7 +23,7 @@ <h1>{{ selectedFoundation()?.name }} Overview</h1>
2323
filterPlaceholder="Search organizations..."
2424
placeholder="Select an organization"
2525
[showClear]="false"
26-
styleClass="min-w-[300px]"
26+
styleClass="w-full sm:min-w-[300px]"
2727
inputId="organization-select"
2828
data-testid="organization-select" />
2929
</div>

apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.html

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,21 @@
22
<!-- SPDX-License-Identifier: MIT -->
33

44
<section data-testid="foundation-health-section">
5-
<div class="flex items-center justify-between mb-4">
6-
<div class="flex flex-col md:flex-row md:items-center gap-3">
7-
<h2>{{ title() }}</h2>
5+
<div class="flex flex-wrap gap-3 items-end justify-between mb-4">
6+
<div class="flex flex-col gap-3">
7+
<div class="flex gap-3 flex-wrap">
8+
<h2 class="mb-0">{{ title() }}</h2>
9+
<!-- Data Copilot Button -->
10+
<lfx-data-copilot></lfx-data-copilot>
11+
</div>
812

9-
<div class="flex items-center gap-2">
13+
<div class="flex flex-wrap items-center gap-2">
1014
<!-- Filter Pills -->
1115
<lfx-filter-pills
1216
[options]="filterOptions"
1317
[selectedFilter]="selectedFilter()"
1418
(filterChange)="handleFilterChange($event)"
1519
data-testid="foundation-health-filters"></lfx-filter-pills>
16-
17-
<!-- Data Copilot Button -->
18-
<lfx-data-copilot [includeOrganizationId]="false" [includeOrganizationName]="false"></lfx-data-copilot>
1920
</div>
2021
</div>
2122

@@ -49,19 +50,11 @@ <h2>{{ title() }}</h2>
4950
<p class="text-xs text-gray-500">Use the project selector in the sidebar to choose a foundation</p>
5051
</div>
5152
</div>
52-
} @else if (isLoading() && !metricCards()) {
53-
<!-- Loading State -->
54-
<div class="flex items-center justify-center p-12">
55-
<div class="text-center space-y-3">
56-
<i class="fa-light fa-spinner-third fa-spin text-4xl text-blue-500"></i>
57-
<p class="text-sm text-gray-500">Loading foundation health data...</p>
58-
</div>
59-
</div>
6053
} @else {
6154
<!-- Carousel Container -->
6255
<div class="overflow-hidden">
6356
<div #carouselScroll class="flex gap-4 overflow-x-auto pb-2 hide-scrollbar scroll-smooth" data-testid="foundation-health-carousel">
64-
@for (card of metricCards(); track card.title) {
57+
@for (card of metricCards(); track card.testId) {
6558
@switch (card.customContentType) {
6659
<!-- Bar Chart - Use shared metric card -->
6760
@case ('bar-chart') {
@@ -73,7 +66,8 @@ <h2>{{ title() }}</h2>
7366
[chartData]="card.chartData"
7467
[chartOptions]="barChartOptions"
7568
[value]="card.value"
76-
[subtitle]="card.subtitle"></lfx-metric-card>
69+
[subtitle]="card.subtitle"
70+
[loading]="card.loading"></lfx-metric-card>
7771
}
7872

7973
<!-- Top Projects List - Custom content -->
@@ -84,7 +78,8 @@ <h2>{{ title() }}</h2>
8478
[testId]="card.testId"
8579
[chartType]="card.chartType"
8680
[value]="card.value"
87-
[subtitle]="card.subtitle">
81+
[subtitle]="card.subtitle"
82+
[loading]="card.loading">
8883
<ng-template #customContent>
8984
@if (card.topProjects) {
9085
<div class="space-y-0.5 p-0 pl-[60px] m-0 mb-[5px]">
@@ -109,7 +104,8 @@ <h2>{{ title() }}</h2>
109104
[testId]="card.testId"
110105
[chartType]="card.chartType"
111106
[value]="card.value"
112-
[subtitle]="card.subtitle">
107+
[subtitle]="card.subtitle"
108+
[loading]="card.loading">
113109
<ng-template #customContent>
114110
@if (card.busFactor) {
115111
<div class="flex-1 flex flex-col justify-end pb-2">
@@ -139,7 +135,8 @@ <h2>{{ title() }}</h2>
139135
[testId]="card.testId"
140136
[chartType]="card.chartType"
141137
[value]="card.value"
142-
[subtitle]="card.subtitle">
138+
[subtitle]="card.subtitle"
139+
[loading]="card.loading">
143140
<ng-template #customContent>
144141
@if (card.healthScores) {
145142
<div class="flex-1 flex flex-col justify-end p-0">
@@ -173,7 +170,8 @@ <h2>{{ title() }}</h2>
173170
[chartData]="card.chartData"
174171
[chartOptions]="card.chartOptions"
175172
[value]="card.value"
176-
[subtitle]="card.subtitle"></lfx-metric-card>
173+
[subtitle]="card.subtitle"
174+
[loading]="card.loading"></lfx-metric-card>
177175
}
178176
}
179177
}

0 commit comments

Comments
 (0)