codeant-ai-for-open-source[bot] commented on code in PR #41111:
URL: https://github.com/apache/superset/pull/41111#discussion_r3465252082


##########
superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx:
##########
@@ -234,12 +257,15 @@ export default function EchartsTimeseries({
           // Cross-filter by dimension (original behavior)
           const { seriesName: name } = props;
           handleChange(name);
-        } else if (canCrossFilterByXAxis && props.name != null) {
-          // Cross-filter by X-axis value when no dimensions (issue #25334).
-          // Use `name` (the category-axis value) instead of `data[0]`: for
-          // horizontal bars the data tuple is value-first, so `data[0]` would
-          // be the metric value rather than the category (issue #41102).
-          handleXAxisChange(props.name);
+        } else if (canCrossFilterByXAxis) {
+          // Cross-filter by X-axis value when no dimensions (issue #25334)
+          const categoryAxisValue = getCategoryAxisValue(
+            props.data,
+            props.name,
+          );
+          if (categoryAxisValue !== undefined) {
+            handleXAxisChange(categoryAxisValue);
+          }

Review Comment:
   **Suggestion:** The generic `click` handler now triggers X-axis 
cross-filtering for any click event when there are no dimensions, including 
axis-label clicks that are also handled by `queryEventHandlers`. This causes 
duplicate `setDataMask` updates for a single user action and can trigger 
redundant dashboard re-filter/query cycles. Restrict this branch to series data 
clicks (or skip axis component clicks) so axis-label clicks are handled only 
once by the query-based handler. [performance]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Duplicate cross-filter queries on X-axis label clicks.
   - ⚠️ Increased dashboard latency from redundant filter updates.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Create or open an ECharts timeseries chart (plugin registered at
   
`superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/index.ts:34-43`) 
with no
   `groupby` (so `hasDimensions` is false) and a categorical X-axis 
(`xAxis.type ===
   AxisType.Category`), which satisfies `canCrossFilterByXAxis` in
   `EchartsTimeseries.tsx:221-223`.
   
   2. Observe that `transformProps` enables axis-level click events for this 
configuration by
   setting `triggerEvent: true` when `xAxisType === AxisType.Category && 
groupBy.length ===
   0` in
   
`superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts:13-16`
   (shown via `Read`), so X-axis labels emit `click` events.
   
   3. When the chart renders, `Echart` registers both the generic click handler 
and the
   query-based click handler: `chartRef.current?.on(name, handler)` for 
`eventHandlers` in
   
`superset-frontend/plugins/plugin-chart-echarts/src/components/Echart.tsx:90-93`,
 and
   `chartRef.current?.on(name, query, handler)` for `queryEventHandlers` in
   `Echart.tsx:95-97`, using the handlers defined in `EchartsTimeseries.tsx`
   (`eventHandlers.click` at lines 246-271 and `queryEventHandlers` at 385-393).
   
   4. Clicking an X-axis category label (e.g., "Product A") causes ECharts to 
fire a `click`
   event on the axis label, which matches both the generic `click` listener and 
the filtered
   `click` listener with query `${categoryAxis}.category`. The generic handler 
in
   `EchartsTimeseries.tsx:246-271` enters the `else if (canCrossFilterByXAxis)` 
branch at
   line 260, computes a category value via `getCategoryAxisValue(props.data, 
props.name)` at
   lines 262-265, and calls `handleXAxisChange(categoryAxisValue)` at line 267, 
which in turn
   calls `setDataMask(getXAxisCrossFilterDataMask(xAxisValue).dataMask)` at 
lines 211-217.
   Independently, the query-based handler `handleXAxisLabelClick` registered in
   `queryEventHandlers` at lines 369-393 receives the same axis-label `click` 
as an
   `ECElementEvent` and calls `handleXAxisChange(event.value)` at lines 
370-377. As a result,
   a single axis-label click triggers `handleXAxisChange` twice, and thus 
`setDataMask`
   twice, causing duplicate cross-filter updates and redundant downstream 
queries.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=953fd8d0d1e1407abaf609bf787120c7&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=953fd8d0d1e1407abaf609bf787120c7&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx
   **Line:** 260:268
   **Comment:**
        *Performance: The generic `click` handler now triggers X-axis 
cross-filtering for any click event when there are no dimensions, including 
axis-label clicks that are also handled by `queryEventHandlers`. This causes 
duplicate `setDataMask` updates for a single user action and can trigger 
redundant dashboard re-filter/query cycles. Restrict this branch to series data 
clicks (or skip axis component clicks) so axis-label clicks are handled only 
once by the query-based handler.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41111&comment_hash=1ff0bbb4e25054ff25d9c4359d8c0a00830eb5a9cd213efa5160dbdecf622691&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41111&comment_hash=1ff0bbb4e25054ff25d9c4359d8c0a00830eb5a9cd213efa5160dbdecf622691&reaction=dislike'>👎</a>



##########
superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx:
##########
@@ -218,6 +221,26 @@ export default function EchartsTimeseries({
   // Determine if X-axis can be used for cross-filtering (categorical axis 
without dimensions)
   const canCrossFilterByXAxis =
     !hasDimensions && xAxis.type === AxisType.Category;
+  const categoryAxisValueIndex =
+    formData.orientation === OrientationType.Horizontal ? 1 : 0;
+  const getCategoryAxisValue = useCallback(
+    (data: unknown, name: unknown) => {
+      if (Array.isArray(data)) {
+        const categoryAxisValue = data[categoryAxisValueIndex];
+        if (
+          typeof categoryAxisValue === 'string' ||
+          typeof categoryAxisValue === 'number'
+        ) {
+          return categoryAxisValue;
+        }
+      }
+      if (typeof name === 'string' || typeof name === 'number') {
+        return name;

Review Comment:
   **Suggestion:** Falling back to `name` without checking event source can 
convert non-category interactions (for example legend/component clicks that 
also carry a string `name`) into X-axis filters, producing incorrect filter 
values for the X-axis column. Only use `name` when the event is known to come 
from category-axis label clicks (or series points with verified category 
payload), otherwise ignore it. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Legend clicks can apply incorrect X-axis filters.
   - ⚠️ Users see unexpected filters after legend toggles.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Use an ECharts timeseries chart with no `groupby` and a categorical 
X-axis (`xAxis.type
   === AxisType.Category`), so `hasDimensions` is false and 
`canCrossFilterByXAxis` is true
   as defined in
   
`superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx:221-223`.
   Cross-filtering is enabled via `emitCrossFilters` and `setDataMask` from
   `CrossFilterTransformedProps` in
   `superset-frontend/plugins/plugin-chart-echarts/src/types.ts:156-163`.
   
   2. At render time, `Echart` registers a generic `click` handler for all 
chart clicks at
   
`superset-frontend/plugins/plugin-chart-echarts/src/components/Echart.tsx:90-93`,
 wiring
   it to `eventHandlers.click` defined in `EchartsTimeseries.tsx:246-271`. The 
same
   `eventHandlers` object also registers legend-related handlers 
(`legendselectchanged`,
   `legendselectall`, `legendinverseselect`) at lines 281-289, indicating 
legend interactions
   are part of this chart's behavior.
   
   3. When the user clicks a legend item representing a metric (for example, 
legend entry
   "Sales"), ECharts emits a `click` event for the legend component with a 
string `name` (the
   series name) alongside legend-select events; this `click` is handled by the 
generic
   `eventHandlers.click` registered in `Echart.tsx:90-93`. Because 
`hasDimensions` is false
   and `canCrossFilterByXAxis` is true, the handler's timer branch in
   `EchartsTimeseries.tsx:16-31` takes the `else if (canCrossFilterByXAxis)` 
path at line 21.
   
   4. Inside that branch, `getCategoryAxisValue(props.data, props.name)` is 
called at lines
   23-26; for a legend click, `props.data` is not an X-axis tuple (often 
undefined), while
   `props.name` is the legend label "Sales". Since `Array.isArray(data)` is 
false,
   `getCategoryAxisValue` falls through to the unscoped fallback at lines 
237-238 (`if
   (typeof name === 'string' || typeof name === 'number') { return name; }`), 
returning
   `"Sales"` even though it is not an X-axis category value. The handler then 
calls
   `handleXAxisChange(categoryAxisValue)` at line 27, which invokes
   `setDataMask(getXAxisCrossFilterDataMask(xAxisValue).dataMask)` at lines 
211-217, building
   a filter on the X-axis column (`xAxis.label`) with value `"Sales"` via
   `getXAxisCrossFilterDataMask` at lines 163-197. This produces an incorrect 
X-axis filter
   derived from a legend interaction rather than a real category, so legend 
clicks can
   unintentionally drive X-axis cross-filters with invalid values.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=d2e406ac63a44a1b8aabf0bebf09b5bf&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=d2e406ac63a44a1b8aabf0bebf09b5bf&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx
   **Line:** 237:238
   **Comment:**
        *Logic Error: Falling back to `name` without checking event source can 
convert non-category interactions (for example legend/component clicks that 
also carry a string `name`) into X-axis filters, producing incorrect filter 
values for the X-axis column. Only use `name` when the event is known to come 
from category-axis label clicks (or series points with verified category 
payload), otherwise ignore it.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41111&comment_hash=2cb1e0728f94cbf0a0a3a202695f090cdbe755d413a02bfa8ecb63739b78e0da&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41111&comment_hash=2cb1e0728f94cbf0a0a3a202695f090cdbe755d413a02bfa8ecb63739b78e0da&reaction=dislike'>👎</a>



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to