Skip to content

fix(dashboards): stop rendering failed requests as measured zeros - #1333

Open
mrautela365 wants to merge 2 commits into
mainfrom
fix/LFXV2-3005
Open

fix(dashboards): stop rendering failed requests as measured zeros#1333
mrautela365 wants to merge 2 commits into
mainfrom
fix/LFXV2-3005

Conversation

@mrautela365

Copy link
Copy Markdown
Contributor

Summary

The ED Overview Paid Media and Attribution cards rendered $0 spend, 0 impressions, 0.0x ROAS and $0 won revenue whenever their request failed. Those zeros were fabricated by error fallbacks, not measured.

All-zeros was an ambiguous sentinel encoding both "the query failed" and "genuinely zero" — and both rendered identically, as a factual figure. Snowflake returns 52.4M impressions, $456K spend and $28.5M won revenue for the same umbrella window the UI was reporting as zero.

This PR removes the zero-filled fallbacks so a failure is observable as a failure, and renders an explicit "data unavailable" state instead of an invented number.

Changes

File Change
analytics.service.ts Drop the zero-filled catchError from getSocialReach and getRevenueImpact so failures reach the caller. All five consumers already handle the error stream.
project.service.ts getSocialReach rethrows instead of returning defaults, so the failure surfaces as a non-200 rather than a 200 carrying zeros. getRevenueImpact already rethrew.
analytics-data.interface.ts Type paidCampaign and revenueImpact as nullable on EdEvolutionData, mirroring the education card.
dashboard-metrics.constants.ts Render undefined as an explicit unavailable state — em-dash values, no sparkline, no trend pill.
marketing-overview.component.ts Wire the nullable data through to the cards.

Why "data unavailable" rather than hiding the card

These cards sit in a fixed carousel. Suppressing one on error would read as a layout bug, so the card stays in place and states plainly that the figure could not be loaded.

Why the drawers keep non-nullable inputs

The drill-down drawers take a placeholder and keep their non-nullable inputs. They refetch their own detail data and are only reachable by explicit click, so they never present the placeholder as a measured figure.

Testing

  • ./check-headers.sh — passed (1919 files)
  • yarn format:check — passed
  • yarn lint:check — 0 errors (1 pre-existing warning in campaigns.component.ts, untouched by this branch)
  • yarn build — passed, SSR bundle generated

Not verified: the rendered card states were not visually confirmed on local. The ED dashboard was brought up and the social-reach / revenue-impact / email-ctr endpoints returned clean 200s against Snowflake with no errors, but no one eyeballed whether the cards display real figures, the em-dash unavailable state, or $0. Worth a look during review.

Notes

  • Branch is 4 commits behind main. Test-merged clean — dashboard-metrics.constants.ts is touched by both, but in different regions (main changed the import block; this PR changes metric definitions).

LFXV2-3005

The ED Overview Paid Media and Attribution cards rendered $0 spend,
0 impressions, 0.0x ROAS and $0 won revenue whenever their request
failed. Those zeros were fabricated by error fallbacks, not measured:
all-zeros was an ambiguous sentinel encoding both "query failed" and
"genuinely zero", and both rendered identically as a factual figure.

Snowflake returns 52.4M impressions, $456K spend and $28.5M won revenue
for the same umbrella window the UI reported as zero.

- analytics.service.ts: drop the zero-filled catchError from
  getSocialReach and getRevenueImpact so failures reach the caller.
  All five consumers already handle the error stream.
- project.service.ts: getSocialReach rethrows instead of returning
  defaults, so the failure is observable as a non-200 rather than a
  200 carrying zeros. getRevenueImpact already rethrew.
- analytics-data.interface.ts: type paidCampaign and revenueImpact as
  nullable on EdEvolutionData, mirroring the education card.
- dashboard-metrics.constants.ts: render undefined as an explicit
  "data unavailable" state — em-dash values, no sparkline, no trend
  pill — rather than suppressing the card, which in a fixed carousel
  would read as a layout bug.

The drill-down drawers keep their non-nullable inputs and take a
placeholder; they refetch their own detail data and are only reachable
by explicit click, so they never present it as a measured figure.

LFXV2-3005

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

cursor Bot commented Aug 5, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches revenue and paid-media presentation paths where mislabeling errors as zeros was a product bug; changes are localized but affect executive-facing financial KPIs when backends fail.

Overview
Paid Media and Attribution on the ED Marketing Overview no longer show $0 spend, zero impressions, 0.0x ROAS, or $0 won revenue when social-reach / revenue-impact fail. Those figures used to come from zero-filled error fallbacks and looked like real measurements.

End-to-end behavior: getSocialReach and getRevenueImpact no longer swallow errors into all-zeros (client analytics.service and server getSocialReach, which now rethrows). EdEvolutionData types paidCampaign and revenueImpact as | undefined for failure, adds optional pending for the first load, and buildEdEvolutionMetrics renders em-dashes plus Loading… vs Data unavailable — could not be loaded instead of fake metrics. marketing-overview uses a separate PENDING_ED_EVOLUTION_DATA initial value (so loading is not mistaken for failure) and drawer-only zero placeholders where inputs stay non-nullable.

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

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e71caed9-aa64-48ae-beec-0292a4c94966

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

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 1 potential issue.

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 b3b4753. 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

Prevents failed ED dashboard analytics requests from appearing as measured zeros.

Changes:

  • Propagates social-reach and revenue-impact errors.
  • Models failed card data as undefined.
  • Renders explicit unavailable card states.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
analytics-data.interface.ts Allows failed metrics to be undefined.
dashboard-metrics.constants.ts Builds unavailable card states.
project.service.ts Rethrows social-reach failures.
analytics.service.ts Removes zero-filled client fallbacks.
marketing-overview.component.ts Maps request failures to unavailable data.

Paid Media and Attribution announced "Data unavailable — could not be
loaded" during the initial in-flight window, before any request had
failed. EMPTY_ED_EVOLUTION_DATA was passed as both toSignal's
initialValue and safe()'s per-call error fallback, so the undefined
paidCampaign and revenueImpact that encode "the request failed" were
also the values present while the requests were still pending.

- marketing-overview.component.ts: add PENDING_ED_EVOLUTION_DATA as a
  distinct initial value, so the error object no longer doubles as the
  loading state.
- analytics-data.interface.ts: add the optional pending marker that
  separates "not answered yet" from "answered with a failure".
- dashboard-metrics.constants.ts: caption the placeholder as "Loading…"
  while pending and keep "could not be loaded" for a real failure. Both
  still render em-dash values with no sparkline or trend pill, so
  neither is mistakable for a measured zero.

Reported by cursor and copilot-pull-request-reviewer on PR #1333.

LFXV2-3005

Signed-off-by: Misha Rautela <mrautela@linuxfoundation.org>
Copilot AI review requested due to automatic review settings August 6, 2026 00:42

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

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

apps/lfx-one/src/server/services/project.service.ts:3228

  • The new failure contract has no regression coverage: project.service.spec.ts tests other ProjectService methods but has no getSocialReach case. Add a test that makes the Snowflake query reject and asserts getSocialReach rejects with that error; otherwise the zero-filled fallback this PR removes can be reintroduced without a failing test.
      throw error;

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