aminghadersohi commented on code in PR #45571:
URL: https://github.com/apache/superset/pull/45571#discussion_r4351297947
##########
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(
Review Comment:
Fixed in 80118e754d0f087124087fdfc59ebae3e4e2a8e5 (drill payload, factory
and SQL) and e3492ea8b6b73bb03479637bb7e421c314bcd54b (adhoc transport). Both
Sunburst drill actions send raw bucket equality plus `grain`. The factory
retains that predicate alongside a Time Range/Time Column override, and SQL
applies the dataset Hours offset before truncation. Semantic drills select the
provider's grained dimension rather than an exact instant.
Regression test:
`tests/unit_tests/models/test_sunburst_drill_hours_offset.py::test_sunburst_factory_drill_preserves_bucket_with_time_range`
covers samples/full with and without legacy granularity, asserting category
membership as well as counts. The four direct-filter cases fail with the
previous backend; all eight direct/adhoc cases pass at this head.
`tests/unit_tests/models/test_sunburst_drill_hours_offset.py::test_sunburst_drill_grain_matches_ring_bucket_with_hours_offset`
also rejects equal-count/wrong-row results.
The actual DrillByModal conversion path also retains the grain: Regression
test: `Drill by retains the temporal bucket grain through adhoc form data` in
`superset-frontend/src/utils/simpleFilterToAdhoc.test.ts` fails before the
adapter change and passes after.
`tests/unit_tests/common/test_form_data_query_context.py::test_temporal_drill_grain_survives_adhoc_adapters`
reproduces all three backend-adapter losses before and passes after.
Siblings checked:
-
superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/EchartsSunburst.tsx
— fixed in 80118e754d0f087124087fdfc59ebae3e4e2a8e5
- superset/common/query_context_factory.py — fixed in
80118e754d0f087124087fdfc59ebae3e4e2a8e5
- superset/models/helpers.py — fixed in
80118e754d0f087124087fdfc59ebae3e4e2a8e5
- superset/semantic_layers/mapper.py — fixed in
80118e754d0f087124087fdfc59ebae3e4e2a8e5
-
superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx
— fixed in 80118e754d0f087124087fdfc59ebae3e4e2a8e5 (detail already emits
equality plus grain; its shared SQL filter path gets the Hours offset
correction)
-
superset-frontend/plugins/plugin-chart-echarts/src/utils/xAxisDrillByFilter.ts
— not affected: Sunburst drills no longer call the range helper; the unchanged
Timeseries Drill by range contract is outside this Sunburst change
-
superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/EchartsSunburst.tsx:52
— not affected: cross-filter payload changes are handled separately in
https://github.com/apache/superset/pull/45598
- superset-frontend/src/utils/simpleFilterToAdhoc.ts — fixed in
e3492ea8b6b73bb03479637bb7e421c314bcd54b
- superset-frontend/packages/superset-ui-core/src/query/convertFilter.ts —
fixed in e3492ea8b6b73bb03479637bb7e421c314bcd54b
-
superset-frontend/src/explore/components/controls/FilterControl/AdhocFilter/index.ts
— fixed in e3492ea8b6b73bb03479637bb7e421c314bcd54b
- superset/utils/core.py — fixed in e3492ea8b6b73bb03479637bb7e421c314bcd54b
- superset/common/form_data_query_context.py — fixed in
e3492ea8b6b73bb03479637bb7e421c314bcd54b
- superset-frontend/src/components/Chart/DrillBy/DrillByModal.tsx — fixed in
e3492ea8b6b73bb03479637bb7e421c314bcd54b (its existing adapter calls preserve
timeGrain)
- superset/mcp_service/chart/schemas.py — not affected: get_chart_info's
filter summary is read-only metadata, not a query reconstruction path
Final head: `8cc881ab51c29c79d574d7b254933fa7babd3019`.
##########
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)
Review Comment:
Fixed in 80118e754d0f087124087fdfc59ebae3e4e2a8e5. An explicit Time Column
takes precedence over the lookup, and a hidden control preserves that subject
through Explore reconstruction. Without an explicit subject, all physical
temporal levels still receive the grain. The dashboard Time Column override
follows the same precedence in querying and drills. I also corrected the
description: Explore does persist the lookup in params.
Regression test:
`superset-frontend/src/explore/controlUtils/sunburstTimeGrain.test.ts` —
`Explore preserves an MCP time-column subject in a two-temporal-level
hierarchy` fails before this change and passes after.
`tests/unit_tests/models/test_sunburst_drill_hours_offset.py::test_sunburst_explicit_subject_matches_explore_lookup`
and
`tests/unit_tests/mcp_service/chart/test_sunburst_chart.py::test_mcp_time_column_override_grains_one_hierarchy_level`
reproduce the server-side mismatch (four failures with the old builder, four
passes here).
Siblings checked:
- superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/buildQuery.ts
— fixed in 80118e754d0f087124087fdfc59ebae3e4e2a8e5
-
superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/controlPanel.tsx —
fixed in 80118e754d0f087124087fdfc59ebae3e4e2a8e5
- superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/timeGrain.ts —
fixed in 80118e754d0f087124087fdfc59ebae3e4e2a8e5
- superset/common/form_data_query_context.py — fixed in
80118e754d0f087124087fdfc59ebae3e4e2a8e5
- superset/mcp_service/chart/chart_helpers.py — not affected: MCP normalizes
dashboard overrides before delegating to the shared builder, covered by the MCP
regression test
- superset/charts/data/api.py — not affected: saved-context GET executes
persisted query_context, rather than recomputing levels from dataset lookup
Final head: `8cc881ab51c29c79d574d7b254933fa7babd3019`.
##########
superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/controlPanel.tsx:
##########
@@ -39,6 +42,36 @@ const config: ControlPanelConfig = {
expanded: true,
controlSetRows: [
['columns'],
+ [
+ {
+ name: 'time_grain_sqla',
+ config: {
+ ...sharedControls.time_grain_sqla,
+ // Keep the saved grain (or none). Unlike the shared control, a
+ // new chart starts without a grain, so temporal levels keep
+ // their raw values until one is chosen.
+ initialValue: (control: ControlState) => control.value,
Review Comment:
Fixed in 80118e754d0f087124087fdfc59ebae3e4e2a8e5 by giving the grain
control a null default while retaining its saved-value initializer. Retained
Time Column subjects also reset when their selected level is removed, without
stashing legacy outside subjects on load
(8cc881ab51c29c79d574d7b254933fa7babd3019).
Regression test: `hiding the Sunburst grain control clears the saved grain`
in `superset-frontend/src/explore/components/Control.test.tsx` renders the
control visible with P1M, hides it, and checks the programmatic reset to null.
It fails with the previous control config and passes here. The existing
no-initial-grain tests still pass.
Additional regression test: `removing an MCP temporal level clears its
hidden Time Column subject` in
`superset-frontend/src/explore/components/Control.test.tsx` fails at
e3492ea8b6b73bb03479637bb7e421c314bcd54b and passes at the final head.
Siblings checked:
-
superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/controlPanel.tsx —
fixed in 80118e754d0f087124087fdfc59ebae3e4e2a8e5
- superset-frontend/src/explore/components/Control.tsx — not affected: its
existing reset-on-hide hook works once default is defined
- superset-frontend/src/explore/controlUtils/getControlState.ts — not
affected: a null default does not inject an initial grain
- superset/mcp_service/chart/sunburst.py — not affected: the temporal-state
validator already accepts a null grain
-
superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx
— not affected: its resetOnHide=false controls intentionally retain values;
the only saved-value grain initializer found by the sibling search is Sunburst's
-
superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/controlPanel.tsx:82
— fixed in 8cc881ab51c29c79d574d7b254933fa7babd3019 (retained-subject reset and
non-stashing)
Final head: `8cc881ab51c29c79d574d7b254933fa7babd3019`.
--
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]