This is an automated email from the ASF dual-hosted git repository. github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-7396-ae3ad45c45712e22625a5e30516cc1a31df8c5de in repository https://gitbox.apache.org/repos/asf/texera.git
commit 5914ae077fee211ba89af55ac7fea86bde2e0b72 Author: Kary Zheng <[email protected]> AuthorDate: Sun Aug 9 17:11:54 2026 -0700 feat(workflow-operator): stop forcing a color column on every Bubble Chart (#7396) ### What changes were proposed in this PR? Bubble Chart's Color-Column was declared `required = true` with `@NotNull`, but the generated Python reads it only inside the Enable Color branch. The effect was that a freshly dropped Bubble Chart stayed invalid until the user picked a color column, even when they wanted plain bubbles — and the column they picked was then never used. This PR makes the field optional and puts it behind the toggle via `toggleHidden`, so it disappears from the panel when Enable Color is off. That matches Ternary Plot, which has the same toggle-plus-column pair and already declares its color field optional. The color decision also moves out of the generated Python and into Scala. The old template emitted an `if '...' == 'true':` comparison over a Scala Boolean; it is now a `colorArg` computed at build time, guarded on both the toggle and the column being non-empty. That second half matters: with the required flag gone, an empty column would otherwise reach `px.scatter(color='')`, which plotly rejects — the same failure fixed for Bar Chart in #6792. Behavior for existing workflows is unchanged. `enableColor` keeps its meaning, so no saved chart changes appearance. The operator reference page is updated to match the new requirement and description. ### Any related issues, documentation, discussions? Closes #7395 ### How was this PR tested? Existing `BubbleChartOpDescSpec` passes unchanged, including the assertion that pins the no-color output line. Three cases were added to it, covering the toggle-and-column matrix: enabled with a column chosen (color is emitted), enabled with no column (color is omitted rather than emitted empty), and disabled with a column chosen (the column is not emitted). ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5) Co-authored-by: Meng Wang <[email protected]> --- .../bubbleChart/BubbleChartOpDesc.scala | 15 +++++----- .../bubbleChart/BubbleChartOpDescSpec.scala | 32 ++++++++++++++++++++++ .../operators/visualization/basic/bubble-chart.md | 2 +- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/visualization/bubbleChart/BubbleChartOpDesc.scala b/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/visualization/bubbleChart/BubbleChartOpDesc.scala index ad31361064..edb83c2bbb 100644 --- a/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/visualization/bubbleChart/BubbleChartOpDesc.scala +++ b/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/visualization/bubbleChart/BubbleChartOpDesc.scala @@ -75,13 +75,15 @@ class BubbleChartOpDesc extends PythonOperatorDescriptor { @JsonProperty(value = "enableColor", defaultValue = "false") @JsonSchemaTitle("Enable Color") @JsonPropertyDescription("Colors bubbles using a data column") + @JsonSchemaInject(json = """{"toggleHidden" : ["colorCategory"]}""") var enableColor: Boolean = false - @JsonProperty(value = "colorCategory", required = true) + @JsonProperty(value = "colorCategory", required = false) @JsonSchemaTitle("Color-Column") - @JsonPropertyDescription("Picks data column to color bubbles with if color is enabled") + @JsonPropertyDescription( + "Optional data column to color bubbles with; leave empty for uniform bubbles" + ) @AutofillAttributeName - @NotNull(message = "Color-Column cannot be empty") var colorCategory: EncodableString = "" override def getOutputSchemas( @@ -114,11 +116,10 @@ class BubbleChartOpDesc extends PythonOperatorDescriptor { assert(xValue.nonEmpty, "X-Column cannot be empty") assert(yValue.nonEmpty, "Y-Column cannot be empty") assert(zValue.nonEmpty, "Z-Column cannot be empty") + // An unset column counts as "no color" even with the toggle on, else px.scatter(color='') fails. + val colorArg = if (enableColor && colorCategory.nonEmpty) pyb", color=$colorCategory" else pyb"" pyb""" - | if '$enableColor' == 'true': - | fig = go.Figure(px.scatter(table, x=$xValue, y=$yValue, size=$zValue, size_max=100, color=$colorCategory)) - | else: - | fig = go.Figure(px.scatter(table, x=$xValue, y=$yValue, size=$zValue, size_max=100)) + | fig = go.Figure(px.scatter(table, x=$xValue, y=$yValue, size=$zValue$colorArg, size_max=100)) |""" } diff --git a/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/visualization/bubbleChart/BubbleChartOpDescSpec.scala b/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/visualization/bubbleChart/BubbleChartOpDescSpec.scala index 85fbd1fa3f..37c4197b6b 100644 --- a/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/visualization/bubbleChart/BubbleChartOpDescSpec.scala +++ b/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/visualization/bubbleChart/BubbleChartOpDescSpec.scala @@ -53,6 +53,38 @@ class BubbleChartOpDescSpec extends AnyFlatSpec with BeforeAndAfter with Matcher ) } + it should "color by the chosen column when color is enabled" in { + opDesc.xValue = "column1" + opDesc.yValue = "column2" + opDesc.zValue = "column3" + opDesc.enableColor = true + opDesc.colorCategory = "column4" + + opDesc.createPlotlyFigure().plain should include( + "fig = go.Figure(px.scatter(table, x=column1, y=column2, size=column3, color=column4, size_max=100))" + ) + } + + // px.scatter(color='') raises, so an unset column has to fall back to uniform bubbles. + it should "omit color when color is enabled but no column is chosen" in { + opDesc.xValue = "column1" + opDesc.yValue = "column2" + opDesc.zValue = "column3" + opDesc.enableColor = true + + opDesc.createPlotlyFigure().plain should not include "color=" + } + + it should "omit color when a column is chosen but color is disabled" in { + opDesc.xValue = "column1" + opDesc.yValue = "column2" + opDesc.zValue = "column3" + opDesc.enableColor = false + opDesc.colorCategory = "column4" + + opDesc.createPlotlyFigure().plain should not include "column4" + } + it should "throw assertion error if variable xValue is empty" in { assertThrows[AssertionError] { opDesc.createPlotlyFigure() diff --git a/docs/reference/operators/visualization/basic/bubble-chart.md b/docs/reference/operators/visualization/basic/bubble-chart.md index e1dde75f62..4489cacedd 100644 --- a/docs/reference/operators/visualization/basic/bubble-chart.md +++ b/docs/reference/operators/visualization/basic/bubble-chart.md @@ -35,7 +35,7 @@ tags: [visualization, basic] | Y-Column | ✓ | String | - | Data column for the y-axis | | Z-Column | ✓ | String | - | Data column to determine bubble size | | Enable Color | | Boolean | false | Colors bubbles using a data column | -| Color-Column | ✓ | String | - | Picks data column to color bubbles with if color<br>is enabled | +| Color-Column | | String | - | Optional data column to color bubbles with; leave<br>empty for uniform bubbles | ### Output Ports
