feat: added widgetselector on variable creation

This commit is contained in:
SagarRajput-7 2025-08-11 08:21:33 +05:30
parent 0c2553b110
commit d6088f97e7
6 changed files with 127 additions and 75 deletions

View File

@ -42,6 +42,7 @@ import { variablePropsToPayloadVariables } from '../../../utils';
import { TVariableMode } from '../types'; import { TVariableMode } from '../types';
import DynamicVariable from './DynamicVariable/DynamicVariable'; import DynamicVariable from './DynamicVariable/DynamicVariable';
import { LabelContainer, VariableItemRow } from './styles'; import { LabelContainer, VariableItemRow } from './styles';
import { WidgetSelector } from './WidgetSelector';
const { Option } = Select; const { Option } = Select;
@ -139,6 +140,14 @@ function VariableItem({
endUnixMilli: maxTime, endUnixMilli: maxTime,
}); });
const [selectedWidgets, setSelectedWidgets] = useState<string[]>([]);
useEffect(() => {
if (queryType === 'DYNAMIC') {
setSelectedWidgets(variableData?.dynamicVariablesWidgetIds || []);
}
}, [queryType, variableData?.dynamicVariablesWidgetIds]);
useEffect(() => { useEffect(() => {
if (queryType === 'CUSTOM') { if (queryType === 'CUSTOM') {
setPreviewValues( setPreviewValues(
@ -208,6 +217,10 @@ function VariableItem({
dynamicVariablesAttribute: dynamicVariablesSelectedValue?.name, dynamicVariablesAttribute: dynamicVariablesSelectedValue?.name,
dynamicVariablesSource: dynamicVariablesSelectedValue?.value, dynamicVariablesSource: dynamicVariablesSelectedValue?.value,
}), }),
...(queryType === 'DYNAMIC' && {
dynamicVariablesWidgetIds:
selectedWidgets?.length > 0 ? selectedWidgets : [],
}),
}; };
const allVariables = [...Object.values(existingVariables), newVariable]; const allVariables = [...Object.values(existingVariables), newVariable];
@ -582,6 +595,19 @@ function VariableItem({
</VariableItemRow> </VariableItemRow>
</> </>
)} )}
{queryType === 'DYNAMIC' && (
<VariableItemRow className="dynamic-variable-section">
<LabelContainer>
<Typography className="typography-variables">
Select Widgets to apply
</Typography>
</LabelContainer>
<WidgetSelector
selectedWidgets={selectedWidgets}
setSelectedWidgets={setSelectedWidgets}
/>
</VariableItemRow>
)}
</div> </div>
</div> </div>
<div className="variable-item-footer"> <div className="variable-item-footer">

View File

@ -0,0 +1,28 @@
import { CustomMultiSelect } from 'components/NewSelect';
import { generateGridTitle } from 'container/GridPanelSwitch/utils';
import { useDashboard } from 'providers/Dashboard/Dashboard';
export function WidgetSelector({
selectedWidgets,
setSelectedWidgets,
}: {
selectedWidgets: string[];
setSelectedWidgets: (widgets: string[]) => void;
}): JSX.Element {
const { selectedDashboard } = useDashboard();
const widgets = selectedDashboard?.data?.widgets || [];
return (
<CustomMultiSelect
placeholder="Select Widgets"
options={widgets.map((widget) => ({
label: generateGridTitle(widget.title),
value: widget.id,
}))}
value={selectedWidgets}
labelInValue
onChange={(value): void => setSelectedWidgets(value as string[])}
/>
);
}

View File

@ -1,5 +1,4 @@
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
import { useMemo } from 'react';
import { Dashboard, Widgets } from 'types/api/dashboard/getAll'; import { Dashboard, Widgets } from 'types/api/dashboard/getAll';
import { import {
IBuilderQuery, IBuilderQuery,
@ -16,7 +15,8 @@ const updateQueryFilters = (
...queryData, ...queryData,
filters: { filters: {
...queryData.filters, ...queryData.filters,
items: [...queryData.filters.items, ...filters], items: [...(queryData.filters?.items || []), ...filters],
op: queryData.filters?.op || 'AND',
}, },
}); });
@ -46,7 +46,7 @@ const updateSingleWidget = (
}; };
/** /**
* A hook that takes a dashboard configuration and a list of tag filters * A function that takes a dashboard configuration and a list of tag filters
* and returns an updated dashboard with the filters appended to widget queries. * and returns an updated dashboard with the filters appended to widget queries.
* *
* @param dashboard The dashboard configuration * @param dashboard The dashboard configuration
@ -54,35 +54,34 @@ const updateSingleWidget = (
* @param widgetIds Optional array of widget IDs to filter which widgets get updated * @param widgetIds Optional array of widget IDs to filter which widgets get updated
* @returns Updated dashboard configuration with filters applied * @returns Updated dashboard configuration with filters applied
*/ */
export const useAddTagFiltersToDashboard = ( export const addTagFiltersToDashboard = (
dashboard: Dashboard | undefined, dashboard: Dashboard | undefined,
filters: TagFilterItem[], filters: TagFilterItem[],
widgetIds?: string[], widgetIds?: string[],
): Dashboard | undefined => ): Dashboard | undefined => {
useMemo(() => { if (!dashboard || !filters.length) {
if (!dashboard || !filters.length) { return dashboard;
return dashboard; }
}
// Create a deep copy to avoid mutating the original dashboard // Create a deep copy to avoid mutating the original dashboard
const updatedDashboard = cloneDeep(dashboard); const updatedDashboard = cloneDeep(dashboard);
// Process each widget to add filters // Process each widget to add filters
if (updatedDashboard.data.widgets) { if (updatedDashboard.data.widgets) {
updatedDashboard.data.widgets = updatedDashboard.data.widgets.map( updatedDashboard.data.widgets = updatedDashboard.data.widgets.map(
(widget) => { (widget) => {
// Only apply to widgets with 'query' property // Only apply to widgets with 'query' property
if ('query' in widget) { if ('query' in widget) {
// If widgetIds is provided, only update widgets with matching IDs // If widgetIds is provided, only update widgets with matching IDs
if (widgetIds && !widgetIds.includes(widget.id)) { if (widgetIds && !widgetIds.includes(widget.id)) {
return widget; return widget;
}
return updateSingleWidget(widget as Widgets, filters);
} }
return widget; return updateSingleWidget(widget as Widgets, filters);
}, }
); return widget;
} },
);
}
return updatedDashboard; return updatedDashboard;
}, [dashboard, filters, widgetIds]); };

View File

@ -15,6 +15,7 @@ import { CSS } from '@dnd-kit/utilities';
import { Button, Modal, Row, Space, Table, Typography } from 'antd'; import { Button, Modal, Row, Space, Table, Typography } from 'antd';
import { RowProps } from 'antd/lib'; import { RowProps } from 'antd/lib';
import { convertVariablesToDbFormat } from 'container/NewDashboard/DashboardVariablesSelection/util'; import { convertVariablesToDbFormat } from 'container/NewDashboard/DashboardVariablesSelection/util';
import { useAddDynamicVariableToPanels } from 'hooks/dashboard/useAddDynamicVariableToPanels';
import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard'; import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import { PenLine, Trash2 } from 'lucide-react'; import { PenLine, Trash2 } from 'lucide-react';
@ -162,19 +163,30 @@ function VariablesSetting({
setExistingVariableNamesMap(variableNamesMap); setExistingVariableNamesMap(variableNamesMap);
}, [variables]); }, [variables]);
const addDynamicVariableToPanels = useAddDynamicVariableToPanels();
const updateVariables = ( const updateVariables = (
updatedVariablesData: Dashboard['data']['variables'], updatedVariablesData: Dashboard['data']['variables'],
currentRequestedId?: string,
): void => { ): void => {
if (!selectedDashboard) { if (!selectedDashboard) {
return; return;
} }
const newDashboard =
(currentRequestedId &&
addDynamicVariableToPanels(
selectedDashboard,
updatedVariablesData[currentRequestedId || ''],
)) ||
selectedDashboard;
updateMutation.mutateAsync( updateMutation.mutateAsync(
{ {
id: selectedDashboard.id, id: selectedDashboard.id,
data: { data: {
...selectedDashboard.data, ...newDashboard.data,
variables: updatedVariablesData, variables: updatedVariablesData,
}, },
}, },
@ -225,7 +237,7 @@ function VariablesSetting({
const variables = convertVariablesToDbFormat(newVariablesArr); const variables = convertVariablesToDbFormat(newVariablesArr);
setVariablesTableData(newVariablesArr); setVariablesTableData(newVariablesArr);
updateVariables(variables); updateVariables(variables, variableData?.id);
onDoneVariableViewMode(); onDoneVariableViewMode();
}; };

View File

@ -1,57 +1,43 @@
import { useMemo } from 'react'; import { getFiltersFromKeyValue } from 'pages/Celery/CeleryOverview/CeleryOverviewUtils';
import { Dashboard } from 'types/api/dashboard/getAll'; import { useCallback } from 'react';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { Dashboard, IDashboardVariable } from 'types/api/dashboard/getAll';
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData'; import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
import { v4 as uuid } from 'uuid';
import { useAddTagFiltersToDashboard } from './useAddTagFiltersToDashboard'; import { addTagFiltersToDashboard } from '../../container/NewDashboard/DashboardSettings/Variables/addTagFiltersToDashboard';
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 * A hook that returns a function to add dynamic variables to dashboard panels as tag filters.
* *
* @param dashboard The dashboard configuration * @returns A function that, when given a dashboard and variable config, returns the updated dashboard.
* @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 = ( export const useAddDynamicVariableToPanels = (): ((
dashboard: Dashboard | undefined, dashboard: Dashboard | undefined,
variableConfig: DynamicVariableConfig, variableConfig: IDashboardVariable,
widgetIds?: string[], ) => Dashboard | undefined) =>
): Dashboard | undefined => { useCallback(
// Create the tag filter based on the variable configuration (
const tagFilters = useMemo((): TagFilterItem[] => { dashboard: Dashboard | undefined,
if (!variableConfig) { variableConfig: IDashboardVariable,
return []; ): Dashboard | undefined => {
} if (!variableConfig) return dashboard;
const { variableName, tagKey, operator } = variableConfig; const {
dynamicVariablesAttribute,
name,
dynamicVariablesWidgetIds,
} = variableConfig;
// Create a TagFilterItem that uses the variable as the value const tagFilters: TagFilterItem[] = [
const filter: TagFilterItem = { getFiltersFromKeyValue(dynamicVariablesAttribute || '', `$${name}`),
id: uuid().slice(0, 8), ];
key: tagKey as BaseAutocompleteData,
op: operator,
value: `$${variableName}`,
};
return [filter]; return addTagFiltersToDashboard(
}, [variableConfig]); dashboard,
tagFilters,
// Use the existing hook to add these filters to the dashboard dynamicVariablesWidgetIds,
return useAddTagFiltersToDashboard(dashboard, tagFilters, widgetIds); );
}; },
[],
);
export default useAddDynamicVariableToPanels; export default useAddDynamicVariableToPanels;

View File

@ -55,6 +55,7 @@ export interface IDashboardVariable {
dynamicVariablesAttribute?: string; dynamicVariablesAttribute?: string;
dynamicVariablesSource?: string; dynamicVariablesSource?: string;
haveCustomValuesSelected?: boolean; haveCustomValuesSelected?: boolean;
dynamicVariablesWidgetIds?: string[];
} }
export interface Dashboard { export interface Dashboard {
id: string; id: string;