Skip to content

feat: Add formula-based calculated value to data browser graph#3129

Merged
mtrezza merged 8 commits intoparse-community:alphafrom
mtrezza:feat/graph-formula
Jan 20, 2026
Merged

feat: Add formula-based calculated value to data browser graph#3129
mtrezza merged 8 commits intoparse-community:alphafrom
mtrezza:feat/graph-formula

Conversation

@mtrezza
Copy link
Member

@mtrezza mtrezza commented Jan 20, 2026

New Pull Request Checklist

Summary by CodeRabbit

  • New Features

    • Added formula-based calculated values for graphs with arithmetic, comparison, conditional, and math functions.
    • UI now accepts formulas for calculated values and validates them before saving.
  • Documentation

    • Expanded README with Browser Control API and detailed Graph/Formula documentation, examples, and usage anchors (note: Graph docs appear in two places).
  • Tests

    • Comprehensive tests for formula evaluation and integration into chart data processing.

✏️ Tip: You can customize this high-level summary in your review settings.

@parse-github-assistant
Copy link

parse-github-assistant bot commented Jan 20, 2026

🚀 Thanks for opening this pull request! We appreciate your effort in improving the project. Please let us know once your pull request is ready for review.

@coderabbitai
Copy link

coderabbitai bot commented Jan 20, 2026

Warning

Rate limit exceeded

@mtrezza has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 14 minutes and 12 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 55b94d5 and c488a61.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • package.json
  • src/lib/FormulaEvaluator.js
  • src/lib/tests/GraphDataUtils.test.js
📝 Walkthrough

Walkthrough

Adds a new "formula" calculated-value feature: a FormulaEvaluator module (expr-eval), UI validation/input in GraphDialog, and GraphDataUtils support to evaluate formulas during chart data processing; includes tests and README documentation updates.

Changes

Cohort / File(s) Change Summary
Documentation
README.md
Added Browser Control API subsections and a comprehensive Graph section describing Calculated Values, Formula operators (arithmetic, comparison, conditional, math functions), examples, and TOC anchors
Dependencies
package.json
Added dependency: expr-eval v2.0.2
UI Integration
src/dashboard/Data/Browser/GraphDialog.react.js
Added formula operator option; imported validateFormula; added getFormulaError and getNameError; extended validation flow and UI to render formula input and show validation errors
Formula Evaluation Core
src/lib/FormulaEvaluator.js
New module exporting buildVariables, evaluateFormula, validateFormula, getFormulaVariables; configures a restricted expr-eval parser, preprocesses formulas (round → roundTo), handles $-prefixed variables and safe evaluation/validation
Data Processing
src/lib/GraphDataUtils.js
Extended calculateValue signature to accept formula and availableFields; added formula handling across processPieData and processBarLineData (variable building, per-row evaluation, aggregation and grouping adjustments)
Tests
src/lib/tests/*
src/lib/tests/FormulaEvaluator.test.js, src/lib/tests/GraphDataUtils.test.js
Added extensive tests for FormulaEvaluator (evaluation, validation, variable extraction, error cases) and for GraphDataUtils integration of the formula operator in bar/line and pie processing

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant GraphDialog
    participant FormulaEvaluator
    participant GraphDataUtils
    participant Chart

    User->>GraphDialog: Enter calculated value name & formula
    GraphDialog->>FormulaEvaluator: validateFormula(formula, availableVariables)
    FormulaEvaluator-->>GraphDialog: {isValid, error}

    alt Formula Invalid
        GraphDialog->>User: Display validation error
    else Formula Valid
        User->>GraphDialog: Confirm calculated value
        GraphDialog->>GraphDataUtils: Request chart processing with calculated values
        GraphDataUtils->>GraphDataUtils: For each row, build field values
        GraphDataUtils->>FormulaEvaluator: evaluateFormula(formula, variables)
        FormulaEvaluator-->>GraphDataUtils: numeric result
        GraphDataUtils->>GraphDataUtils: Augment row with calculated value
        GraphDataUtils-->>Chart: Provide enhanced dataset
        Chart->>User: Render chart with formula-derived data
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description only contains checkbox completion without filling required fields like Issue Description, Approach, or relevant TODOs. Complete the template by adding: issue reference/number under 'Closes:', detailed approach explanation, and relevant pre-merge TODOs (tests, documentation updates).
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely describes the main change: adding formula-based calculated values to the data browser graph feature.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@parseplatformorg
Copy link
Contributor

parseplatformorg commented Jan 20, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@mtrezza mtrezza changed the title feat: Add calculated value of type formula to data browser graph feat: Add formula-based calculated value to data browser graph Jan 20, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@package.json`:
- Line 42: The package.json currently pins the vulnerable dependency "expr-eval"
at 2.0.2; replace that dependency with the maintained fork "expr-eval-fork"
(version 3.0.0 or later) or remove the dependency entirely if runtime expression
evaluation of untrusted input is not required, then update lockfile
(npm/yarn/pnpm) and run dependency audits and tests; look for the string
"expr-eval": "2.0.2" in package.json and replace it with "expr-eval-fork":
">=3.0.0" (or delete the entry) and ensure imports/usages that reference the
module name are updated accordingly in code (search for require/import of
"expr-eval") so runtime resolution and security scans pass.

In `@src/lib/FormulaEvaluator.js`:
- Around line 80-105: In preprocessFormula, add explicit braces for all
single-line if/else bodies to satisfy lint rules: wrap the early return if
(!formula) return formula; in braces, and add braces for the three condition
branches inside the for loop that mutate depth/hasComma (the checks using
rest[i] === '(', rest[i] === ')', and rest[i] === ',' with depth === 1), and for
the else-if chain that returns 'roundTo(' or 'round(' in the replace callback;
ensure each conditional block uses { ... } while keeping the existing logic and
referenced identifiers (preprocessFormula, processed, rest, depth, hasComma,
match, offset).

In `@src/lib/tests/GraphDataUtils.test.js`:
- Around line 273-284: The test for processPieData is missing assertions for the
computed formula results; update the 'should evaluate formula in pie chart' test
to assert that the returned result.datasets exists and contains the computed
values from calculatedValues (e.g., for calculatedValues with name 'Profit' and
formula 'revenue - cost' assert datasets[0].data equals [40, 50] or the expected
order based on mockData, verify datasets[0].label (or name) matches 'Profit',
and confirm labels length matches mockData categories so the formula computation
is actually validated; use processPieData, mockData, and calculatedValues as the
referenced symbols.
🧹 Nitpick comments (4)
README.md (1)

1499-1507: Add language specification to fenced code block.

The static analysis tool flagged this code block as missing a language specification. Adding a language identifier improves syntax highlighting and accessibility.

📝 Suggested fix
 **Example formulas:**
-```
+```text
 price * quantity                              # Multiply two fields
 round(revenue / cost * 100, 2)                # Calculate percentage with rounding
 max(value, 0)                                 # Floor at 0 (no negatives)
 min(value, 100)                               # Cap at 100
 score > 50 ? score : 0                        # Conditional logic
 round((revenue - cost) / revenue * 100, 1)    # Profit margin calculation
</details>

</blockquote></details>
<details>
<summary>src/dashboard/Data/Browser/GraphDialog.react.js (1)</summary><blockquote>

`88-116`: **Consider also blocking submission when formula errors exist.**

The `valid()` method checks for name errors but does not check for formula errors. A calculated value with operator `'formula'` and an invalid formula (e.g., unknown variables) will still allow form submission, potentially leading to null values at runtime.



<details>
<summary>♻️ Suggested enhancement</summary>

```diff
   valid() {
     const { chartType, xColumn, yColumn, valueColumn, calculatedValues } = this.state;
     const hasValueColumn = Array.isArray(valueColumn) && valueColumn.length > 0;
     const hasCalculatedValues = Array.isArray(calculatedValues) && calculatedValues.length > 0;
     const hasValuesToDisplay = hasValueColumn || hasCalculatedValues;

     // Check for any name errors in calculated values
     if (hasCalculatedValues) {
       for (let i = 0; i < calculatedValues.length; i++) {
         if (this.getNameError(i)) {
           return false;
         }
+        // Also check for formula errors
+        if (this.getFormulaError(i)) {
+          return false;
+        }
       }
     }

     switch (chartType) {
src/lib/tests/GraphDataUtils.test.js (2)

201-214: Consider adding assertions for all computed values.

The test only verifies that the result contains 2 (Jan's value), but doesn't check 6.67 (Feb) or 3.75 (Mar). Adding these assertions would ensure the rounding function handles decimals correctly.

Suggested improvement
         expect(result).toHaveProperty('datasets');
         expect(result.datasets[0].label).toBe('Rounded');
         // Jan: round(10/5, 2)=2, Feb: round(20/3, 2)=6.67, Mar: round(15/4, 2)=3.75
         expect(result.datasets[0].data).toContain(2);
+        expect(result.datasets[0].data).toContain(6.67);
+        expect(result.datasets[0].data).toContain(3.75);

240-264: Consider strengthening error-handling assertions.

Both tests only verify that result has a datasets property, but don't assert the expected behavior:

  • For empty formula: Should the 'Empty' calculated value be omitted from datasets, or produce zeros?
  • For invalid formula: Should the 'Invalid' calculated value be skipped?

The comment on line 249 states "just without the empty formula calculated value" but this isn't verified.

Suggested improvement
       it('should handle empty formula gracefully', () => {
         const calculatedValues = [{
           name: 'Empty',
           operator: 'formula',
           formula: '',
         }];
 
         const result = processBarLineData(mockData, 'month', 'price', null, 'sum', calculatedValues);
 
         // Should still work, just without the empty formula calculated value
         expect(result).toHaveProperty('datasets');
+        // Verify that regular 'price' dataset is present and 'Empty' is omitted
+        expect(result.datasets.some(d => d.label === 'price')).toBe(true);
+        expect(result.datasets.some(d => d.label === 'Empty')).toBe(false);
       });
 
       it('should handle invalid formula gracefully', () => {
         const calculatedValues = [{
           name: 'Invalid',
           operator: 'formula',
           formula: 'invalid syntax @@@',
         }];
 
         const result = processBarLineData(mockData, 'month', 'price', null, 'sum', calculatedValues);
 
         // Should not throw, chart should render with regular values
         expect(result).toHaveProperty('datasets');
+        // Verify that regular 'price' dataset is present
+        expect(result.datasets.some(d => d.label === 'price')).toBe(true);
       });

@mtrezza mtrezza merged commit 7c5d1b3 into parse-community:alpha Jan 20, 2026
12 checks passed
parseplatformorg pushed a commit that referenced this pull request Jan 20, 2026
# [8.3.0-alpha.12](8.3.0-alpha.11...8.3.0-alpha.12) (2026-01-20)

### Features

* Add formula-based calculated value to data browser graph ([#3129](#3129)) ([7c5d1b3](7c5d1b3))
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 8.3.0-alpha.12

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state:released-alpha Released as alpha version

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants