aminghadersohi commented on code in PR #45612:
URL: https://github.com/apache/superset/pull/45612#discussion_r4379855945


##########
superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx:
##########
@@ -679,41 +683,64 @@ export default function EchartsTimeseries({
         const xAxisCol =
           // if the xAxis is '__timestamp', granularity_sqla will be the 
column of filter
           xAxis.label === DTTM_ALIAS ? formData.granularitySqla : xAxis.label;
-        if (data && xAxis.type === AxisType.Time && xAxisCol) {
-          // For horizontal orientation the [x, value] pair is swapped
-          const xValue = Array.isArray(data) ? data[xAxisValueIndex] : data;
-          const xAxisFilter = getTemporalXAxisDrillByFilter(
-            xAxisCol,
+        const isTemporalCategory =
+          xAxis.type === AxisType.Category &&
+          coltypeMapping?.[getColumnLabel(xAxis.label)] ===
+            GenericDataType.Temporal;
+        if ((xAxis.type === AxisType.Time || isTemporalCategory) && xAxisCol) {
+          // A markerless line/area event identifies the series but no point.
+          // Snap its pixel coordinate to an actual bucket in that series.
+          const series = ensureIsArray(echartOptions.series)[
+            eventParams.seriesIndex
+          ];
+          const xValue = getTimeAxisDrillByValue(
+            data ??
+              (isTemporalCategory && eventParams.name
+                ? eventParams.name
+                : undefined),
+            series,
+            data
+              ? undefined
+              : echartRef.current
+                  ?.getEchartInstance()
+                  ?.convertFromPixel({ seriesIndex: eventParams.seriesIndex }, 
[
+                    eventParams.event.offsetX,
+                    eventParams.event.offsetY,
+                  ]),
+            xAxisValueIndex,
+            isTemporalCategory,
+          );
+          const xAxisFilter = getTemporalBucketDrillByFilter(
+            // A grained '__timestamp' bucket resolves to the time column the
+            // query groups by, including a dashboard Time Column override.
+            resolvedTimeGrain ? xAxis.label : xAxisCol,

Review Comment:
   Fixed in 195a3a38834842260fe7f03cbb622c6606d402ab. I now emit the effective 
real time column for legacy `__timestamp` axes (dashboard Time Column override 
first, then `granularitySqla`) in both Timeseries and Mixed charts. Explicit 
x-axis labels remain unchanged, including SQL axes.
   
   Regression test: `Drill by uses the dashboard time grain for the clicked 
time-axis bucket`
   Its real-column assertion fails with the original source and passes here. I 
also added the legacy Timeseries and Mixed Edit-chart cases, each with and 
without a dashboard Time Column override; all four failed with `col: 
__timestamp` before the change and pass with the real column. The scoped Jest 
suites pass (481 tests), including query/CSV/Explore predicate transport; 
Docker backend sibling suites pass (338 tests).
   
   Siblings checked:
   - 
superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx:683
 — fixed in 195a3a38834842260fe7f03cbb622c6606d402ab
   - 
superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/EchartsMixedTimeseries.tsx:225
 — fixed in 195a3a38834842260fe7f03cbb622c6606d402ab
   - 
superset-frontend/plugins/plugin-chart-echarts/src/utils/xAxisDrillByFilter.ts:197
 — not affected: accepts its caller's column unchanged; both production callers 
are covered above.
   - superset-frontend/src/components/Chart/DrillBy/DrillBySubmenu.tsx:156 — 
not affected: forwards the resolved bucket filter without changing its column.
   - superset-frontend/src/components/Chart/DrillBy/DrillByModal.tsx:111 — not 
affected: query, downloads and Edit chart share the drilled form data; it does 
not create timestamp aliases.
   - 
superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/mixins.tsx:47
 — not affected: Explore can still initialize x_axis from granularity_sqla; the 
persisted filter names the real column rather than the legacy alias.
   - superset/models/helpers.py:5454 — not affected: physical time-column 
filters already resolve in both legacy and non-legacy queries; backend changes 
are unnecessary.
   



##########
superset-frontend/plugins/plugin-chart-echarts/src/utils/xAxisDrillByFilter.ts:
##########
@@ -165,3 +165,72 @@ export const getTemporalXAxisDrillByFilter = (
     formattedVal,
   };
 };
+
+/**
+ * Build the Drill by filter for a clicked temporal bucket. With a time grain
+ * it matches the grained column, like Drill to detail: the backend compares
+ * the bucket the chart grouped by (same grain, Hours offset and Time Column)
+ * and, unlike a TEMPORAL_RANGE, never replaces it with a query time range, so
+ * the drill keeps every other filter of the chart as the chart applied it.
+ * Without a grain it falls back to an exact match on the timestamp.
+ */
+export const getTemporalBucketDrillByFilter = (
+  col: QueryFormColumn,
+  value: unknown,
+  grain?: TimeGranularity,
+  formattedVal?: string,
+): BinaryQueryObjectFilterClause | undefined => {
+  const bucket = parseTemporalValue(value);
+  if (!col || !bucket) {
+    return undefined;
+  }
+  return grain
+    ? { col, op: '==', val: bucket.getTime(), grain, formattedVal }
+    : { col, op: '==', val: formatNaiveDateTime(bucket), formattedVal };
+};
+
+/** Resolve a markerless line/area click to a real bucket in that series. */
+export const getTimeAxisDrillByValue = (
+  data: unknown,
+  series: unknown,
+  coordinate: unknown,
+  valueIndex = 0,
+  categorical = false,
+): unknown => {
+  if (Array.isArray(data)) {
+    return data[valueIndex];
+  }
+  if (typeof data === 'number' || typeof data === 'string') {
+    return data;
+  }
+  const axisValue = Array.isArray(coordinate)
+    ? coordinate[valueIndex]
+    : coordinate;
+  if (
+    typeof axisValue !== 'number' ||
+    !Number.isFinite(axisValue) ||
+    typeof series !== 'object' ||
+    series === null ||
+    !('data' in series) ||
+    !Array.isArray(series.data)
+  ) {
+    return undefined;
+  }
+  if (categorical) {
+    const point: unknown = series.data[Math.round(axisValue)];

Review Comment:
   Fixed in 195a3a38834842260fe7f03cbb622c6606d402ab. I now resolve the 
category index through ECharts' shared axis domain, then look up that 
category's point in the clicked series. An absent point produces no bucket 
instead of selecting the next month. The axis model supplies auto-collected 
categories, which are not present in getOption().
   
   Regression test: `Mixed categorical markerless Drill by uses shared axis 
categories for a sparse query B`
   It checks February, March and absent January. It fails with the original 
source and passes here. The horizontal/vertical helper regression also fails 
before and passes after; a real ECharts SSR test checks auto-collected 
categories in both orientations. All 481 scoped Jest tests pass.
   
   Siblings checked:
   - 
superset-frontend/plugins/plugin-chart-echarts/src/utils/xAxisDrillByFilter.ts:213
 — fixed in 195a3a38834842260fe7f03cbb622c6606d402ab
   - 
superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/EchartsMixedTimeseries.tsx:239
 — fixed in 195a3a38834842260fe7f03cbb622c6606d402ab
   - 
superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx:700
 — fixed in 195a3a38834842260fe7f03cbb622c6606d402ab
   - 
superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx:253
 — not affected: percentage-baseline dragging does not call the drill helper or 
index a sparse series by axis index.
   - 
superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx:761
 — not affected: cross-filter handlers read the event's value, not a markerless 
category index.
   - superset-frontend/src/components/Chart/DrillBy/DrillBySubmenu.tsx:156 — 
not affected: consumes the resolved filter and performs no pixel or 
series-index lookup.
   



-- 
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