Skip to content

feat(dashboards): add event roster with goal bars to overview - #1171

Draft
mrautela365 wants to merge 1 commit into
feat/LFXV2-2768-events-summaryfrom
feat/LFXV2-2768-event-roster
Draft

feat(dashboards): add event roster with goal bars to overview#1171
mrautela365 wants to merge 1 commit into
feat/LFXV2-2768-events-summaryfrom
feat/LFXV2-2768-event-roster

Conversation

@mrautela365

Copy link
Copy Markdown
Contributor

Summary

Adds the Events roster table below the summary tiles, from MARKETING_EVENT_REGISTRATIONS joined to sponsorship actuals from MARKETING_EVENT_SPONSORSHIPS_BY_TIER. Each row shows registration and sponsorship actual-vs-goal as a health-colored bar (green/amber/red); a goal of 0 renders no bar (matches PCC's "no goal required"). Includes an at-risk flag, an upcoming/all toggle, and name search.

PR 2/6 of the LF Events dashboard stack (LFXV2-2768). Base: feat/LFXV2-2768-events-summary (PR #1170). Review/merge PR 1 first.

Queries validated live. Typecheck + lint pass.

LFXV2-2768

Add an Events roster table below the summary tiles, sourced from
ANALYTICS.PLATINUM_LFX_ONE.MARKETING_EVENT_REGISTRATIONS joined to
sponsorship actuals from MARKETING_EVENT_SPONSORSHIPS_BY_TIER. Each row
shows registration and sponsorship actual-vs-goal as a health-colored
progress bar (green/amber/red), a goal of 0 renders no bar (matches PCC's
'no goal required' rule), plus an at-risk flag for events behind goal with
a low comparison pace. Includes an upcoming/all toggle and name search.

LFXV2-2768

Signed-off-by: Misha Rautela <mrautela@linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 23, 2026 03:53
@mrautela365
mrautela365 requested a review from a team as a code owner July 23, 2026 03:53
@cursor

cursor Bot commented Jul 23, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Introduces a new Snowflake analytics query and dashboard metrics users may act on; validation and error handling match existing marketing endpoints, with no auth or write-path changes.

Overview
Adds an Events roster table on the Marketing Impact Overview tab (below the events summary tiles), backed by a new GET /api/analytics/event-roster endpoint and Snowflake data from MARKETING_EVENT_REGISTRATIONS joined to sponsorship actuals.

Each row shows date, name (link when URL exists), registration and sponsorship revenue actual vs goal as color-coded progress bars (no bar when goal is 0, aligned with PCC), CFP status, and an at-risk indicator when registration is under 50% of goal and compScore is low. The UI supports name search, Upcoming vs All events (includePast), loading skeletons, and empty states; API errors degrade to an empty roster on the client.

Shared types (EventRosterResponse, row/view models) and AnalyticsService.getEventRoster wire the new lfx-event-roster-section component into the overview tab.

Reviewed by Cursor Bugbot for commit 8997b71. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 35793486-85ae-46ad-a1ec-cde78b433014

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/LFXV2-2768-event-roster

Comment @coderabbitai help to get the list of available commands.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 8997b71. Configure here.

} @else {
<div class="flex items-center justify-center rounded-lg border border-dashed border-gray-300 bg-gray-50 p-8" data-testid="event-roster-empty">
<p class="text-sm text-gray-500">No events match your search.</p>
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty state blames search incorrectly

Medium Severity

The empty state always shows “No events match your search.” whenever hasRows() is false, but that branch also runs when the roster API returns zero events, the “Upcoming” scope hides all rows, or the search box is empty. Users with no upcoming events or an empty foundation see a search-specific message that does not apply.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 8997b71. Configure here.

<span class="truncate text-xs font-semibold text-gray-700">{{ row.eventName }}</span>
}
@if (row.atRisk) {
<i class="fa-solid fa-circle-exclamation text-xs text-red-500" aria-label="Behind registration goal" title="Behind registration goal"></i>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At-risk icon misstates trigger conditions

Low Severity

The at-risk icon’s aria-label and title say the event is only “Behind registration goal,” but atRisk is set only when registration progress is under 50% of goal and compScore === 'low'. Assistive tech and hover users are not told the low year-over-year pace requirement.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 8997b71. Configure here.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an LF Events roster to the Marketing Impact overview, backed by Snowflake registration and sponsorship data.

Changes:

  • Adds roster API contracts, query, controller, route, and client service.
  • Adds searchable upcoming/all event roster UI with goal bars and risk indicators.
  • Integrates the roster below Events Summary.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
packages/shared/src/interfaces/marketing-impact.interface.ts Adds roster view models.
packages/shared/src/interfaces/dashboard-metric.interface.ts Adds roster API contracts.
apps/lfx-one/src/server/services/project.service.ts Queries and maps roster data.
apps/lfx-one/src/server/routes/analytics.route.ts Registers the roster endpoint.
apps/lfx-one/src/server/controllers/analytics.controller.ts Validates and handles roster requests.
apps/lfx-one/src/app/shared/services/analytics.service.ts Adds the roster HTTP client.
apps/lfx-one/src/app/modules/dashboards/marketing-impact/components/overview-tab/overview-tab.component.ts Imports the roster component.
apps/lfx-one/src/app/modules/dashboards/marketing-impact/components/overview-tab/overview-tab.component.html Places the roster in the overview.
apps/lfx-one/src/app/modules/dashboards/marketing-impact/components/event-roster-section/event-roster-section.component.ts Implements roster state and formatting.
apps/lfx-one/src/app/modules/dashboards/marketing-impact/components/event-roster-section/event-roster-section.component.html Implements roster controls and table UI.
Comments suppressed due to low confidence (1)

apps/lfx-one/src/app/modules/dashboards/marketing-impact/components/event-roster-section/event-roster-section.component.html:34

  • The active scope is conveyed only visually. Expose the toggle state so screen-reader users can determine when “All events” is selected.
          [ngClass]="includePast() ? 'bg-blue-500 text-white' : 'text-gray-500'"

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

cfpStatus: row.CFP_STATUS ?? '',
}));

return { projectId: '', events };
if (includePast) {
params['includePast'] = 'true';
}
return this.http.get<EventRosterResponse>('/api/analytics/event-roster', { params }).pipe(catchError(() => of({ projectId: '', events: [] })));
<h3 class="text-base font-semibold text-gray-900">Events</h3>
<p class="text-xs text-gray-500">Registrations and sponsorship vs goal · click an event to open it</p>
</div>
<div class="flex items-center gap-3">
<button
type="button"
class="rounded-full px-3 py-1 text-xs font-semibold"
[ngClass]="!includePast() ? 'bg-blue-500 text-white' : 'text-gray-500'"
Comment on lines +94 to +101
<div
class="h-full rounded-full"
[ngClass]="{
'bg-emerald-500': row.registrations.tone === 'good',
'bg-amber-500': row.registrations.tone === 'warn',
'bg-red-400': row.registrations.tone === 'critical',
}"
[style.width.%]="row.registrations.percent"></div>
Comment on lines +116 to +123
<div
class="h-full rounded-full"
[ngClass]="{
'bg-emerald-500': row.sponsorshipRevenue.tone === 'good',
'bg-amber-500': row.sponsorshipRevenue.tone === 'warn',
'bg-red-400': row.sponsorshipRevenue.tone === 'critical',
}"
[style.width.%]="row.sponsorshipRevenue.percent"></div>
}
</div>
} @else if (hasRows()) {
<div class="flex flex-col gap-0 overflow-x-auto" role="table" aria-label="Event roster" data-testid="event-roster-table">
</div>
} @else {
<div class="flex items-center justify-center rounded-lg border border-dashed border-gray-300 bg-gray-50 p-8" data-testid="event-roster-empty">
<p class="text-sm text-gray-500">No events match your search.</p>
@mrautela365
mrautela365 marked this pull request as draft August 3, 2026 21:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants