From c80b9e4da4cd89270d98c871352eed408c305574 Mon Sep 17 00:00:00 2001 From: SagarRajput-7 Date: Thu, 21 Aug 2025 11:29:24 +0530 Subject: [PATCH] Revert "feat: added variable in url and made dashboard sync around that and sharable (#7944)" This reverts commit 1d1557e79ab460d21a12bfacd042c7ce07aecbb8. --- frontend/src/constants/query.ts | 1 - .../DashboardVariableSelection.tsx | 15 +- .../VariableItem.tsx | 11 ++ .../__test__/useVariablesFromUrl.test.tsx | 169 ------------------ .../hooks/dashboard/useVariablesFromUrl.tsx | 102 ----------- .../src/providers/Dashboard/Dashboard.tsx | 44 +---- .../Dashboard/initializeDefaultVariables.ts | 46 ----- 7 files changed, 19 insertions(+), 369 deletions(-) delete mode 100644 frontend/src/hooks/dashboard/__test__/useVariablesFromUrl.test.tsx delete mode 100644 frontend/src/hooks/dashboard/useVariablesFromUrl.tsx delete mode 100644 frontend/src/providers/Dashboard/initializeDefaultVariables.ts diff --git a/frontend/src/constants/query.ts b/frontend/src/constants/query.ts index b256685f5cfe..a7852cdb92e2 100644 --- a/frontend/src/constants/query.ts +++ b/frontend/src/constants/query.ts @@ -49,5 +49,4 @@ export enum QueryParams { tab = 'tab', thresholds = 'thresholds', selectedExplorerView = 'selectedExplorerView', - variableConfigs = 'variableConfigs', } diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.tsx b/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.tsx index a999a0a9dbf8..fe49f48884fd 100644 --- a/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.tsx +++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.tsx @@ -1,8 +1,8 @@ -import { Row } from 'antd'; -import useVariablesFromUrl from 'hooks/dashboard/useVariablesFromUrl'; +import './DashboardVariableSelection.styles.scss'; + +import { Alert, Row } from 'antd'; import { isEmpty } from 'lodash-es'; import { useDashboard } from 'providers/Dashboard/Dashboard'; -import { initializeDefaultVariables } from 'providers/Dashboard/initializeDefaultVariables'; import { memo, useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; import { AppState } from 'store/reducers'; @@ -28,8 +28,6 @@ function DashboardVariableSelection(): JSX.Element | null { setVariablesToGetUpdated, } = useDashboard(); - const { updateUrlVariable, getUrlVariables } = useVariablesFromUrl(); - const { data } = selectedDashboard || {}; const { variables } = data || {}; @@ -63,11 +61,8 @@ function DashboardVariableSelection(): JSX.Element | null { tableRowData.sort((a, b) => a.order - b.order); setVariablesTableData(tableRowData); - - // Initialize variables with default values if not in URL - initializeDefaultVariables(variables, getUrlVariables, updateUrlVariable); } - }, [getUrlVariables, updateUrlVariable, variables]); + }, [variables]); useEffect(() => { if (variablesTableData.length > 0) { @@ -116,8 +111,6 @@ function DashboardVariableSelection(): JSX.Element | null { if (id) { updateLocalStorageDashboardVariables(name, value, allSelected); - updateUrlVariable(id, value, allSelected); - if (selectedDashboard) { setSelectedDashboard((prev) => { if (prev) { diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx b/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx index 470e470e25e8..550fec4c4ebe 100644 --- a/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx +++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx @@ -135,6 +135,17 @@ function VariableItem({ ) { const value = variableData.selectedValue; let allSelected = false; + // The default value for multi-select is ALL and first value for + // single select + // console.log(valueNotInList); + // if (valueNotInList) { + // if (variableData.multiSelect) { + // value = newOptionsData; + // allSelected = true; + // } else { + // [value] = newOptionsData; + // } + // } else if (variableData.multiSelect) { const { selectedValue } = variableData; diff --git a/frontend/src/hooks/dashboard/__test__/useVariablesFromUrl.test.tsx b/frontend/src/hooks/dashboard/__test__/useVariablesFromUrl.test.tsx deleted file mode 100644 index aece2b927716..000000000000 --- a/frontend/src/hooks/dashboard/__test__/useVariablesFromUrl.test.tsx +++ /dev/null @@ -1,169 +0,0 @@ -import { act, renderHook } from '@testing-library/react'; -import { QueryParams } from 'constants/query'; -import { createMemoryHistory } from 'history'; -import { Router } from 'react-router-dom'; -import { IDashboardVariable } from 'types/api/dashboard/getAll'; - -import useVariablesFromUrl from '../useVariablesFromUrl'; - -describe('useVariablesFromUrl', () => { - it('should initialize with empty variables when no URL params exist', () => { - const history = createMemoryHistory({ - initialEntries: ['/'], - }); - - const { result } = renderHook(() => useVariablesFromUrl(), { - wrapper: ({ children }: { children: React.ReactNode }) => ( - {children} - ), - }); - - expect(result.current.getUrlVariables()).toEqual({}); - }); - - it('should correctly parse variables from URL', () => { - const mockVariables = { - var1: { selectedValue: 'value1', allSelected: false }, - var2: { selectedValue: ['value2', 'value3'], allSelected: true }, - }; - - const encodedVariables = encodeURIComponent(JSON.stringify(mockVariables)); - const history = createMemoryHistory({ - initialEntries: [`/?${QueryParams.variableConfigs}=${encodedVariables}`], - }); - - const { result } = renderHook(() => useVariablesFromUrl(), { - wrapper: ({ children }: { children: React.ReactNode }) => ( - {children} - ), - }); - - expect(result.current.getUrlVariables()).toEqual(mockVariables); - }); - - it('should handle malformed URL parameters gracefully', () => { - const history = createMemoryHistory({ - initialEntries: [`/?${QueryParams.variableConfigs}=invalid-json`], - }); - - const { result } = renderHook(() => useVariablesFromUrl(), { - wrapper: ({ children }: { children: React.ReactNode }) => ( - {children} - ), - }); - - // Should return empty object when JSON parsing fails - expect(result.current.getUrlVariables()).toEqual({}); - }); - - it('should set variables to URL correctly', () => { - const history = createMemoryHistory({ - initialEntries: ['/'], - }); - - const { result } = renderHook(() => useVariablesFromUrl(), { - wrapper: ({ children }: { children: React.ReactNode }) => ( - {children} - ), - }); - - const mockVariables = { - var1: { selectedValue: 'value1', allSelected: false }, - }; - - act(() => { - result.current.setUrlVariables(mockVariables); - }); - - // Check if the URL was updated correctly - const searchParams = new URLSearchParams(history.location.search); - const urlVariables = searchParams.get(QueryParams.variableConfigs); - - expect(urlVariables).toBeTruthy(); - expect(JSON.parse(decodeURIComponent(urlVariables || ''))).toEqual( - mockVariables, - ); - }); - - it('should remove variables param from URL when empty object is provided', () => { - const mockVariables = { - var1: { selectedValue: 'value1', allSelected: false }, - }; - - const encodedVariables = encodeURIComponent(JSON.stringify(mockVariables)); - const history = createMemoryHistory({ - initialEntries: [`/?${QueryParams.variableConfigs}=${encodedVariables}`], - }); - - const { result } = renderHook(() => useVariablesFromUrl(), { - wrapper: ({ children }: { children: React.ReactNode }) => ( - {children} - ), - }); - - act(() => { - result.current.setUrlVariables({}); - }); - - // Check if the URL param was removed - const searchParams = new URLSearchParams(history.location.search); - expect(searchParams.has(QueryParams.variableConfigs)).toBe(false); - }); - - it('should update a specific variable correctly', () => { - const initialVariables = { - var1: { selectedValue: 'value1', allSelected: false }, - var2: { selectedValue: ['value2'], allSelected: true }, - }; - - const encodedVariables = encodeURIComponent(JSON.stringify(initialVariables)); - const history = createMemoryHistory({ - initialEntries: [`/?${QueryParams.variableConfigs}=${encodedVariables}`], - }); - - const { result } = renderHook(() => useVariablesFromUrl(), { - wrapper: ({ children }: { children: React.ReactNode }) => ( - {children} - ), - }); - - const newValue: IDashboardVariable['selectedValue'] = 'updated-value'; - - act(() => { - result.current.updateUrlVariable('var1', newValue, true); - }); - - // Check if only the specified variable was updated - const updatedVariables = result.current.getUrlVariables(); - expect(updatedVariables.var1).toEqual({ - selectedValue: newValue, - allSelected: true, - }); - expect(updatedVariables.var2).toEqual(initialVariables.var2); - }); - - it('should preserve other URL parameters when updating variables', () => { - const history = createMemoryHistory({ - initialEntries: ['/?otherParam=value'], - }); - - const { result } = renderHook(() => useVariablesFromUrl(), { - wrapper: ({ children }: { children: React.ReactNode }) => ( - {children} - ), - }); - - const mockVariables = { - var1: { selectedValue: 'value1', allSelected: false }, - }; - - act(() => { - result.current.setUrlVariables(mockVariables); - }); - - // Check if other params are preserved - const searchParams = new URLSearchParams(history.location.search); - expect(searchParams.get('otherParam')).toBe('value'); - expect(searchParams.has(QueryParams.variableConfigs)).toBe(true); - }); -}); diff --git a/frontend/src/hooks/dashboard/useVariablesFromUrl.tsx b/frontend/src/hooks/dashboard/useVariablesFromUrl.tsx deleted file mode 100644 index d06bfab4d59e..000000000000 --- a/frontend/src/hooks/dashboard/useVariablesFromUrl.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import { QueryParams } from 'constants/query'; -import useUrlQuery from 'hooks/useUrlQuery'; -import { useCallback } from 'react'; -import { useHistory } from 'react-router-dom'; -import { IDashboardVariable } from 'types/api/dashboard/getAll'; - -interface LocalStoreDashboardVariables { - [id: string]: { - selectedValue: IDashboardVariable['selectedValue']; - allSelected: boolean; - }; -} - -interface UseVariablesFromUrlReturn { - getUrlVariables: () => LocalStoreDashboardVariables; - setUrlVariables: (variables: LocalStoreDashboardVariables) => void; - updateUrlVariable: ( - id: string, - selectedValue: IDashboardVariable['selectedValue'], - allSelected: boolean, - ) => void; - clearUrlVariables: () => void; -} - -const useVariablesFromUrl = (): UseVariablesFromUrlReturn => { - const urlQuery = useUrlQuery(); - const history = useHistory(); - - const getUrlVariables = useCallback((): LocalStoreDashboardVariables => { - const variableConfigsParam = urlQuery.get(QueryParams.variableConfigs); - - if (!variableConfigsParam) { - return {}; - } - - try { - return JSON.parse(decodeURIComponent(variableConfigsParam)); - } catch (error) { - console.error('Failed to parse variables from URL:', error); - return {}; - } - }, [urlQuery]); - - const setUrlVariables = useCallback( - (variables: LocalStoreDashboardVariables): void => { - const params = new URLSearchParams(urlQuery.toString()); - - if (Object.keys(variables).length === 0) { - params.delete(QueryParams.variableConfigs); - } else { - try { - const encodedVariables = encodeURIComponent(JSON.stringify(variables)); - params.set(QueryParams.variableConfigs, encodedVariables); - } catch (error) { - console.error('Failed to serialize variables for URL:', error); - } - } - - history.replace({ - search: params.toString(), - }); - }, - [history, urlQuery], - ); - - const clearUrlVariables = useCallback((): void => { - const params = new URLSearchParams(urlQuery.toString()); - params.delete(QueryParams.variableConfigs); - params.delete('options'); - - history.replace({ - search: params.toString(), - }); - }, [history, urlQuery]); - - const updateUrlVariable = useCallback( - ( - id: string, - selectedValue: IDashboardVariable['selectedValue'], - allSelected: boolean, - ): void => { - const currentVariables = getUrlVariables(); - - const updatedVariables = { - ...currentVariables, - [id]: { selectedValue, allSelected }, - }; - - setUrlVariables(updatedVariables); - }, - [getUrlVariables, setUrlVariables], - ); - - return { - getUrlVariables, - setUrlVariables, - updateUrlVariable, - clearUrlVariables, - }; -}; - -export default useVariablesFromUrl; diff --git a/frontend/src/providers/Dashboard/Dashboard.tsx b/frontend/src/providers/Dashboard/Dashboard.tsx index 98ff9273cc1e..a51ac9439f42 100644 --- a/frontend/src/providers/Dashboard/Dashboard.tsx +++ b/frontend/src/providers/Dashboard/Dashboard.tsx @@ -7,8 +7,6 @@ import ROUTES from 'constants/routes'; import { getMinMax } from 'container/TopNav/AutoRefresh/config'; import dayjs, { Dayjs } from 'dayjs'; import { useDashboardVariablesFromLocalStorage } from 'hooks/dashboard/useDashboardFromLocalStorage'; -import useVariablesFromUrl from 'hooks/dashboard/useVariablesFromUrl'; -import useAxiosError from 'hooks/useAxiosError'; import { useSafeNavigate } from 'hooks/useSafeNavigate'; import useTabVisibility from 'hooks/useTabFocus'; import useUrlQuery from 'hooks/useUrlQuery'; @@ -18,7 +16,6 @@ import isEqual from 'lodash-es/isEqual'; import isUndefined from 'lodash-es/isUndefined'; import omitBy from 'lodash-es/omitBy'; import { useAppContext } from 'providers/App/App'; -import { initializeDefaultVariables } from 'providers/Dashboard/initializeDefaultVariables'; import { useErrorModal } from 'providers/ErrorModalProvider'; import { createContext, @@ -201,12 +198,6 @@ export function DashboardProvider({ updateLocalStorageDashboardVariables, } = useDashboardVariablesFromLocalStorage(dashboardId); - const { - getUrlVariables, - updateUrlVariable, - clearUrlVariables, - } = useVariablesFromUrl(); - const updatedTimeRef = useRef(null); // Using ref to store the updated time const modalRef = useRef(null); @@ -217,14 +208,6 @@ export function DashboardProvider({ const [isDashboardFetching, setIsDashboardFetching] = useState(false); - // Clear variable configs when not on dashboard pages - useEffect(() => { - const isOnDashboardPage = !!isDashboardPage || !!isDashboardWidgetPage; - if (!isOnDashboardPage) { - clearUrlVariables(); - } - }, [isDashboardPage, isDashboardWidgetPage, clearUrlVariables]); - const mergeDBWithLocalStorage = ( data: Dashboard, localStorageVariables: any, @@ -234,23 +217,11 @@ export function DashboardProvider({ const updatedVariables = data.data.variables; Object.keys(data.data.variables).forEach((variable) => { const variableData = data.data.variables[variable]; - - // values from url - const urlVariable = getUrlVariables()[variableData.id]; - - let updatedVariable = { + const updatedVariable = { ...data.data.variables[variable], ...localStorageVariables[variableData.name as any], }; - // respect the url variable if it is set, override the others - if (urlVariable) { - updatedVariable = { - ...updatedVariable, - ...urlVariable, - }; - } - updatedVariables[variable] = updatedVariable; }); updatedData.data.variables = updatedVariables; @@ -318,16 +289,9 @@ export function DashboardProvider({ onError: (error) => { showErrorModal(error as APIError); }, - // eslint-disable-next-line sonarjs/cognitive-complexity - onSuccess: (data) => { - // if the url variable is not set for any variable, set it to the default value - const variables = data?.data?.variables; - if (variables) { - initializeDefaultVariables(variables, getUrlVariables, updateUrlVariable); - } - - const updatedDashboardData = transformDashboardVariables(data); - const updatedDate = dayjs(updatedDashboardData.updatedAt); + onSuccess: (data: SuccessResponseV2) => { + const updatedDashboardData = transformDashboardVariables(data?.data); + const updatedDate = dayjs(updatedDashboardData?.updatedAt); setIsDashboardLocked(updatedDashboardData?.locked || false); diff --git a/frontend/src/providers/Dashboard/initializeDefaultVariables.ts b/frontend/src/providers/Dashboard/initializeDefaultVariables.ts deleted file mode 100644 index 132863a3a289..000000000000 --- a/frontend/src/providers/Dashboard/initializeDefaultVariables.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { IDashboardVariable } from 'types/api/dashboard/getAll'; - -import { commaValuesParser } from '../../lib/dashbaordVariables/customCommaValuesParser'; - -interface UrlVariables { - [key: string]: any; -} - -/** - * Initializes default values for dashboard variables if not already in URL - * Handles cases where variables might be keyed by either id or name - * - * @param variables Dashboard variables object - * @param getUrlVariables Function to get variables from URL - * @param updateUrlVariable Function to update URL with variable values - */ -export const initializeDefaultVariables = ( - variables: Record, - getUrlVariables: () => UrlVariables | undefined, - updateUrlVariable: ( - id: string, - selectedValue: IDashboardVariable['selectedValue'], - allSelected: boolean, - ) => void, -): void => { - if (!variables) return; - - Object.values(variables).forEach((variable) => { - const { id, name } = variable; - const urlVariables = getUrlVariables(); - - // Check if either id or name is available in URL variables - const existsInUrl = - (id && urlVariables?.[id]) || (name && urlVariables?.[name]); - - if (!existsInUrl) { - updateUrlVariable( - id, - variable.type === 'CUSTOM' - ? commaValuesParser(variable?.customValue || '') - : variable?.selectedValue || variable?.defaultValue, - variable.allSelected || false, - ); - } - }); -};