From 0c2553b1106c462b39ff29538730cf44949d452c Mon Sep 17 00:00:00 2001 From: SagarRajput-7 Date: Wed, 14 May 2025 04:54:33 +0530 Subject: [PATCH] feat: added ability to add/remove variable filter to one or more existing panels --- .../useAddDynamicVariableToPanels.tsx | 57 ++++++++++++ .../dashboard/useAddTagFiltersToDashboard.tsx | 88 +++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 frontend/src/hooks/dashboard/useAddDynamicVariableToPanels.tsx create mode 100644 frontend/src/hooks/dashboard/useAddTagFiltersToDashboard.tsx diff --git a/frontend/src/hooks/dashboard/useAddDynamicVariableToPanels.tsx b/frontend/src/hooks/dashboard/useAddDynamicVariableToPanels.tsx new file mode 100644 index 000000000000..9092bfe312a4 --- /dev/null +++ b/frontend/src/hooks/dashboard/useAddDynamicVariableToPanels.tsx @@ -0,0 +1,57 @@ +import { useMemo } from 'react'; +import { Dashboard } from 'types/api/dashboard/getAll'; +import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; +import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData'; +import { v4 as uuid } from 'uuid'; + +import { useAddTagFiltersToDashboard } from './useAddTagFiltersToDashboard'; + +interface DynamicVariableConfig { + variableName: string; + tagKey: { + key: string; + dataType: string; + isColumn: boolean; + isJSON?: boolean; + type: string; + }; + operator: string; +} + +/** + * A hook that adds dynamic variables to dashboard panels as tag filters + * + * @param dashboard The dashboard configuration + * @param variableConfig Configuration for the dynamic variable to add + * @param widgetIds Optional array of widget IDs to target specific widgets + * @returns Updated dashboard with dynamic variables added as filters + */ +export const useAddDynamicVariableToPanels = ( + dashboard: Dashboard | undefined, + variableConfig: DynamicVariableConfig, + widgetIds?: string[], +): Dashboard | undefined => { + // Create the tag filter based on the variable configuration + const tagFilters = useMemo((): TagFilterItem[] => { + if (!variableConfig) { + return []; + } + + const { variableName, tagKey, operator } = variableConfig; + + // Create a TagFilterItem that uses the variable as the value + const filter: TagFilterItem = { + id: uuid().slice(0, 8), + key: tagKey as BaseAutocompleteData, + op: operator, + value: `$${variableName}`, + }; + + return [filter]; + }, [variableConfig]); + + // Use the existing hook to add these filters to the dashboard + return useAddTagFiltersToDashboard(dashboard, tagFilters, widgetIds); +}; + +export default useAddDynamicVariableToPanels; diff --git a/frontend/src/hooks/dashboard/useAddTagFiltersToDashboard.tsx b/frontend/src/hooks/dashboard/useAddTagFiltersToDashboard.tsx new file mode 100644 index 000000000000..07e9d07cddbf --- /dev/null +++ b/frontend/src/hooks/dashboard/useAddTagFiltersToDashboard.tsx @@ -0,0 +1,88 @@ +import { cloneDeep } from 'lodash-es'; +import { useMemo } from 'react'; +import { Dashboard, Widgets } from 'types/api/dashboard/getAll'; +import { + IBuilderQuery, + TagFilterItem, +} from 'types/api/queryBuilder/queryBuilderData'; + +/** + * Updates the query filters in a builder query by appending new tag filters + */ +const updateQueryFilters = ( + queryData: IBuilderQuery, + filters: TagFilterItem[], +): IBuilderQuery => ({ + ...queryData, + filters: { + ...queryData.filters, + items: [...queryData.filters.items, ...filters], + }, +}); + +/** + * Updates a single widget by adding filters to its query + */ +const updateSingleWidget = ( + widget: Widgets, + filters: TagFilterItem[], +): Widgets => { + if (!widget.query?.builder?.queryData) { + return widget; + } + + return { + ...widget, + query: { + ...widget.query, + builder: { + ...widget.query.builder, + queryData: widget.query.builder.queryData.map((queryData) => + updateQueryFilters(queryData, filters), + ), + }, + }, + }; +}; + +/** + * A hook that takes a dashboard configuration and a list of tag filters + * and returns an updated dashboard with the filters appended to widget queries. + * + * @param dashboard The dashboard configuration + * @param filters Array of tag filters to apply to widgets + * @param widgetIds Optional array of widget IDs to filter which widgets get updated + * @returns Updated dashboard configuration with filters applied + */ +export const useAddTagFiltersToDashboard = ( + dashboard: Dashboard | undefined, + filters: TagFilterItem[], + widgetIds?: string[], +): Dashboard | undefined => + useMemo(() => { + if (!dashboard || !filters.length) { + return dashboard; + } + + // Create a deep copy to avoid mutating the original dashboard + const updatedDashboard = cloneDeep(dashboard); + + // Process each widget to add filters + if (updatedDashboard.data.widgets) { + updatedDashboard.data.widgets = updatedDashboard.data.widgets.map( + (widget) => { + // Only apply to widgets with 'query' property + if ('query' in widget) { + // If widgetIds is provided, only update widgets with matching IDs + if (widgetIds && !widgetIds.includes(widget.id)) { + return widget; + } + return updateSingleWidget(widget as Widgets, filters); + } + return widget; + }, + ); + } + + return updatedDashboard; + }, [dashboard, filters, widgetIds]);