Skip to content

feat: Replace graph fields with graph series for more customization#3157

Merged
mtrezza merged 15 commits intoparse-community:alphafrom
mtrezza:feat/graph-series
Jan 28, 2026
Merged

feat: Replace graph fields with graph series for more customization#3157
mtrezza merged 15 commits intoparse-community:alphafrom
mtrezza:feat/graph-series

Conversation

@mtrezza
Copy link
Member

@mtrezza mtrezza commented Jan 28, 2026

Pull Request

Summary by CodeRabbit

  • New Features

    • Multi-series charts with per-series options (title, fields, aggregation, chart type, color, styles) and calculated-value items
    • Add/remove series and calculated-value editors; color presets + custom HEX
    • Line stroke-width override in graph settings; dropdown auto-scroll; custom inline styles for text inputs
  • Breaking Changes

    • Chart configs now use a series-based model instead of a single value field; saved graph configs must be updated
  • Tests

    • Graph utilities tests updated for series-based inputs

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

@parse-github-assistant
Copy link

parse-github-assistant bot commented Jan 28, 2026

🚀 Thanks for opening this pull request!

@mtrezza mtrezza changed the title feat: Replace global graph fields with graph series for better customization feat: Replace global graph fields with graph series for more customization Jan 28, 2026
@parseplatformorg
Copy link
Contributor

parseplatformorg commented Jan 28, 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: Replace global graph fields with graph series for more customization feat: Replace graph fields with graph series for more customization Jan 28, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 28, 2026

📝 Walkthrough

Walkthrough

Replaces the single valueColumn chart model with a multi-series model (per-series fields, styling, and calculated values), adds strokeWidthOverride for line charts, updates data processing/validation, and makes small UI tweaks in Dropdown (menuRef + auto-scroll) and TextInput (style prop).

Changes

Cohort / File(s) Summary
Dropdown Component
src/components/Dropdown/Dropdown.react.js
Added menuRef field and componentDidUpdate to auto-scroll the selected item when opening; attach ref to menu container; mark option buttons with data-selected; guard against null children.
TextInput Component
src/components/TextInput/TextInput.react.js
Added style prop (PropTypes.object) and apply/merge inline styles for single-line and multiline inputs.
Graph Dialog UI (Browser)
src/dashboard/Data/Browser/GraphDialog.react.js
Replaced single valueColumn with multi-series; added state/UI/API to add/remove/update/toggle series and calculated values; color presets and hex validation; per-series options (title, fields, aggregation, chartType, color, lineStyle, strokeWidth, barStyle, useSecondaryYAxis); updated confirm payload shape.
Custom Dashboard Config & Element
src/dashboard/Data/CustomDashboard/elements/GraphConfigDialog.react.js, src/dashboard/Data/CustomDashboard/elements/GraphElement.react.js
Added strokeWidthOverride UI/state (STROKE_WIDTHS) and persist/pass strokeWidthOverride in graphConfig; show option only when a line chart/series exists.
Graph Rendering Panel
src/components/GraphPanel/GraphPanel.react.js
Switched to series input (replacing valueColumn); removed aggregationType/secondaryYAxisType props; added strokeWidthOverride handling and apply to line datasets; derive effective dataset type from `dataset.type
Graph Data Utilities & Tests
src/lib/GraphDataUtils.js, src/lib/tests/GraphDataUtils.test.js
Removed groupAndAggregate; rewrote processPieData and processBarLineData to accept series arrays (fields, titles, styles); added getSeriesLabel helper; per‑series aggregation & styling; updated validateGraphConfig to expect series; adapted tests to new signatures and shapes.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant User as User
participant Dialog as GraphDialog.react
participant Element as GraphElement.react
participant Panel as GraphPanel.react
participant Utils as GraphDataUtils.js
participant Chart as ChartRenderer
User->>Dialog: configure series / calculated values / strokeWidthOverride
Dialog->>Element: save graphConfig (series, calculatedValues, strokeWidthOverride)
Element->>Panel: render(graphConfig)
Panel->>Utils: process*Data(data, graphConfig.series, graphConfig.calculatedValues, ...)
Utils-->>Panel: datasets, labels, options
Panel->>Chart: render(datasets, labels, options including strokeWidthOverride)
Chart-->>User: visualized chart

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is incomplete. It includes the template boilerplate but is missing the Issue link, Approach section explaining the changes, and Tasks checklist—all required sections from the repository template. Complete the PR description by filling in: (1) the Issue link under 'Closes:', (2) a detailed Approach section explaining the series-based changes, and (3) the Tasks checklist indicating whether tests and documentation updates were included.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: replacing graph fields with graph series for enhanced customization, which is the primary structural change across multiple files.
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 docstrings
🧪 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.

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 `@src/components/TextInput/TextInput.react.js`:
- Around line 67-68: The multiline branch in the TextInput component is ignoring
this.props.style: update the textarea rendering path (where a <textarea> is
returned) to merge style the same way as the <input> path (e.g., style={{
height: this.props.height || 80, ...this.props.style }}), ensuring the
placeholder and other props remain unchanged; modify the render method/JSX where
the textarea is created so both single-line (input) and multiline (textarea) use
the same merged style logic.

In `@src/dashboard/Data/CustomDashboard/elements/GraphConfigDialog.react.js`:
- Around line 69-75: The linter flags single-line if statements in the
isLineChart useMemo; update the conditional branches inside isLineChart (the
checks on selectedGraph and selectedGraph.chartType) to use braces for their
bodies: add { ... } around the return false and return true statements and
ensure the function still computes hasMixedLine from (selectedGraph.series ||
[]) and (selectedGraph.calculatedValues || []). This affects the isLineChart
useMemo closure and its internal if blocks referencing selectedGraph.

In `@src/lib/GraphDataUtils.js`:
- Around line 408-415: Change mutable declarations to const where values are not
reassigned (e.g., replace let aggregatedData = {} with const aggregatedData =
{}) and add braces for single-line conditional bodies inside the series loops to
satisfy the brace rule; specifically update the seriesArray.forEach callback(s)
that declare const fields = s.fields || [] and replace lone "if (fields.length
=== 0) return;" (and the other similar single-line if/else blocks in the same
loops) with a braced form (e.g., if (fields.length === 0) { return; }) so
prefer-const and brace-style lint rules are satisfied for the blocks that
reference aggregatedData, seriesArray.forEach, s/idx, and fields.
🧹 Nitpick comments (1)
src/dashboard/Data/Browser/GraphDialog.react.js (1)

55-61: Consider centralizing STROKE_WIDTHS to avoid drift.

This constant is duplicated in GraphConfigDialog.react.js; extracting it to a shared module will keep the options in sync.

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 `@src/dashboard/Data/CustomDashboard/elements/GraphConfigDialog.react.js`:
- Around line 39-40: Normalize strokeWidthOverride to a numeric type everywhere:
initialize the state using Number(initialConfig?.strokeWidthOverride) (or
null/undefined -> '' as desired), convert the Dropdown/change handler to
setStrokeWidthOverride(Number(value)) instead of raw string, and before saving
the config (e.g., in the component's save/submit handler such as
handleSave/onSave) coerce strokeWidthOverride to a number
(Number(strokeWidthOverride) or parseInt) so the saved config and Dropdown use
the same numeric type and borderWidth is numeric; apply this to the
initialization, change handlers, and save logic for strokeWidthOverride
referenced in this file.

In `@src/lib/GraphDataUtils.js`:
- Around line 1005-1007: The code currently treats strokeWidth truthily (e.g.,
if (s.strokeWidth) and using || to default), which drops valid 0 values; update
all such checks in GraphDataUtils.js (including where seriesStrokeWidthMap is
set and the blocks around the referenced ranges) to use explicit null/undefined
checks or the nullish coalescing operator so zero is preserved — e.g., replace
if (s.strokeWidth) with if (s.strokeWidth !== undefined && s.strokeWidth !==
null) and replace usages of value || defaultValue with value ?? defaultValue (or
equivalent !== undefined checks) for any variables or map assignments handling
strokeWidth.
- Around line 445-450: The group label generation can collide with
calculated-value labels when groupByColumn is used with exactly one series and
one calculated value: update the labelKey logic in the block that iterates
Object.keys(groups) so it accounts for presence of calculated values (e.g.,
check a calculatedValues/aggregates array or the computedValues count) and use a
more specific label when necessary — for example change the condition to
something like "if seriesArray.length > 1 || hasCalculatedValues then
`${seriesLabel} (${groupKey})` else groupKey" and use that same disambiguation
approach in the other similar block (the one around the second occurrence you
noted) so aggregatedData keys (and calls to aggregateValues(groups[groupKey],
s.aggregationType || 'count')) do not overwrite calculated-value labels.
🧹 Nitpick comments (1)
src/dashboard/Data/CustomDashboard/elements/GraphConfigDialog.react.js (1)

17-22: Consider reusing a shared STROKE_WIDTHS constant to avoid drift.
The same list exists in src/dashboard/Data/Browser/GraphDialog.react.js; extracting to a shared constants module would prevent mismatches as options evolve.

@mtrezza mtrezza merged commit 51feba4 into parse-community:alpha Jan 28, 2026
11 of 12 checks passed
@mtrezza mtrezza deleted the feat/graph-series branch January 28, 2026 01:36
parseplatformorg pushed a commit that referenced this pull request Jan 28, 2026
# [8.3.0-alpha.34](8.3.0-alpha.33...8.3.0-alpha.34) (2026-01-28)

### Features

* Replace graph fields with graph series for more customization ([#3157](#3157)) ([51feba4](51feba4))
@parseplatformorg
Copy link
Contributor

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

@parseplatformorg parseplatformorg added the state:released-alpha Released as alpha version label Jan 28, 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: 1

🤖 Fix all issues with AI agents
In `@src/lib/GraphDataUtils.js`:
- Around line 689-713: Labels for grouped pies include a " (Group)" suffix so
exact lookups in seriesStyleMap and calcValueColorMap miss configured colors;
update the color resolution in the labels.map block (where colors is built) to
fall back to the base label by stripping the group suffix before lookups:
compute baseLabel = label.split(' (')[0] (or similar) and if
seriesStyleMap.get(label) is falsy try seriesStyleMap.get(baseLabel), likewise
check calcValueColorMap.has(baseLabel) / get(baseLabel) before falling back to
defaultColors[index]; keep existing generateColors, seriesStyleMap and
calcValueColorMap logic but add this base-label fallback for both series and
calculated-value checks.

Comment on lines +689 to +713
// Generate default colors, then apply custom colors from series or calculated values
const defaultColors = generateColors(labels.length);

// Build a map of colors from calculated values
const calcValueColorMap = new Map();
if (calculatedValues && Array.isArray(calculatedValues)) {
calculatedValues.forEach(calc => {
if (calc.name && calc.color) {
calcValueColorMap.set(calc.name, calc.color);
}
});
}

const colors = labels.map((label, index) => {
// Check series style map first
const seriesStyle = seriesStyleMap.get(label);
if (seriesStyle && seriesStyle.color) {
return seriesStyle.color;
}
// Check calculated value color
if (calcValueColorMap.has(label)) {
return calcValueColorMap.get(label);
}
return defaultColors[index];
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Custom colors are dropped for grouped pie/doughnut labels.
When groupByColumn is set, labels become SeriesLabel (Group) or CalcName (Group), but the color lookup only checks exact label keys, so configured series/calc colors are ignored. This breaks customization for grouped pies.

🛠️ Suggested fix (base-label fallback)
-  const colors = labels.map((label, index) => {
-    // Check series style map first
-    const seriesStyle = seriesStyleMap.get(label);
-    if (seriesStyle && seriesStyle.color) {
-      return seriesStyle.color;
-    }
-    // Check calculated value color
-    if (calcValueColorMap.has(label)) {
-      return calcValueColorMap.get(label);
-    }
-    return defaultColors[index];
-  });
+  const colors = labels.map((label, index) => {
+    const baseLabel =
+      label.includes(' (') && label.endsWith(')')
+        ? label.slice(0, label.lastIndexOf(' ('))
+        : label;
+    // Check series style map first
+    const seriesStyle = seriesStyleMap.get(label) || seriesStyleMap.get(baseLabel);
+    if (seriesStyle && seriesStyle.color) {
+      return seriesStyle.color;
+    }
+    // Check calculated value color
+    if (calcValueColorMap.has(label)) {
+      return calcValueColorMap.get(label);
+    }
+    if (calcValueColorMap.has(baseLabel)) {
+      return calcValueColorMap.get(baseLabel);
+    }
+    return defaultColors[index];
+  });
🤖 Prompt for AI Agents
In `@src/lib/GraphDataUtils.js` around lines 689 - 713, Labels for grouped pies
include a " (Group)" suffix so exact lookups in seriesStyleMap and
calcValueColorMap miss configured colors; update the color resolution in the
labels.map block (where colors is built) to fall back to the base label by
stripping the group suffix before lookups: compute baseLabel = label.split('
(')[0] (or similar) and if seriesStyleMap.get(label) is falsy try
seriesStyleMap.get(baseLabel), likewise check calcValueColorMap.has(baseLabel) /
get(baseLabel) before falling back to defaultColors[index]; keep existing
generateColors, seriesStyleMap and calcValueColorMap logic but add this
base-label fallback for both series and calculated-value checks.

parseplatformorg pushed a commit that referenced this pull request Feb 5, 2026
# [8.3.0](8.2.0...8.3.0) (2026-02-05)

### Bug Fixes

* Canvas graph element does not apply data filter option ([#3128](#3128)) ([00ff1aa](00ff1aa))
* Canvas is not expandable or scrollable beyond current view size ([#3140](#3140)) ([cb73122](cb73122))
* Cloud Config parameter modal cannot scroll when content scales beyond visible area ([#3124](#3124)) ([bb6de31](bb6de31))
* Context menu of header cell in info panel does not group related records by class name ([#3122](#3122)) ([230c1e2](230c1e2))
* Context menu sub-menu in data browser vertically misaligned when scrolling in parent menu ([#3120](#3120)) ([2acaa27](2acaa27))
* Dashboard crashes when adding Parse Pointer JSON to array field in data browser ([#3125](#3125)) ([70bf081](70bf081))
* Data browser graph requires value field even when calculated value is defined ([#3127](#3127)) ([53e4f2b](53e4f2b))
* Graph in canvas ignores date filter constraints ([#3137](#3137)) ([6d8b8e6](6d8b8e6))
* Group-by not using custom aggregation type for single-series graph ([#3159](#3159)) ([b8e8891](b8e8891))
* Incorrect percentage and average calculation for calculated values in graphs ([#3152](#3152)) ([14b4d48](14b4d48))
* Info panel auto-scrolling not pausing during UI interaction like text selection or context menu display ([#3165](#3165)) ([bfe4e8a](bfe4e8a))
* Name of calculated value in data browser graph allows leading and trailing spaces ([#3132](#3132)) ([9493b18](9493b18))
* Optimize data browser cell context menu grouping and readability ([#3141](#3141)) ([5c711e1](5c711e1))
* Security upgrade react-router and react-router-dom ([#3107](#3107)) ([b76b9d1](b76b9d1))
* Setting a keyboard shortcut to its default value creates an unnecessary dashboard config storage entry ([#3173](#3173)) ([4949053](4949053))

### Features

* Add auto-scrolling for info panels ([#3149](#3149)) ([3cd8197](3cd8197))
* Add canvas tree to sidebar instead of loading dialog and favorite functionality ([#3146](#3146)) ([e58dc82](e58dc82))
* Add cloning of element in canvas ([#3144](#3144)) ([dec06ad](dec06ad))
* Add context menu in data browser to add cell content or selected text to Cloud Config parameter ([#3123](#3123)) ([9bc5197](9bc5197))
* Add context menu in data browser to get related records from String and Number fields ([#3118](#3118)) ([824bebd](824bebd))
* Add context menu item to get related records for selected text in data browser cell ([#3142](#3142)) ([33d3595](33d3595))
* Add custom dashboard canvas with graphs and data tables ([#3126](#3126)) ([d45c27b](d45c27b))
* Add customizable styles for line and bar series in data browser graph ([#3131](#3131)) ([501dd4b](501dd4b))
* Add customizable Y-axis titles for data browser graphs ([#3130](#3130)) ([2946e64](2946e64))
* Add dialog to execute Cloud Job with parameters ([#3158](#3158)) ([da419e0](da419e0))
* Add expanded view for canvas elements graph, table, view ([#3156](#3156)) ([0ffd767](0ffd767))
* Add field `objectId` to get related records context menu in data browser ([#3161](#3161)) ([2847ccf](2847ccf))
* Add formula-based calculated value to data browser graph ([#3129](#3129)) ([7c5d1b3](7c5d1b3))
* Add keyboard shortcut for executing script on selected rows in data browser ([#3171](#3171)) ([75389ad](75389ad))
* Add more customization options for graphs in canvas ([#3134](#3134)) ([ddbd666](ddbd666))
* Add non-alphanumeric character detection in Cloud Config parameters ([#3143](#3143)) ([1594ec8](1594ec8))
* Add quick-remove button to array parameter in Cloud Config ([#3121](#3121)) ([b632074](b632074))
* Add support for server side storage of Cloud Config parameter history ([#3169](#3169)) ([964e540](964e540))
* Allow adding View elements to canvas ([#3133](#3133)) ([2f2ae9a](2f2ae9a))
* Allow to favorite canvas for quick-access via sidebar menu ([#3135](#3135)) ([1e3a3c7](1e3a3c7))
* Allow to pause auto-scroll of info panel by holding the Option key ([#3160](#3160)) ([db38f14](db38f14))
* Allow to use ESC key to cancel, Cmd + Enter key to submit, Tab key to navigate a modal dialog ([#3172](#3172)) ([debdc09](debdc09))
* Detect and warn about unprintable characters in Cloud Config parameter values ([#3119](#3119)) ([26c909c](26c909c))
* Improve usability and layout of canvas and elements ([#3148](#3148)) ([cd654dc](cd654dc))
* Optimize appearance of graph tick labels on x-axis for date values ([#3147](#3147)) ([a9edcaf](a9edcaf))
* Optimize canvas menu organization ([#3145](#3145)) ([1558826](1558826))
* Replace graph fields with graph series for more customization ([#3157](#3157)) ([51feba4](51feba4))
* Various improvements for auto-scrolling info panel ([#3151](#3151)) ([423d83a](423d83a))
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