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


##########
superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx:
##########
@@ -63,10 +69,97 @@ export default function EchartsTimeseries({
   onLegendScroll,
 }: TimeseriesChartTransformedProps) {
   const { stack } = formData;
+  const theme = useTheme();
   const echartRef = useRef<EchartsHandler | null>(null);
   // eslint-disable-next-line no-param-reassign
   refs.echartRef = echartRef;
   const clickTimer = useRef<ReturnType<typeof setTimeout>>();
+
+  // Draggable percent-change baseline: when the rebase view is active, a
+  // vertical line is drawn on the plot; dragging it re-indexes every series
+  // to the hovered point via the composable rebase, entirely client-side.
+  const rebaseEnabled = Boolean(
+    (formData as { rebasePercentChange?: boolean }).rebasePercentChange,
+  );
+  useEffect(() => {
+    if (!rebaseEnabled) return undefined;
+    const chart = echartRef.current?.getEchartInstance?.();
+    if (!chart) return undefined;
+
+    const option = chart.getOption() as {
+      series?: { data?: SeriesDataPoint[] }[];
+    };
+    const baseSeries = (option.series ?? []).map(s =>
+      Array.isArray(s.data) ? (s.data as SeriesDataPoint[]) : [],
+    );
+    const xs = Array.from(
+      new Set(baseSeries.flat().map(([x]) => Number(x))),
+    ).sort((a, b) => a - b);

Review Comment:
   **Suggestion:** The x-values are coerced with `Number(x)` before snapping, 
which turns common datetime strings (for example ISO timestamps) into `NaN`; 
that makes baseline initialization/snap logic invalid and can break dragging 
behavior. Normalize/parsing should preserve valid time values instead of blind 
numeric coercion. [type error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Percent-change baseline fails on string-based time axes.
   - ⚠️ Dragging baseline may not update series correctly.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Open a Time-series Line chart in Explore that uses the ECharts renderer, 
which mounts
   `EchartsTimeseries` from
   
`superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx:50`
   for the visualization.
   
   2. Configure the chart so the x-axis values in the underlying `series.data` 
are datetime
   strings (for example ISO timestamps returned under `DTTM_ALIAS`), not 
pre-parsed numbers;
   these are read back from the chart via `chart.getOption()` in the effect at 
lines 89–93.
   
   3. Enable the Percent change / rebase view so `rebaseEnabled` at lines 81–83 
is true,
   causing the `useEffect` at lines 84–162 to run and compute `xs` at lines 
95–97 via
   `baseSeries.flat().map(([x]) => Number(x))`.
   
   4. Observe that `Number(x)` on string timestamps yields `NaN`, so `xs` 
contains `NaN`
   values and `baselineX = xs[0]` at line 99 becomes `NaN`; the subsequent
   `chart.convertToPixel({ xAxisIndex: 0 }, baselineX)` in `drawHandle()` at 
lines 110–115
   fails and the draggable baseline either does not render or behaves 
incorrectly when
   dragging.
   ```
   </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=2658bc4c99a844ca8806e66195e88040&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=2658bc4c99a844ca8806e66195e88040&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:** 95:97
   **Comment:**
        *Type Error: The x-values are coerced with `Number(x)` before snapping, 
which turns common datetime strings (for example ISO timestamps) into `NaN`; 
that makes baseline initialization/snap logic invalid and can break dragging 
behavior. Normalize/parsing should preserve valid time values instead of blind 
numeric coercion.
   
   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%2F42247&comment_hash=2c6aa33c2cbe97774f72bcdcf8eb45cbefbd95c8a3ad781ad773ac6481c3ae4d&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42247&comment_hash=2c6aa33c2cbe97774f72bcdcf8eb45cbefbd95c8a3ad781ad773ac6481c3ae4d&reaction=dislike'>👎</a>



##########
superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx:
##########
@@ -63,10 +69,97 @@ export default function EchartsTimeseries({
   onLegendScroll,
 }: TimeseriesChartTransformedProps) {
   const { stack } = formData;
+  const theme = useTheme();
   const echartRef = useRef<EchartsHandler | null>(null);
   // eslint-disable-next-line no-param-reassign
   refs.echartRef = echartRef;
   const clickTimer = useRef<ReturnType<typeof setTimeout>>();
+
+  // Draggable percent-change baseline: when the rebase view is active, a
+  // vertical line is drawn on the plot; dragging it re-indexes every series
+  // to the hovered point via the composable rebase, entirely client-side.
+  const rebaseEnabled = Boolean(
+    (formData as { rebasePercentChange?: boolean }).rebasePercentChange,
+  );
+  useEffect(() => {
+    if (!rebaseEnabled) return undefined;
+    const chart = echartRef.current?.getEchartInstance?.();
+    if (!chart) return undefined;
+
+    const option = chart.getOption() as {
+      series?: { data?: SeriesDataPoint[] }[];
+    };
+    const baseSeries = (option.series ?? []).map(s =>
+      Array.isArray(s.data) ? (s.data as SeriesDataPoint[]) : [],
+    );
+    const xs = Array.from(
+      new Set(baseSeries.flat().map(([x]) => Number(x))),
+    ).sort((a, b) => a - b);
+    if (xs.length === 0) return undefined;
+    let baselineX = xs[0];

Review Comment:
   **Suggestion:** The baseline position is stored in a local variable inside 
the effect, so any dependency-triggered rerun resets it to the first x-value 
and discards the user's dragged baseline. Persist the selected baseline in 
React state/ref and reapply it after rerenders/resizes. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ⚠️ User-chosen baseline resets on resize or option changes.
   - ⚠️ Rebasing state cannot persist across chart re-renders.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Render a Percent change Line chart so that `EchartsTimeseries` (file
   
`superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx:50`)
   receives `formData.rebasePercentChange` true, making `rebaseEnabled` true at 
lines 81–83
   and activating the baseline effect.
   
   2. Drag the vertical baseline handle to a later x-position; the `ondrag` 
handler at lines
   130–139 snaps to a new x via `snapToNearestX(xs, dataX)` and calls
   `applyBaseline(snapped)` at line 138, which updates the series and assigns 
the new value
   to the local `baselineX` variable at line 102.
   
   3. Cause a prop change that affects the effect dependencies, such as 
resizing the chart
   container (changing `width`/`height` passed into `EchartsTimeseries` at 
lines 52–54) or
   changing `echartOptions` by interacting with controls; the `useEffect` at 
lines 84–162
   depends on `[rebaseEnabled, echartOptions, width, height, theme]` (line 162) 
and therefore
   reruns.
   
   4. On rerun, `xs` is recomputed at lines 95–97 and `baselineX` is reset to 
`xs[0]` at line
   99 before `drawHandle()` is called, so the handle is redrawn at the first 
x-value and the
   previously user-selected baseline position is lost.
   ```
   </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=b16b823ef5d441b0a20cd3d8dfbf4b0e&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=b16b823ef5d441b0a20cd3d8dfbf4b0e&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:** 99:99
   **Comment:**
        *Logic Error: The baseline position is stored in a local variable 
inside the effect, so any dependency-triggered rerun resets it to the first 
x-value and discards the user's dragged baseline. Persist the selected baseline 
in React state/ref and reapply it after rerenders/resizes.
   
   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%2F42247&comment_hash=28f6901a2ec7a0b646f23a3131a62f2691d5783233d4a4c0ace5440fa810311a&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42247&comment_hash=28f6901a2ec7a0b646f23a3131a62f2691d5783233d4a4c0ace5440fa810311a&reaction=dislike'>👎</a>



##########
superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx:
##########
@@ -63,10 +69,97 @@ export default function EchartsTimeseries({
   onLegendScroll,
 }: TimeseriesChartTransformedProps) {
   const { stack } = formData;
+  const theme = useTheme();
   const echartRef = useRef<EchartsHandler | null>(null);
   // eslint-disable-next-line no-param-reassign
   refs.echartRef = echartRef;
   const clickTimer = useRef<ReturnType<typeof setTimeout>>();
+
+  // Draggable percent-change baseline: when the rebase view is active, a
+  // vertical line is drawn on the plot; dragging it re-indexes every series
+  // to the hovered point via the composable rebase, entirely client-side.
+  const rebaseEnabled = Boolean(
+    (formData as { rebasePercentChange?: boolean }).rebasePercentChange,
+  );
+  useEffect(() => {
+    if (!rebaseEnabled) return undefined;
+    const chart = echartRef.current?.getEchartInstance?.();
+    if (!chart) return undefined;
+
+    const option = chart.getOption() as {
+      series?: { data?: SeriesDataPoint[] }[];
+    };
+    const baseSeries = (option.series ?? []).map(s =>
+      Array.isArray(s.data) ? (s.data as SeriesDataPoint[]) : [],
+    );
+    const xs = Array.from(
+      new Set(baseSeries.flat().map(([x]) => Number(x))),
+    ).sort((a, b) => a - b);
+    if (xs.length === 0) return undefined;
+    let baselineX = xs[0];
+
+    const applyBaseline = (newX: number) => {
+      baselineX = newX;
+      chart.setOption({
+        series: baseSeries.map(data => ({
+          data: rebaseSeriesData(data, newX),
+        })),
+      });
+    };
+
+    const drawHandle = () => {
+      const gridRect = { top: 0, height: chart.getHeight() };
+      let px: number;
+      try {
+        [px] = [chart.convertToPixel({ xAxisIndex: 0 }, baselineX) as number];
+      } catch {
+        return;
+      }
+      chart.setOption({
+        graphic: [
+          {
+            id: 'percent-change-baseline',
+            type: 'rect',
+            x: px - 4,
+            y: gridRect.top,
+            shape: { width: 8, height: gridRect.height },
+            style: { fill: theme.colorFillQuaternary },
+            cursor: 'ew-resize',
+            draggable: true,
+            z: 100,
+            ondrag(this: { x: number; y: number }) {
+              this.y = gridRect.top;
+              const dataX = chart.convertFromPixel(
+                { xAxisIndex: 0 },
+                this.x + 4,
+              ) as number;
+              const snapped = snapToNearestX(xs, dataX);
+              if (snapped !== undefined && snapped !== baselineX) {
+                applyBaseline(snapped);
+              }

Review Comment:
   **Suggestion:** Rebasing every series on every `ondrag` event causes 
repeated full `setOption` updates while the pointer moves, which can freeze or 
stutter large charts. Throttle/debounce drag updates (or apply on drag end with 
lightweight preview) to avoid a high-frequency full-series recomputation loop. 
[possible bug]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ⚠️ Dragging baseline on large charts visibly stutters.
   - ⚠️ Interactive rebasing feels laggy for heavy datasets.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Render a Percent change time-series chart using the ECharts Line chart so 
that
   `EchartsTimeseries` in
   
`superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx:50`
   is mounted with `rebaseEnabled` true (lines 81–83).
   
   2. Use a dataset that produces many series points (large `baseSeries` array 
built at lines
   92–94) so rebasing involves substantial data (thousands of points across 
series).
   
   3. Drag the vertical baseline handle drawn by `drawHandle()` at lines 
110–155; during the
   drag, ECharts continuously invokes the `ondrag` handler defined at lines 
130–139.
   
   4. For each drag frame where `snapToNearestX(xs, dataX)` at line 136 returns 
a new value,
   `applyBaseline(snapped)` at line 138 runs, calling `chart.setOption({ series:
   baseSeries.map(...) })` at lines 101–107; this repeated full-series 
recomputation and
   re-render on a hot interaction path causes visible stutter or freezing while 
the baseline
   is dragged.
   ```
   </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=a16723fae8ca46fa967e3d0f95c66a16&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=a16723fae8ca46fa967e3d0f95c66a16&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:** 130:139
   **Comment:**
        *Possible Bug: Rebasing every series on every `ondrag` event causes 
repeated full `setOption` updates while the pointer moves, which can freeze or 
stutter large charts. Throttle/debounce drag updates (or apply on drag end with 
lightweight preview) to avoid a high-frequency full-series recomputation loop.
   
   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%2F42247&comment_hash=9c3949af6aca6a97e7313f4b0c7bc708dc68685bdef70603b00727ad87090815&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42247&comment_hash=9c3949af6aca6a97e7313f4b0c7bc708dc68685bdef70603b00727ad87090815&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