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


##########
superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/EchartsSunburst.tsx:
##########
@@ -120,26 +123,53 @@ export default function EchartsSunburst(props: 
SunburstTransformedProps) {
         const drillToDetailFilters: BinaryQueryObjectFilterClause[] = [];
         const drillByFilters: BinaryQueryObjectFilterClause[] = [];
         if (columns?.length) {
-          treePath.forEach((path, i) =>
-            drillToDetailFilters.push({
-              col: columns[i],
-              op: '==',
-              val: records[i],
-              formattedVal: path,
-            }),
-          );
-          const val = treePath[treePath.length - 1];
-          drillByFilters.push({
-            col: columns[treePath.length - 1],
-            op: '==',
-            val,
-            formattedVal: formatSeriesName(val, {
-              timeFormatter: getTimeFormatter(formData.dateFormat),
-              numberFormatter: getNumberFormatter(formData.numberFormat),
-              coltype:
-                coltypeMapping?.[getColumnLabel(columns[treePath.length - 1])],
-            }),
+          const timeGrain = (formData.extraFormData?.time_grain_sqla ??
+            formData.timeGrainSqla) as TimeGranularity | undefined;
+          treePath.forEach((path, i) => {
+            // Range filters apply the dataset timezone/offset to both bucket
+            // bounds. Equality on a truncated column bypasses that handling.
+            const temporalFilter =
+              timeGrain &&
+              isGrainedLevel(
+                columns[i],
+                formData.temporalColumnsLookup,
+                formData.granularitySqla,
+              )
+                ? getTemporalXAxisDrillByFilter(
+                    columns[i],
+                    records[i],
+                    timeGrain,
+                    path,
+                  )
+                : undefined;
+            drillToDetailFilters.push(
+              temporalFilter ?? {
+                col: columns[i],
+                op: '==',
+                val: records[i],
+                formattedVal: path,
+              },
+            );
+            if (temporalFilter && i === treePath.length - 1) {
+              drillByFilters.push(temporalFilter);
+            }

Review Comment:
   The behavior described is accurate, but this PR does not introduce it. Drill 
by on Sunburst has only ever filtered the clicked level, for every ancestor 
type: on master before this PR (EchartsSunburst.tsx:131-142 at f9a0d8af49) the 
drill-by filter list is only `columns[treePath.length - 1] == value`, so a 
categorical child under a categorical ancestor also drops that ancestor. This 
PR keeps that contract and only changes the clicked level's own filter when 
that level is a grained temporal column (EchartsSunburst.tsx:153-172 at 
9d8c2acb81, pinned by `drill-by on a grained temporal segment uses its raw 
bucket instead of its label` and `categorical drill-by and root detail filters 
retain their behavior` in test/Sunburst/EchartsSunburst.test.tsx). 
https://github.com/apache/superset/pull/45598 keeps the same last-level-only 
rule.
   
   Carrying temporal ancestors alone would make Drill by keep a date bucket 
while dropping a region above it, which is a separate change to Drill by 
semantics for all hierarchy levels.
   
   Remaining: Drill by from a child segment does not carry any ancestor filters 
(temporal or categorical). Not changed in this PR; I am leaving this thread 
open for the maintainers to decide whether Drill by should carry ancestor 
filters.
   



##########
superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/buildQuery.ts:
##########
@@ -16,14 +16,83 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { buildQueryContext, QueryFormData } from '@superset-ui/core';
+import {
+  AdhocColumn,
+  buildQueryContext,
+  ensureIsArray,
+  isPhysicalColumn,
+  QueryFormColumn,
+  QueryFormData,
+} from '@superset-ui/core';
+
+// A hierarchy level takes the time grain when it is a physical column that the
+// temporal lookup (or the legacy ``granularity_sqla``) marks temporal.
+export function isGrainedLevel(
+  column: QueryFormColumn,
+  temporalColumnsLookup: Record<string, boolean> | undefined,
+  granularitySqla: string | undefined,
+): boolean {
+  return (
+    isPhysicalColumn(column) &&
+    (!!temporalColumnsLookup?.[column] || granularitySqla === column)
+  );
+}
+
+// Wrap each temporal hierarchy level in the BASE_AXIS column reference that
+// carries the time grain, the shape ``normalizeTimeColumn`` uses for a 
physical
+// x-axis. Non-temporal levels are left untouched.
+function applyTimeGrain(
+  columns: QueryFormColumn[],
+  formData: QueryFormData,
+  timeGrain: string | undefined,
+): { columns: QueryFormColumn[]; grained: boolean } {
+  let grained = false;
+  const mapped = columns.map(column => {
+    if (
+      timeGrain &&
+      isPhysicalColumn(column) &&
+      isGrainedLevel(
+        column,
+        formData.temporal_columns_lookup,
+        formData.granularity_sqla,
+      )
+    ) {
+      grained = true;
+      return {
+        timeGrain,
+        columnType: 'BASE_AXIS',
+        sqlExpression: column,
+        label: column,
+        expressionType: 'SQL',
+        isColumnReference: true,
+      } as AdhocColumn;

Review Comment:
   Confirmed at 9d8c2acb81: `getCrossFilterDataMask` emits `{col: 
columns[treePath.length - 1], op: '==', val: <formatted segment name>}` 
(EchartsSunburst.tsx:78-96), so a grained temporal segment cross-filters by its 
label. This PR does not touch the cross-filter path; its scope is Explore 
keeping the saved grain plus the drill ranges.
   
   The cross-filter fix is in https://github.com/apache/superset/pull/45598: 
the click path there builds the filter from the raw record with 
`getSunburstFilter`, which returns a `TEMPORAL_RANGE` over the bucket for a 
grained temporal level and also sets `time_range` on `extraFormData`. Resolving 
here as covered by that PR.
   



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