Skip to content

fix: Calculated attributes don't always update on graphs (CODAP-1439)#2657

Merged
emcelroy merged 3 commits into
mainfrom
CODAP-1439-calculated-attrs-graph-update
Jul 8, 2026
Merged

fix: Calculated attributes don't always update on graphs (CODAP-1439)#2657
emcelroy merged 3 commits into
mainfrom
CODAP-1439-calculated-attrs-graph-update

Conversation

@emcelroy

@emcelroy emcelroy commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Fixes CODAP-1439. When a calculated (formula) attribute was plotted on a graph, changing its formula didn't reliably update the graph:

  • No update at all when the attribute was a 2nd attribute on the left axis or on the right (y2) axis — the dots only moved after a manual resize forced a full refresh.
  • Position updated but no rescale when the attribute was on x or the first y axis — dots moved but the axis didn't refit, so recalculated values could land outside the viewport.

Both symptoms are fixed: the dots move immediately, and the numeric axes grow to fit values that move outside the current view.

These changes also fix CODAP-1444: Graph with computed values as second y attribute doesn't update when slider is dragged

Root causes

  1. Dots not moving (2nd-y / y2). The value-change responder in use-plot.ts skips refreshing when a formula recalc affects no plotted attribute, checked against uniqueAttributes. But the graph's attributeDescriptions override omits the additional left-y and the y2/rightNumeric attributes, so uniqueAttributes never contained them and their recalcs were filtered out.

  2. No rescale on value change. Nothing refit axis domains when values changed — only addCases did. Compounding this, numericValuesForRole reads a manually-invalidated cache (numericValuesForAttribute) that is only cleared by clearCasesCache, which fires from a reaction keyed on numericAttrs — and numericAttrs excluded the 2nd-y/y2 attributes, so their value changes never invalidated the cache. A naïve synchronous rescale also reads this cache before the invalidation reaction runs.

Changes

  • plottedAttributeIDs (new view) — union of uniqueAttributes and yAttributeIDs; the value-change responder now filters against it so 2nd-y/y2 recalcs move the dots.
  • numericAttrs now includes the additional left-y and y2 numeric attributes, so their value changes invalidate the cases cache (fixing cache coherence for the rescale and other consumers such as adornments).
  • growNumericAxesToFit() (new grow-only action) grows numeric axes to fit current data without shrinking, so user/plugin-set bounds are preserved and a binned plot's primary axis is left to its own bin sync. It's driven by a reaction on casesChangeCount, which clearCasesCache bumps after invalidating the cache — guaranteeing the rescale reads post-change values. The addCases handler now shares this helper.

Rescale is grow-only (never shrinks) — consistent with the existing addCases behavior — so it fits outliers without discarding manually adjusted bounds.

Testing

  • Unit tests for plottedAttributeIDs (includes 2nd-y/y2 that uniqueAttributes omits).
  • Reaction-driven rescale tests using the real setComputedCaseValues formula path: left-y grows, grow-only leaves in-range domains unchanged, and a y2-only attribute grows its axis (with the cache pre-populated, reproducing the reported scenario).
  • Full graph suite passes (612 tests); typecheck and lint clean.

Manual verification

Confirmed against the shared document from the story: editing the "calculated values" formula now updates and rescales all graphs without a manual resize.

@cypress

cypress Bot commented Jul 8, 2026

Copy link
Copy Markdown

codap-v3    Run #11956

Run Properties:  status check passed Passed #11956  •  git commit ec885255df: null
Project codap-v3
Branch Review main
Run status status check passed Passed #11956
Run duration 08m 19s
Commit git commit ec885255df: null
Committer null
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 82
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 380
View all changes introduced in this branch ↗︎

@emcelroy emcelroy requested a review from Copilot July 8, 2026 17:46
@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.46%. Comparing base (f999f14) to head (43c73bb).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff             @@
##             main    #2657       +/-   ##
===========================================
+ Coverage   71.74%   87.46%   +15.72%     
===========================================
  Files         800      800               
  Lines       45800    45811       +11     
  Branches    11209    11648      +439     
===========================================
+ Hits        32860    40070     +7210     
+ Misses      12925     5728     -7197     
+ Partials       15       13        -2     
Flag Coverage Δ
cypress 70.46% <96.00%> (+32.01%) ⬆️
jest 61.68% <96.15%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

Fixes CODAP-1439 by ensuring graphs immediately refresh point positions and grow-fit numeric axis domains when calculated/formula attribute values change, including additional left-y (y+) and rightNumeric (y2) axes.

Changes:

  • Add plottedAttributeIDs to include all plotted attributes (including y+/y2) and use it to avoid skipping relevant formula-driven updates.
  • Expand numericAttrs to include additional left-y/y2 numeric attributes so their value changes invalidate numeric-value caches.
  • Introduce growNumericAxesToFit() and a casesChangeCount-driven reaction to grow-fit numeric axes after value changes (and reuse it for add-cases behavior).

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
v3/src/components/graph/models/graph-data-configuration-model.ts Adds plottedAttributeIDs and expands numeric-attribute tracking for cache invalidation (y+/y2).
v3/src/components/graph/models/graph-data-configuration-model.test.ts Adds unit coverage for plottedAttributeIDs including y+/y2 IDs.
v3/src/components/graph/models/graph-content-model.ts Adds grow-only axis fitting helper and reaction to refit numeric axes after case value changes.
v3/src/components/graph/models/graph-content-model.test.ts Adds reaction-driven rescale tests using setComputedCaseValues (formula path), including y2-only coverage and cache prepopulation.
v3/src/components/graph/hooks/use-plot.ts Switches computed-value refresh filtering from uniqueAttributes to plottedAttributeIDs.

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

Comment thread v3/src/components/graph/models/graph-data-configuration-model.ts
@emcelroy emcelroy added the v3 CODAP v3 label Jul 8, 2026
@emcelroy emcelroy marked this pull request as ready for review July 8, 2026 18:48
@emcelroy emcelroy requested a review from kswenson July 8, 2026 18:52
The casesChangeCount rescale reaction called growNumericAxesToFit on
every value change, formula recalc, and case removal. For clamped
count/percent axes (bar charts and histograms), setNiceDomain refit them
tightly, so a user- or plugin-set count-axis max was silently discarded
on any such change, and removeCases could shrink the axis.

- Add a growOnly option to setNiceDomain; when set, the clamp branch no
  longer opts into shrinking, so setDomain's grow-only clamp preserves a
  larger existing bound. growNumericAxesToFit now passes growOnly.
- Drop the redundant growNumericAxesToFit call from the addCases handler;
  addCases bumps casesChangeCount, so the reaction already covers it. The
  handler now only resyncs a binned plot's primary axis.
- Add tests: grow-only clamp behavior in setNiceDomain, and a bar chart
  count axis that keeps a user-set max across a value change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@kswenson kswenson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

👍 Looks good -- the following review was developed in conjunction with Claude Code 🤖.

Approving. The two-part fix is sound: the use-plot guard now filters against plottedAttributeIDs (a strict superset of uniqueAttributes, so it can only allow more refreshes through), and the casesChangeCount rescale reaction is correctly ordered — MST transaction batching guarantees it reads post-invalidation values. I also confirmed the numericAttrs broadening has a contained blast radius (its sole consumer is the getCellKeys reaction, which doesn't depend on .role).

During review I pushed one follow-up commit (43c73bb, with the author's OK) addressing three findings:

  • Grow-only for clamped axes. The new rescale reaction ran growNumericAxesToFit on every value change, formula recalc, and removeCases. For clamped count/percent axes (bar charts, histograms), setNiceDomain refit them tightly, so a user- or plugin-set count-axis max was silently discarded on any such change (and removeCases could shrink the axis). Added a growOnly option to setNiceDomain; growNumericAxesToFit now passes it so those axes are grown, never shrunk. The bar-chart/plot-model resync paths (which don't pass the flag) still tight-fit as before.
  • Redundant refit on addCases. Dropped the growNumericAxesToFit() call in the addCases handler — addCases bumps casesChangeCount, so the reaction already covers it. The handler now only resyncs a binned plot's primary axis.
  • Tests. Added setNiceDomain grow-only unit tests and a bar-chart count-axis regression test (verified it fails without the grow-only fix).

670 graph + axis Jest tests pass locally; typecheck and lint clean.

@emcelroy emcelroy merged commit ec88525 into main Jul 8, 2026
27 checks passed
@emcelroy emcelroy deleted the CODAP-1439-calculated-attrs-graph-update branch July 8, 2026 21:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants