You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ru...@apache.org on 2026/07/05 06:18:13 UTC

(superset) branch master updated: fix(drill-detail): drill to detail by a null value dimension should use NULL_STRING (#41678)

This is an automated email from the ASF dual-hosted git repository.

rusackas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new ea40b87e2fd fix(drill-detail): drill to detail by a null value dimension should use NULL_STRING (#41678)
ea40b87e2fd is described below

commit ea40b87e2fda762e437299bc978cb301146ea50a
Author: Viktor Högberg <11...@users.noreply.github.com>
AuthorDate: Sun Jul 5 08:18:07 2026 +0200

    fix(drill-detail): drill to detail by a null value dimension should use NULL_STRING (#41678)
---
 .../Chart/useDrillDetailMenuItems/index.tsx        | 58 ++++++++++++----------
 .../useDrillDetailMenuItems.test.tsx               | 18 +++++++
 2 files changed, 51 insertions(+), 25 deletions(-)

diff --git a/superset-frontend/src/components/Chart/useDrillDetailMenuItems/index.tsx b/superset-frontend/src/components/Chart/useDrillDetailMenuItems/index.tsx
index 2914dbbd8c7..48aeef24dda 100644
--- a/superset-frontend/src/components/Chart/useDrillDetailMenuItems/index.tsx
+++ b/superset-frontend/src/components/Chart/useDrillDetailMenuItems/index.tsx
@@ -38,6 +38,7 @@ import { css, styled } from '@apache-superset/core/theme';
 import { useSelector } from 'react-redux';
 import { type ItemType } from '@superset-ui/core/components/Menu';
 import { RootState } from 'src/dashboard/types';
+import { NULL_STRING } from 'src/utils/common';
 import { getSubmenuYOffset } from '../utils';
 import { MenuItemTooltip } from '../DisabledMenuItemTooltip';
 import { TruncatedMenuLabel } from '../MenuItemWithTruncation';
@@ -219,33 +220,40 @@ export const useDrillDetailMenuItems = ({
           popupOffset: [0, submenuYOffset],
           popupClassName: 'chart-context-submenu',
           children: [
-            ...filters.map((filter, i) => ({
-              key: `drill-detail-filter-${i}`,
-              onClick: openModal.bind(null, [filter]),
-              label: (
-                <div
-                  css={css`
-                    max-width: 200px;
-                  `}
-                >
-                  <TruncatedMenuLabel
-                    tooltipText={`${DRILL_TO_DETAIL_BY} ${filter.formattedVal}`}
-                    aria-label={`${DRILL_TO_DETAIL_BY} ${filter.formattedVal}`}
+            ...filters.map((filter, i) => {
+              const isNullVal =
+                filter.val === null || filter.formattedVal === NULL_STRING;
+              const formattedVal = isNullVal
+                ? NULL_STRING
+                : filter.formattedVal;
+              return {
+                key: `drill-detail-filter-${i}`,
+                onClick: openModal.bind(null, [filter]),
+                label: (
+                  <div
+                    css={css`
+                      max-width: 200px;
+                    `}
                   >
-                    <span
-                      css={css`
-                        display: inline;
-                      `}
+                    <TruncatedMenuLabel
+                      tooltipText={`${DRILL_TO_DETAIL_BY} ${formattedVal}`}
+                      aria-label={`${DRILL_TO_DETAIL_BY} ${formattedVal}`}
                     >
-                      {DRILL_TO_DETAIL_BY}{' '}
-                      <StyledFilter stripHTML>
-                        {filter.formattedVal}
-                      </StyledFilter>
-                    </span>
-                  </TruncatedMenuLabel>
-                </div>
-              ),
-            })),
+                      <span
+                        css={css`
+                          display: inline;
+                        `}
+                      >
+                        {DRILL_TO_DETAIL_BY}{' '}
+                        <StyledFilter stripHTML={!isNullVal}>
+                          {formattedVal}
+                        </StyledFilter>
+                      </span>
+                    </TruncatedMenuLabel>
+                  </div>
+                ),
+              };
+            }),
             ...(filters.length > 1
               ? [
                   {
diff --git a/superset-frontend/src/components/Chart/useDrillDetailMenuItems/useDrillDetailMenuItems.test.tsx b/superset-frontend/src/components/Chart/useDrillDetailMenuItems/useDrillDetailMenuItems.test.tsx
index 9d601f90734..0e7e2a7c5df 100644
--- a/superset-frontend/src/components/Chart/useDrillDetailMenuItems/useDrillDetailMenuItems.test.tsx
+++ b/superset-frontend/src/components/Chart/useDrillDetailMenuItems/useDrillDetailMenuItems.test.tsx
@@ -74,6 +74,13 @@ const filterB: BinaryQueryObjectFilterClause = {
   formattedVal: 'Two days ago',
 };
 
+const filterNull: BinaryQueryObjectFilterClause = {
+  col: 'sample_column_3',
+  op: '==',
+  val: null as unknown as string,
+  formattedVal: '<NULL>',
+};
+
 const MockRenderChart = ({
   chartId,
   formData,
@@ -426,3 +433,14 @@ test.skip('context menu for supported chart, dimensions, all filters', async ()
   await setupMenu(filters);
   await expectDrillToDetailByAll(filters);
 });
+
+test('context menu renders <NULL> for null dimension values', async () => {
+  renderMenu({
+    formData: defaultFormData,
+    isContextMenu: true,
+    filters: [filterNull],
+  });
+
+  await expectDrillToDetailByEnabled();
+  await expectDrillToDetailByDimension(filterNull);
+});