feat: Add formula-based calculated value to data browser graph#3129
feat: Add formula-based calculated value to data browser graph#3129mtrezza merged 8 commits intoparse-community:alphafrom
Conversation
|
🚀 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. |
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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. ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (3)
📝 WalkthroughWalkthroughAdds 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
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
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. Comment |
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
There was a problem hiding this comment.
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 check6.67(Feb) or3.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
resulthas adatasetsproperty, 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); });
# [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))
|
🎉 This change has been released in version 8.3.0-alpha.12 |
New Pull Request Checklist
Summary by CodeRabbit
New Features
Documentation
Tests
✏️ Tip: You can customize this high-level summary in your review settings.