diff --git a/frontend/src/container/QueryTable/contextConfig.tsx b/frontend/src/container/QueryTable/contextConfig.tsx index 946f06ea9552..4b58b9504871 100644 --- a/frontend/src/container/QueryTable/contextConfig.tsx +++ b/frontend/src/container/QueryTable/contextConfig.tsx @@ -8,11 +8,8 @@ import { IBuilderQuery, Query } from 'types/api/queryBuilder/queryBuilderData'; import { getAggregateColumnHeader } from './drilldownUtils'; import { AGGREGATE_OPTIONS, SUPPORTED_OPERATORS } from './menuOptions'; -import { - getBreakoutQuery, - getFiltersToAdd, - getQueryData, -} from './tableDrilldownUtils'; +import { getBreakoutQuery, getQueryData } from './tableDrilldownUtils'; +import { AggregateData } from './useAggregateDrilldown'; export type ContextMenuItem = ReactNode; @@ -45,7 +42,7 @@ export interface BreakoutOptionsProps { onColumnClick: (groupBy: BaseAutocompleteData) => void; } -function getGroupContextMenuConfig({ +export function getGroupContextMenuConfig({ query, clickedData, panelType, @@ -88,26 +85,32 @@ function getGroupContextMenuConfig({ return {}; } -function getAggregateContextMenuConfig({ +export function getAggregateContextMenuConfig({ subMenu, query, - clickedData, onColumnClick, -}: Omit): AggregateContextMenuConfig { - console.log('getAggregateContextMenuConfig', { clickedData, query }); + aggregateData, +}: { + subMenu?: string; + query: Query; + onColumnClick: (key: string, query?: Query) => void; + aggregateData: AggregateData | null; +}): AggregateContextMenuConfig { + console.log('getAggregateContextMenuConfig', { query, aggregateData }); if (subMenu === 'breakout') { - const queryData = getQueryData(query, clickedData); + const queryData = getQueryData(query, aggregateData); return { header: 'Breakout by', items: ( { - const filtersToAdd = getFiltersToAdd(query, clickedData); + // Use aggregateData.filters + const filtersToAdd = aggregateData?.filters || []; const breakoutQuery = getBreakoutQuery( query, - clickedData, + aggregateData, groupBy, filtersToAdd, ); @@ -118,11 +121,16 @@ function getAggregateContextMenuConfig({ }; } + // Use aggregateData.queryName + const queryName = aggregateData?.queryName; const { dataSource, aggregations } = getAggregateColumnHeader( query, - clickedData?.column?.dataIndex as string, + queryName as string, ); + console.log('dataSource', dataSource); + console.log('aggregations', aggregations); + return { header: (
@@ -141,36 +149,3 @@ function getAggregateContextMenuConfig({ )), }; } - -export function getContextMenuConfig({ - subMenu, - configType, - query, - clickedData, - panelType, - onColumnClick, -}: ContextMenuConfigParams): { - header?: string | ReactNode; - items?: ContextMenuItem; -} { - if (configType === ConfigType.GROUP) { - return getGroupContextMenuConfig({ - query, - clickedData, - panelType, - onColumnClick, - }); - } - - if (configType === ConfigType.AGGREGATE) { - return getAggregateContextMenuConfig({ - subMenu, - query, - clickedData, - panelType, - onColumnClick, - }); - } - - return {}; -} diff --git a/frontend/src/container/QueryTable/drilldownUtils.tsx b/frontend/src/container/QueryTable/drilldownUtils.tsx index 73d0deddd2e4..ab1c78c3c440 100644 --- a/frontend/src/container/QueryTable/drilldownUtils.tsx +++ b/frontend/src/container/QueryTable/drilldownUtils.tsx @@ -122,7 +122,8 @@ export const getAggregateColumnHeader = ( return { dataSource: '', aggregations: '' }; } - const { dataSource, aggregations } = queryStep; + console.log('queryStep', queryStep); + const { dataSource, aggregations } = queryStep; // TODO: check if this is correct // Extract aggregation expressions based on data source type let aggregationExpressions: string[] = []; diff --git a/frontend/src/container/QueryTable/tableDrilldownUtils.tsx b/frontend/src/container/QueryTable/tableDrilldownUtils.tsx index 66d20521de65..0e30a1f28254 100644 --- a/frontend/src/container/QueryTable/tableDrilldownUtils.tsx +++ b/frontend/src/container/QueryTable/tableDrilldownUtils.tsx @@ -13,43 +13,25 @@ import { IBuilderQuery, Query } from 'types/api/queryBuilder/queryBuilderData'; import { v4 as uuid } from 'uuid'; import { getBaseMeta } from './drilldownUtils'; +import { AggregateData } from './useAggregateDrilldown'; /** - * Gets the query data that matches the clicked column's dataIndex + * Gets the query data that matches the aggregate data's queryName */ -export const getQueryData = (query: Query, clickedData: any): IBuilderQuery => { - if (!clickedData) { - console.warn('clickedData is null in getQueryData'); +export const getQueryData = ( + query: Query, + aggregateData: AggregateData | null, +): IBuilderQuery => { + if (!aggregateData) { + console.warn('aggregateData is null in getQueryData'); return initialQueryBuilderFormValuesMap.logs; } const queryData = query?.builder?.queryData?.filter( - (item: IBuilderQuery) => item.queryName === clickedData.column.dataIndex, + (item: IBuilderQuery) => item.queryName === aggregateData.queryName, ); return queryData[0]; }; -/** - * Creates filters to add to the query from columns which are part of the query.builder.queryData[].groupBy - */ -export const getFiltersToAdd = ( - query: Query, - clickedData: any, -): FilterData[] => { - if (!clickedData) { - console.warn('clickedData is null in getFiltersToAdd'); - return []; - } - - const queryData = getQueryData(query, clickedData); - const { groupBy } = queryData; - - return groupBy.map((item: BaseAutocompleteData) => ({ - filterKey: item.key, - filterValue: clickedData.record[item.key], - operator: OPERATORS['='], - })); -}; - export const isEmptyFilterValue = (value: any): boolean => value === '' || value === null || value === undefined || value === 'n/a'; @@ -138,29 +120,29 @@ export const getViewQuery = ( */ export const getBreakoutQuery = ( query: Query, - clickedData: any, + aggregateData: AggregateData | null, groupBy: BaseAutocompleteData, filtersToAdd: FilterData[], ): Query => { - if (!clickedData) { - console.warn('clickedData is null in getBreakoutQuery'); + if (!aggregateData) { + console.warn('aggregateData is null in getBreakoutQuery'); return query; } console.log('>> groupBy', groupBy); - console.log('>> clickedData', clickedData); + console.log('>> aggregateData', aggregateData); console.log('>> query', query); const queryWithFilters = addFilterToSelectedQuery( query, filtersToAdd, - clickedData.column.dataIndex, + aggregateData.queryName, ); const newQuery = cloneDeep(queryWithFilters); newQuery.builder.queryData = newQuery.builder.queryData.map( (item: IBuilderQuery) => { - if (item.queryName === clickedData.column.dataIndex) { + if (item.queryName === aggregateData.queryName) { return { ...item, groupBy: [groupBy], diff --git a/frontend/src/container/QueryTable/useAggregateDrilldown.tsx b/frontend/src/container/QueryTable/useAggregateDrilldown.tsx index b63071db93c6..ffd194ee9682 100644 --- a/frontend/src/container/QueryTable/useAggregateDrilldown.tsx +++ b/frontend/src/container/QueryTable/useAggregateDrilldown.tsx @@ -1,22 +1,24 @@ import { QueryParams } from 'constants/query'; import ROUTES from 'constants/routes'; -import { - getFiltersToAddToView, - getViewQuery, -} from 'container/QueryTable/tableDrilldownUtils'; +import { FilterData } from 'container/QueryTable/drilldownUtils'; +import { getViewQuery } from 'container/QueryTable/tableDrilldownUtils'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import { useSafeNavigate } from 'hooks/useSafeNavigate'; import createQueryParams from 'lib/createQueryParams'; -import { ClickedData } from 'periscope/components/ContextMenu/types'; import { useCallback, useMemo } from 'react'; import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { - ConfigType, ContextMenuItem, - getContextMenuConfig, + getAggregateContextMenuConfig, } from './contextConfig'; +// Type for aggregate data +export interface AggregateData { + queryName: string; + filters: FilterData[]; +} + const getRoute = (key: string): string => { switch (key) { case 'view_logs': @@ -33,17 +35,17 @@ const getRoute = (key: string): string => { const useAggregateDrilldown = ({ query, widgetId, - clickedData, onClose, subMenu, setSubMenu, + aggregateData, }: { query: Query; widgetId: string; - clickedData: ClickedData | null; onClose: () => void; subMenu: string; setSubMenu: (subMenu: string) => void; + aggregateData: AggregateData | null; }): { aggregateDrilldownConfig: { header?: string | React.ReactNode; @@ -56,7 +58,7 @@ const useAggregateDrilldown = ({ (query: Query): void => { redirectWithQueryBuilderData( query, - { [QueryParams.expandedWidgetId]: widgetId }, + { [QueryParams.expandedWidgetId]: widgetId }, // add only if view mode undefined, true, ); @@ -67,7 +69,7 @@ const useAggregateDrilldown = ({ const handleAggregateDrilldown = useCallback( (key: string, drilldownQuery?: Query): void => { - console.log('Aggregate drilldown:', { clickedData, widgetId, query, key }); + console.log('Aggregate drilldown:', { widgetId, query, key, aggregateData }); if (key === 'breakout') { if (!drilldownQuery) { @@ -80,7 +82,7 @@ const useAggregateDrilldown = ({ } const route = getRoute(key); - const filtersToAdd = clickedData ? getFiltersToAddToView(clickedData) : []; + const filtersToAdd = aggregateData?.filters || []; const viewQuery = getViewQuery(query, filtersToAdd, key); let queryParams = { @@ -105,30 +107,28 @@ const useAggregateDrilldown = ({ onClose(); }, [ - clickedData, query, widgetId, safeNavigate, onClose, redirectToViewMode, setSubMenu, + aggregateData, ], ); const aggregateDrilldownConfig = useMemo(() => { - if (!clickedData) { - console.warn('clickedData is null in aggregateDrilldownConfig'); + if (!aggregateData) { + console.warn('aggregateData is null in aggregateDrilldownConfig'); return {}; } - return getContextMenuConfig({ + return getAggregateContextMenuConfig({ subMenu, - configType: ConfigType.AGGREGATE, query, - clickedData, - panelType: 'table', onColumnClick: handleAggregateDrilldown, + aggregateData, }); - }, [handleAggregateDrilldown, clickedData, query, subMenu]); + }, [handleAggregateDrilldown, query, subMenu, aggregateData]); return { aggregateDrilldownConfig }; }; diff --git a/frontend/src/container/QueryTable/useFilterDrilldown.tsx b/frontend/src/container/QueryTable/useFilterDrilldown.tsx index 678de5cfd755..62be55441832 100644 --- a/frontend/src/container/QueryTable/useFilterDrilldown.tsx +++ b/frontend/src/container/QueryTable/useFilterDrilldown.tsx @@ -2,9 +2,11 @@ import { QueryParams } from 'constants/query'; import { addFilterToQuery } from 'container/QueryTable/drilldownUtils'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import { ClickedData } from 'periscope/components/ContextMenu/types'; -import { useCallback } from 'react'; +import { useCallback, useMemo } from 'react'; import { Query } from 'types/api/queryBuilder/queryBuilderData'; +import { getGroupContextMenuConfig } from './contextConfig'; + const useFilterDrilldown = ({ query, widgetId, @@ -15,7 +17,12 @@ const useFilterDrilldown = ({ widgetId: string; clickedData: ClickedData | null; onClose: () => void; -}): { handleFilterDrilldown: (operator: string) => void } => { +}): { + filterDrilldownConfig: { + header?: string | React.ReactNode; + items?: React.ReactNode; + }; +} => { const { redirectWithQueryBuilderData } = useQueryBuilder(); const redirectToViewMode = useCallback( @@ -47,8 +54,21 @@ const useFilterDrilldown = ({ [onClose, clickedData, query, redirectToViewMode], ); + const filterDrilldownConfig = useMemo(() => { + if (!clickedData) { + console.warn('clickedData is null in filterDrilldownConfig'); + return {}; + } + return getGroupContextMenuConfig({ + query, + clickedData, + panelType: 'table', + onColumnClick: handleFilterDrilldown, + }); + }, [handleFilterDrilldown, clickedData, query]); + return { - handleFilterDrilldown, + filterDrilldownConfig, }; }; diff --git a/frontend/src/container/QueryTable/useTableContextMenu.tsx b/frontend/src/container/QueryTable/useTableContextMenu.tsx index 8aaddb67ae93..17497b390da2 100644 --- a/frontend/src/container/QueryTable/useTableContextMenu.tsx +++ b/frontend/src/container/QueryTable/useTableContextMenu.tsx @@ -1,7 +1,5 @@ -import { - ConfigType, - getContextMenuConfig, -} from 'container/QueryTable/contextConfig'; +import { ConfigType } from 'container/QueryTable/contextConfig'; +import { getFiltersToAddToView } from 'container/QueryTable/tableDrilldownUtils'; import useAggregateDrilldown from 'container/QueryTable/useAggregateDrilldown'; import useFilterDrilldown from 'container/QueryTable/useFilterDrilldown'; import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam'; @@ -34,34 +32,29 @@ export function useTableContextMenu({ }; } { const drilldownQuery = useGetCompositeQueryParam() || query; - const { handleFilterDrilldown } = useFilterDrilldown({ + const { filterDrilldownConfig } = useFilterDrilldown({ query: drilldownQuery, widgetId, clickedData, onClose, }); - const filterDrilldownConfig = useMemo(() => { - if (!clickedData) { - console.warn('clickedData is null in filterDrilldownConfig'); - return {}; - } - return getContextMenuConfig({ - configType: ConfigType.GROUP, - query, - clickedData, - panelType: 'table', - onColumnClick: handleFilterDrilldown, - }); - }, [handleFilterDrilldown, clickedData, query]); + const aggregateData = useMemo(() => { + if (!clickedData?.column?.isValueColumn) return null; + + return { + queryName: String(clickedData.column.dataIndex || ''), + filters: getFiltersToAddToView(clickedData) || [], + }; + }, [clickedData]); const { aggregateDrilldownConfig } = useAggregateDrilldown({ query: drilldownQuery, widgetId, - clickedData, onClose, subMenu, setSubMenu, + aggregateData, }); const menuItemsConfig = useMemo(() => {