Skip to content

Commit f62101e

Browse files
authored
feat(dashboards): add metrics api integration and monthly charts (#188)
* feat(dashboards): add metrics api integration and monthly charts - Add company bus factor API integration for foundation health dashboard - Add event attendance monthly API with cumulative trend data - Add foundation filtering to organization maintainers, contributors, and certified employees endpoints - Add monthly trend charts to organization involvement dashboard metrics - Update interfaces with monthly data arrays - Remove hardcoded mock chart data from constants LFXV2-845 LFXV2-846 LFXV2-847 LFXV2-848 Signed-off-by: Asitha de Silva <[email protected]> * refactor(dashboards): remove unused analytics code and interfaces Remove deprecated code that is no longer used after dashboard refactoring: - Frontend: Remove getOrganizationEventsOverview and getProjects methods - Backend: Remove corresponding routes, controller and service methods - Interfaces: Remove 7 unused row/response types replaced by monthly versions Generated with [Claude Code](https://claude.ai/code) Signed-off-by: Asitha de Silva <[email protected]> * fix(dashboards): hide membership tier filter on non-all tabs Only show Membership Tier card when ALL filter is selected in organization involvement section. Generated with [Claude Code](https://claude.ai/code) Signed-off-by: Asitha de Silva <[email protected]> * style(ui): update lfx lens button with new design and stacked icon - Update button styling to pill shape with solid blue background - Replace microchip-ai icon with Font Awesome stacked icons - Use fa-comment with fa-sparkle overlay for composite icon LFXV2-845 Signed-off-by: Asitha de Silva <[email protected]> * refactor(ui): use committee label constant for dynamic labeling - Replace hardcoded "Committee" with COMMITTEE_LABEL constant - Update committee-members component header and empty state - Update meeting registrants manager status filter - Update registrant modal info message and tooltip LFXV2-845 Signed-off-by: Asitha de Silva <[email protected]> * style(ui): improve card hover states and visual distinction LFXV2-845 - Add hover border effects to meeting cards and pending actions - Use distinct colors for metrics charts (emerald, amber, violet) - Remove redundant Today/Upcoming section headers from meetings - Update LFX Lens button to outlined style with lighter icons - Remove redundant leading-normal from heading styles Signed-off-by: Asitha de Silva <[email protected]> * fix(dashboards): format contributors mentored tooltip dates LFXV2-845 Update Contributors Mentored chart tooltip to match Active Contributors format with properly formatted date labels (e.g., "Dec 1, 2024") and custom tooltip callbacks. Signed-off-by: Asitha de Silva <[email protected]> * fix(ui): committee member details label Signed-off-by: Asitha de Silva <[email protected]> --------- Signed-off-by: Asitha de Silva <[email protected]>
1 parent 08a4c44 commit f62101e

File tree

23 files changed

+972
-626
lines changed

23 files changed

+972
-626
lines changed

apps/lfx-one/src/app/modules/committees/components/committee-members/committee-members.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<!-- Committee Members Section -->
66
<lfx-card>
77
<div class="flex justify-between gap-4 mb-8">
8-
<h3 class="text-lg font-medium text-gray-900">Committee Members</h3>
8+
<h3 class="text-lg font-medium text-gray-900">{{ committeeLabel.singular }} Members</h3>
99
<!-- Add Member Button -->
1010
@if (committee()?.writer) {
1111
<lfx-button label="Add Member" icon="fa-light fa-user-plus" size="small" severity="secondary" (onClick)="openAddMemberDialog()"> </lfx-button>
@@ -177,7 +177,7 @@ <h3 class="text-lg font-medium text-gray-900">Committee Members</h3>
177177
<div class="text-center">
178178
<i class="fa-light fa-users text-4xl text-gray-400 mb-4"></i>
179179
<h3 class="text-lg font-medium text-gray-900 mb-2">No Members Yet</h3>
180-
<p class="text-gray-600">This committee doesn't have any members yet.</p>
180+
<p class="text-gray-600">This {{ committeeLabel.singular }} doesn't have any members yet.</p>
181181
</div>
182182
</td>
183183
</tr>

apps/lfx-one/src/app/modules/committees/components/committee-members/committee-members.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { MenuComponent } from '@components/menu/menu.component';
1212
import { SelectButtonComponent } from '@components/select-button/select-button.component';
1313
import { SelectComponent } from '@components/select/select.component';
1414
import { TableComponent } from '@components/table/table.component';
15+
import { COMMITTEE_LABEL } from '@lfx-one/shared/constants';
1516
import { Committee, CommitteeMember } from '@lfx-one/shared/interfaces';
1617
import { CommitteeService } from '@services/committee.service';
1718
import { AnimateOnScrollModule } from 'primeng/animateonscroll';
@@ -63,6 +64,7 @@ export class CommitteeMembersComponent implements OnInit {
6364
public selectedMember: WritableSignal<CommitteeMember | null>;
6465
public isDeleting: WritableSignal<boolean>;
6566
public memberActionMenuItems: MenuItem[] = [];
67+
public committeeLabel = COMMITTEE_LABEL;
6668

6769
// Filter-related variables
6870
public filterForm: FormGroup;

apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<!-- SPDX-License-Identifier: MIT -->
33

44
<!-- Card wrapper with border and shadow -->
5-
<div class="bg-white rounded-xl border shadow-md" data-testid="dashboard-meeting-card">
5+
<div class="bg-white rounded-xl border shadow-md hover:border-blue-500 transition-all" data-testid="dashboard-meeting-card">
66
<div class="p-4 space-y-3">
77
<!-- Header with meeting type and project badges -->
88
<div class="flex items-center gap-2 flex-wrap">

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<div class="flex gap-3 flex-wrap">
88
<h2 class="mb-0">{{ title() }}</h2>
99
<!-- Data Copilot Button -->
10-
<lfx-data-copilot></lfx-data-copilot>
10+
<lfx-data-copilot [includeOrganizationId]="false" [includeOrganizationName]="false"></lfx-data-copilot>
1111
</div>
1212

1313
<div class="flex flex-wrap items-center gap-2">
@@ -114,11 +114,11 @@ <h2 class="mb-0">{{ title() }}</h2>
114114
<div class="text-xs font-medium text-slate-700">
115115
{{ card.busFactor.topCompaniesCount }} Companies ({{ card.busFactor.topCompaniesPercentage }}%)
116116
</div>
117-
<div class="h-4 rounded-l-sm bg-gray-300"></div>
117+
<div class="h-4 rounded-l-sm bg-blue-500"></div>
118118
</div>
119119
<div [style.width.%]="card.busFactor.otherCompaniesPercentage" class="flex flex-col gap-1">
120120
<div class="text-xs text-slate-600 text-right">{{ card.busFactor.otherCompaniesCount }} Other Companies</div>
121-
<div class="h-4 bg-slate-200 rounded-r-sm"></div>
121+
<div class="h-4 bg-blue-200 rounded-r-sm"></div>
122122
</div>
123123
</div>
124124
</div>

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

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,20 @@ import { toObservable, toSignal } from '@angular/core/rxjs-interop';
77
import { DataCopilotComponent } from '@app/shared/components/data-copilot/data-copilot.component';
88
import { FilterOption, FilterPillsComponent } from '@components/filter-pills/filter-pills.component';
99
import { MetricCardComponent } from '@components/metric-card/metric-card.component';
10-
import { BASE_BAR_CHART_OPTIONS, BASE_LINE_CHART_OPTIONS, COMPANY_BUS_FACTOR, lfxColors, PRIMARY_FOUNDATION_HEALTH_METRICS } from '@lfx-one/shared/constants';
10+
import { BASE_BAR_CHART_OPTIONS, BASE_LINE_CHART_OPTIONS, lfxColors, PRIMARY_FOUNDATION_HEALTH_METRICS } from '@lfx-one/shared/constants';
1111
import { hexToRgba } from '@lfx-one/shared/utils';
1212
import { AnalyticsService } from '@services/analytics.service';
1313
import { ProjectContextService } from '@services/project-context.service';
1414
import { catchError, map, of, switchMap, tap } from 'rxjs';
1515

16-
import type { DashboardMetricCard, HealthEventsMonthlyResponse, TopProjectDisplay, UniqueContributorsDailyResponse } from '@lfx-one/shared/interfaces';
16+
import type {
17+
CompanyBusFactor,
18+
DashboardMetricCard,
19+
FoundationCompanyBusFactorResponse,
20+
HealthEventsMonthlyResponse,
21+
TopProjectDisplay,
22+
UniqueContributorsDailyResponse,
23+
} from '@lfx-one/shared/interfaces';
1724
import type { TooltipItem } from 'chart.js';
1825

1926
@Component({
@@ -35,6 +42,7 @@ export class FoundationHealthComponent {
3542
private readonly totalProjectsLoading = signal(true);
3643
private readonly totalMembersLoading = signal(true);
3744
private readonly softwareValueLoading = signal(true);
45+
private readonly companyBusFactorLoading = signal(true);
3846
private readonly maintainersLoading = signal(true);
3947
private readonly healthScoresLoading = signal(true);
4048
private readonly activeContributorsLoading = signal(true);
@@ -47,6 +55,7 @@ export class FoundationHealthComponent {
4755
private readonly totalProjectsData = this.initializeTotalProjectsData();
4856
private readonly totalMembersData = this.initializeTotalMembersData();
4957
private readonly softwareValueData = this.initializeSoftwareValueData();
58+
private readonly companyBusFactorData = this.initializeCompanyBusFactorData();
5059
private readonly maintainersData = this.initializeMaintainersData();
5160
private readonly healthScoresData = this.initializeHealthScoresData();
5261
private readonly activeContributorsData = this.initializeActiveContributorsData();
@@ -282,12 +291,21 @@ export class FoundationHealthComponent {
282291
}
283292

284293
private transformCompanyBusFactor(metric: DashboardMetricCard): DashboardMetricCard {
285-
// TODO: Replace with real API data when endpoint is available
294+
const data = this.companyBusFactorData();
295+
296+
const busFactor: CompanyBusFactor = {
297+
topCompaniesCount: data.topCompaniesCount,
298+
topCompaniesPercentage: data.topCompaniesPercentage,
299+
otherCompaniesCount: data.otherCompaniesCount,
300+
otherCompaniesPercentage: data.otherCompaniesPercentage,
301+
};
302+
286303
return {
287304
...metric,
288-
value: COMPANY_BUS_FACTOR.topCompaniesCount.toString(),
305+
loading: this.companyBusFactorLoading(),
306+
value: data.topCompaniesCount.toString(),
289307
subtitle: 'Companies account for >50% code contributions',
290-
busFactor: COMPANY_BUS_FACTOR,
308+
busFactor,
291309
};
292310
}
293311

@@ -510,6 +528,31 @@ export class FoundationHealthComponent {
510528
);
511529
}
512530

531+
private initializeCompanyBusFactorData() {
532+
const defaultValue: FoundationCompanyBusFactorResponse = {
533+
topCompaniesCount: 0,
534+
topCompaniesPercentage: 0,
535+
otherCompaniesCount: 0,
536+
otherCompaniesPercentage: 0,
537+
};
538+
539+
return toSignal(
540+
this.selectedFoundationSlug$.pipe(
541+
tap(() => this.companyBusFactorLoading.set(true)),
542+
switchMap((foundationSlug) =>
543+
this.analyticsService.getCompanyBusFactor(foundationSlug).pipe(
544+
tap(() => this.companyBusFactorLoading.set(false)),
545+
catchError(() => {
546+
this.companyBusFactorLoading.set(false);
547+
return of(defaultValue);
548+
})
549+
)
550+
)
551+
),
552+
{ initialValue: defaultValue }
553+
);
554+
}
555+
513556
private initializeMaintainersData() {
514557
const defaultValue = {
515558
avgMaintainers: 0,

apps/lfx-one/src/app/modules/dashboards/components/my-meetings/my-meetings.component.html

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ <h2 class="flex items-center gap-2">
3232
<!-- TODAY Section - only show if there are meetings today -->
3333
@if (todayMeetings().length > 0) {
3434
<div>
35-
<h4 class="text-xs font-medium text-gray-500 mb-3 uppercase tracking-wide">Today</h4>
3635
<div class="flex flex-col gap-3">
3736
@for (item of todayMeetings(); track item.meeting.uid) {
3837
<lfx-dashboard-meeting-card
@@ -47,7 +46,6 @@ <h4 class="text-xs font-medium text-gray-500 mb-3 uppercase tracking-wide">Today
4746
<!-- UPCOMING Section - only show if there are upcoming meetings -->
4847
@if (upcomingMeetings().length > 0) {
4948
<div>
50-
<h4 class="text-xs font-medium text-gray-500 mb-3 uppercase tracking-wide">Upcoming</h4>
5149
<div class="flex flex-col gap-3">
5250
@for (item of upcomingMeetings(); track item.meeting.uid) {
5351
<lfx-dashboard-meeting-card

0 commit comments

Comments
 (0)