mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-17 15:36:48 +00:00
Revert "feat: added variable in url and made dashboard sync around that and sharable (#7944)"
This reverts commit 1d1557e79ab460d21a12bfacd042c7ce07aecbb8.
This commit is contained in:
parent
f84a926310
commit
c80b9e4da4
@ -49,5 +49,4 @@ export enum QueryParams {
|
||||
tab = 'tab',
|
||||
thresholds = 'thresholds',
|
||||
selectedExplorerView = 'selectedExplorerView',
|
||||
variableConfigs = 'variableConfigs',
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 }) => (
|
||||
<Router history={history}>{children}</Router>
|
||||
),
|
||||
});
|
||||
|
||||
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 }) => (
|
||||
<Router history={history}>{children}</Router>
|
||||
),
|
||||
});
|
||||
|
||||
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 }) => (
|
||||
<Router history={history}>{children}</Router>
|
||||
),
|
||||
});
|
||||
|
||||
// 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 }) => (
|
||||
<Router history={history}>{children}</Router>
|
||||
),
|
||||
});
|
||||
|
||||
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 }) => (
|
||||
<Router history={history}>{children}</Router>
|
||||
),
|
||||
});
|
||||
|
||||
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 }) => (
|
||||
<Router history={history}>{children}</Router>
|
||||
),
|
||||
});
|
||||
|
||||
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 }) => (
|
||||
<Router history={history}>{children}</Router>
|
||||
),
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
@ -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;
|
||||
@ -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<Dayjs | null>(null); // Using ref to store the updated time
|
||||
const modalRef = useRef<any>(null);
|
||||
|
||||
@ -217,14 +208,6 @@ export function DashboardProvider({
|
||||
|
||||
const [isDashboardFetching, setIsDashboardFetching] = useState<boolean>(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<Dashboard>) => {
|
||||
const updatedDashboardData = transformDashboardVariables(data?.data);
|
||||
const updatedDate = dayjs(updatedDashboardData?.updatedAt);
|
||||
|
||||
setIsDashboardLocked(updatedDashboardData?.locked || false);
|
||||
|
||||
|
||||
@ -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<string, IDashboardVariable>,
|
||||
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,
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user