dosubot[bot] commented on issue #28562:
URL: https://github.com/apache/superset/issues/28562#issuecomment-2122001584

   <!-- Answer -->
   To resolve the issue where the "Drill to details by" feature in Apache 
Superset version 4.0.1 ignores applied filters, ensure that filters are 
correctly passed and applied both in the frontend and backend.
   
   ### Frontend Changes
   
   1. **Pass Filters to `DrillDetailMenuItems` Component:**
      Ensure the `filters` object contains the correct filter values and is 
passed to the `DrillDetailMenuItems` component.
   
      ```tsx
      if (showDrillToDetail) {
          menuItems.push(
            <DrillDetailMenuItems
              chartId={id}
              formData={formData}
              filters={filters?.drillToDetail}
              isContextMenu
              contextMenuY={clientY}
              onSelection={onSelection}
              submenuIndex={showCrossFilters ? 2 : 1}
              showModal={drillModalIsOpen}
              setShowModal={setDrillModalIsOpen}
              {...(additionalConfig?.drillToDetail || {})}
            />,
          );
        }
      ```
   
   2. **Verify `handleContextMenu` Function:**
      Ensure the `handleContextMenu` function constructs the 
`drillToDetailFilters` based on the selected filters.
   
      ```tsx
      const handleContextMenu = useCallback(
          (
            e: MouseEvent,
            colKey: (string | number | boolean)[] | undefined,
            rowKey: (string | number | boolean)[] | undefined,
            dataPoint: { [key: string]: string },
          ) => {
            if (onContextMenu) {
              e.preventDefault();
              e.stopPropagation();
              const drillToDetailFilters: BinaryQueryObjectFilterClause[] = [];
              if (colKey && colKey.length > 1) {
                colKey.forEach((val, i) => {
                  const col = cols[i];
                  const formatter = dateFormatters[col];
                  const formattedVal = formatter?.(val as number) || 
String(val);
                  if (i > 0) {
                    drillToDetailFilters.push({
                      col,
                      op: '==',
                      val,
                      formattedVal,
                      grain: formatter ? timeGrainSqla : undefined,
                    });
                  }
                });
              }
              if (rowKey) {
                rowKey.forEach((val, i) => {
                  const col = rows[i];
                  const formatter = dateFormatters[col];
                  const formattedVal = formatter?.(val as number) || 
String(val);
                  drillToDetailFilters.push({
                    col,
                    op: '==',
                    val,
                    formattedVal,
                    grain: formatter ? timeGrainSqla : undefined,
                  });
                });
              }
              onContextMenu(e.clientX, e.clientY, {
                drillToDetail: drillToDetailFilters,
                crossFilter: getCrossFilterDataMask(dataPoint),
                drillBy: dataPoint && {
                  filters: [
                    {
                      col: Object.keys(dataPoint)[0],
                      op: '==',
                      val: Object.values(dataPoint)[0],
                    },
                  ],
                  groupbyFieldName: rowKey ? 'groupbyRows' : 'groupbyColumns',
                },
              });
            }
          },
          [
            cols,
            dateFormatters,
            getCrossFilterDataMask,
            onContextMenu,
            rows,
            timeGrainSqla,
          ],
        );
      ```
   
   ### Backend Changes
   
   1. **Apply Filters in `_get_drill_detail` Function:**
      Ensure the `_get_drill_detail` function in 
`superset/common/query_actions.py` correctly applies the filters to the query 
object.
   
      ```py
      def _get_drill_detail(
          query_context: QueryContext, query_obj: QueryObject, force_cached: 
bool = False
      ) -> dict[str, Any]:
          datasource = _get_datasource(query_context, query_obj)
          query_obj = copy.copy(query_obj)
          query_obj.is_timeseries = False
          query_obj.orderby = []
          query_obj.metrics = None
          query_obj.post_processing = []
          qry_obj_cols = []
          for o in datasource.columns:
              if isinstance(o, dict):
                  qry_obj_cols.append(o.get("column_name"))
              else:
                  qry_obj_cols.append(o.column_name)
          query_obj.columns = qry_obj_cols
          return _get_full(query_context, query_obj, force_cached)
      ```
   
   2. **Check `QueryContext` Object:**
      Ensure the `QueryContext` object handles filters correctly when 
generating SQL queries for drill-down details.
   
      ```python
      def _apply_filters(self, query_object: QueryObject) -> None:
          if query_object.time_range:
              for filter_object in query_object.filter:
                  if filter_object["op"] == "TEMPORAL_RANGE":
                      filter_object["val"] = query_object.time_range
      ```
   
   3. **Verify `buildQuery` Function:**
      Ensure the `buildQuery` function in 
`superset-frontend/src/filters/components/Select/buildQuery.ts` correctly adds 
extra filters based on user input.
   
      ```ts
      const buildQuery: BuildQuery<PluginFilterSelectQueryFormData> = (
        formData: PluginFilterSelectQueryFormData,
        options,
      ) => {
        const { search, coltypeMap } = options?.ownState || {};
        const { sortAscending, sortMetric } = { ...DEFAULT_FORM_DATA, 
...formData };
        return buildQueryContext(formData, baseQueryObject => {
          const { columns = [], filters = [] } = baseQueryObject;
          const extraFilters: QueryObjectFilterClause[] = [];
          if (search) {
            columns.filter(isPhysicalColumn).forEach(column => {
              const label = getColumnLabel(column);
              if (
                coltypeMap[label] === GenericDataType.String ||
                (coltypeMap[label] === GenericDataType.Numeric &&
                  !Number.isNaN(Number(search)))
              ) {
                extraFilters.push({
                  col: column,
                  op: 'ILIKE',
                  val: `%${search}%`,
                });
              }
            });
          }
          const sortColumns = sortMetric ? [sortMetric] : columns;
          const query: QueryObject[] = [
            {
              ...baseQueryObject,
              columns,
              metrics: sortMetric ? [sortMetric] : [],
              filters: filters.concat(extraFilters),
              orderby:
                sortMetric || sortAscending !== undefined
                  ? sortColumns.map(column => [column, !!sortAscending])
                  : [],
            },
          ];
          return query;
        });
      };
      ```
   
   By ensuring that filters are correctly passed and applied at each step, you 
should be able to resolve the issue where the "Drill to details by" feature 
ignores the applied filters.
   
   
   <!-- Dosu Comment Footer -->
   <details>
   <summary>
   
   #### Details
   </summary>
   
   **Sources**
   - [Drill by function error with caching 
enabled](https://github.com/apache/superset/issues/26471)
   - 
[superset-frontend/src/components/Chart/ChartContextMenu/ChartContextMenu.tsx](https://github.com/apache/superset/blob/master/superset-frontend/src/components/Chart/ChartContextMenu/ChartContextMenu.tsx)
   - 
[superset-frontend/plugins/plugin-chart-pivot-table/src/PivotTableChart.tsx](https://github.com/apache/superset/blob/master/superset-frontend/plugins/plugin-chart-pivot-table/src/PivotTableChart.tsx)
   - 
[superset/common/query_actions.py](https://github.com/apache/superset/blob/master/superset/common/query_actions.py)
   - 
[superset-frontend/src/components/Chart/DrillDetail/DrillDetailMenuItems.tsx](https://github.com/apache/superset/blob/master/superset-frontend/src/components/Chart/DrillDetail/DrillDetailMenuItems.tsx)
   - 
[superset-frontend/src/components/Chart/DrillDetail/DrillDetailMenuItems.test.tsx](https://github.com/apache/superset/blob/master/superset-frontend/src/components/Chart/DrillDetail/DrillDetailMenuItems.test.tsx)
   - 
[superset/common/query_context_factory.py](https://github.com/apache/superset/blob/master/superset/common/query_context_factory.py)
   - 
[superset/common/query_context.py](https://github.com/apache/superset/blob/master/superset/common/query_context.py)
   - 
[superset-frontend/src/filters/components/Select/buildQuery.ts](https://github.com/apache/superset/blob/master/superset-frontend/src/filters/components/Select/buildQuery.ts)
   - 
[tests/integration_tests/query_context_tests.py](https://github.com/apache/superset/blob/master/tests/integration_tests/query_context_tests.py)
   - 
[superset-frontend/src/filters/components/TimeColumn/buildQuery.ts](https://github.com/apache/superset/blob/master/superset-frontend/src/filters/components/TimeColumn/buildQuery.ts)
   - 
[superset-frontend/cypress-base/cypress/e2e/dashboard/drilltodetail.test.ts](https://github.com/apache/superset/blob/master/superset-frontend/cypress-base/cypress/e2e/dashboard/drilltodetail.test.ts)
   - 
[superset-frontend/cypress-base/cypress/e2e/dashboard/drillby.test.ts](https://github.com/apache/superset/blob/master/superset-frontend/cypress-base/cypress/e2e/dashboard/drillby.test.ts)
   - 
[superset/common/query_context_processor.py](https://github.com/apache/superset/blob/master/superset/common/query_context_processor.py)
   
   <br/>
   
   **About Dosu**
   This response is meant to be useful and save you time. It is **not meant to 
be a precise solution**, but rather a starting point for your own research.
   
   Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is 
irrelevant.
   </details>
   
   *To continue the conversation, mention @dosu.*
   


-- 
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: notifications-unsubscr...@superset.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@superset.apache.org
For additional commands, e-mail: notifications-h...@superset.apache.org

Reply via email to