fix: wrong payload being sent in the dashboard payload (#4854)

* fix: wrong payload being sent in the dashboard payload

* fix: sync the update set dashboard function

* fix: syncronise the var updates

* fix: jest test cases

* fix: added review comments

* fix: do not make query range API call until the queue is empty

---------

Co-authored-by: Srikanth Chekuri <srikanth.chekuri92@gmail.com>
This commit is contained in:
Vikrant Gupta 2024-04-15 11:11:14 +05:30 committed by GitHub
parent a54b7baa7d
commit 3a5a61aff9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 96 additions and 68 deletions

View File

@ -35,7 +35,11 @@ function GridCardGraph({
}: GridCardGraphProps): JSX.Element {
const dispatch = useDispatch();
const [errorMessage, setErrorMessage] = useState<string>();
const { toScrollWidgetId, setToScrollWidgetId } = useDashboard();
const {
toScrollWidgetId,
setToScrollWidgetId,
variablesToGetUpdated,
} = useDashboard();
const { minTime, maxTime, selectedTime: globalSelectedInterval } = useSelector<
AppState,
GlobalReducer
@ -90,7 +94,11 @@ function GridCardGraph({
const isEmptyWidget =
widget?.id === PANEL_TYPES.EMPTY_WIDGET || isEmpty(widget);
const queryEnabledCondition = isVisible && !isEmptyWidget && isQueryEnabled;
const queryEnabledCondition =
isVisible &&
!isEmptyWidget &&
isQueryEnabled &&
isEmpty(variablesToGetUpdated);
const [requestData, setRequestData] = useState<GetQueryResultsProps>(() => {
if (widget.panelTypes !== PANEL_TYPES.LIST) {

View File

@ -1,9 +1,9 @@
import { Row } from 'antd';
import { isNull } from 'lodash-es';
import { useDashboard } from 'providers/Dashboard/Dashboard';
import { memo, useEffect, useState } from 'react';
import { IDashboardVariable } from 'types/api/dashboard/getAll';
import { convertVariablesToDbFormat } from './util';
import VariableItem from './VariableItem';
function DashboardVariableSelection(): JSX.Element | null {
@ -11,15 +11,14 @@ function DashboardVariableSelection(): JSX.Element | null {
selectedDashboard,
setSelectedDashboard,
updateLocalStorageDashboardVariables,
variablesToGetUpdated,
setVariablesToGetUpdated,
} = useDashboard();
const { data } = selectedDashboard || {};
const { variables } = data || {};
const [update, setUpdate] = useState<boolean>(false);
const [lastUpdatedVar, setLastUpdatedVar] = useState<string>('');
const [variablesTableData, setVariablesTableData] = useState<any>([]);
useEffect(() => {
@ -45,8 +44,27 @@ function DashboardVariableSelection(): JSX.Element | null {
}, [variables]);
const onVarChanged = (name: string): void => {
setLastUpdatedVar(name);
setUpdate(!update);
/**
* this function takes care of adding the dependent variables to current update queue and removing
* the updated variable name from the queue
*/
const dependentVariables = variablesTableData
?.map((variable: any) => {
if (variable.type === 'QUERY') {
const re = new RegExp(`\\{\\{\\s*?\\.${name}\\s*?\\}\\}`); // regex for `{{.var}}`
const queryValue = variable.queryValue || '';
const dependVarReMatch = queryValue.match(re);
if (dependVarReMatch !== null && dependVarReMatch.length > 0) {
return variable.name;
}
}
return null;
})
.filter((val: string | null) => !isNull(val));
setVariablesToGetUpdated((prev) => [
...prev.filter((v) => v !== name),
...dependentVariables,
]);
};
const onValueUpdate = (
@ -56,37 +74,31 @@ function DashboardVariableSelection(): JSX.Element | null {
allSelected: boolean,
): void => {
if (id) {
const newVariablesArr = variablesTableData.map(
(variable: IDashboardVariable) => {
const variableCopy = { ...variable };
if (variableCopy.id === id) {
variableCopy.selectedValue = value;
variableCopy.allSelected = allSelected;
}
return variableCopy;
},
);
updateLocalStorageDashboardVariables(name, value, allSelected);
const variables = convertVariablesToDbFormat(newVariablesArr);
if (selectedDashboard) {
setSelectedDashboard({
...selectedDashboard,
data: {
...selectedDashboard?.data,
variables: {
...variables,
},
},
setSelectedDashboard((prev) => {
if (prev) {
return {
...prev,
data: {
...prev?.data,
variables: {
...prev?.data.variables,
[id]: {
...prev.data.variables[id],
selectedValue: value,
allSelected,
},
},
},
};
}
return prev;
});
}
onVarChanged(name);
setUpdate(!update);
}
};
@ -107,13 +119,12 @@ function DashboardVariableSelection(): JSX.Element | null {
<VariableItem
key={`${variable.name}${variable.id}}${variable.order}`}
existingVariables={variables}
lastUpdatedVar={lastUpdatedVar}
variableData={{
name: variable.name,
...variable,
change: update,
}}
onValueUpdate={onValueUpdate}
variablesToGetUpdated={variablesToGetUpdated}
/>
))}
</Row>

View File

@ -53,7 +53,7 @@ describe('VariableItem', () => {
variableData={mockVariableData}
existingVariables={{}}
onValueUpdate={mockOnValueUpdate}
lastUpdatedVar=""
variablesToGetUpdated={[]}
/>
</MockQueryClientProvider>,
);
@ -68,7 +68,7 @@ describe('VariableItem', () => {
variableData={mockVariableData}
existingVariables={{}}
onValueUpdate={mockOnValueUpdate}
lastUpdatedVar=""
variablesToGetUpdated={[]}
/>
</MockQueryClientProvider>,
);
@ -82,7 +82,7 @@ describe('VariableItem', () => {
variableData={mockVariableData}
existingVariables={{}}
onValueUpdate={mockOnValueUpdate}
lastUpdatedVar=""
variablesToGetUpdated={[]}
/>
</MockQueryClientProvider>,
);
@ -110,7 +110,7 @@ describe('VariableItem', () => {
variableData={mockCustomVariableData}
existingVariables={{}}
onValueUpdate={mockOnValueUpdate}
lastUpdatedVar=""
variablesToGetUpdated={[]}
/>
</MockQueryClientProvider>,
);
@ -131,7 +131,7 @@ describe('VariableItem', () => {
variableData={customVariableData}
existingVariables={{}}
onValueUpdate={mockOnValueUpdate}
lastUpdatedVar=""
variablesToGetUpdated={[]}
/>
</MockQueryClientProvider>,
);
@ -146,7 +146,7 @@ describe('VariableItem', () => {
variableData={mockCustomVariableData}
existingVariables={{}}
onValueUpdate={mockOnValueUpdate}
lastUpdatedVar=""
variablesToGetUpdated={[]}
/>
</MockQueryClientProvider>,
);

View File

@ -32,7 +32,7 @@ interface VariableItemProps {
arg1: IDashboardVariable['selectedValue'],
allSelected: boolean,
) => void;
lastUpdatedVar: string;
variablesToGetUpdated: string[];
}
const getSelectValue = (
@ -49,7 +49,7 @@ function VariableItem({
variableData,
existingVariables,
onValueUpdate,
lastUpdatedVar,
variablesToGetUpdated,
}: VariableItemProps): JSX.Element {
const [optionsData, setOptionsData] = useState<(string | number | boolean)[]>(
[],
@ -108,16 +108,10 @@ function VariableItem({
if (!areArraysEqual(newOptionsData, oldOptionsData)) {
/* eslint-disable no-useless-escape */
const re = new RegExp(`\\{\\{\\s*?\\.${lastUpdatedVar}\\s*?\\}\\}`); // regex for `{{.var}}`
// If the variable is dependent on the last updated variable
// and contains the last updated variable in its query (of the form `{{.var}}`)
// then we need to update the value of the variable
const queryValue = variableData.queryValue || '';
const dependVarReMatch = queryValue.match(re);
if (
variableData.type === 'QUERY' &&
dependVarReMatch !== null &&
dependVarReMatch.length > 0
variableData.name &&
variablesToGetUpdated.includes(variableData.name)
) {
let value = variableData.selectedValue;
let allSelected = false;

View File

@ -67,30 +67,32 @@ export const useDashboardVariablesFromLocalStorage = (
setCurrentDashboard(defaultTo(localStoreDashboardVariables[dashboardId], {}));
}, [dashboardId]);
useEffect(() => {
try {
const serializedData = JSON.stringify(allDashboards);
setLocalStorageKey(LOCALSTORAGE.DASHBOARD_VARIABLES, serializedData);
} catch {
console.error('Failed to set dashboards in local storage');
}
}, [allDashboards]);
useEffect(() => {
setAllDashboards((prev) => ({
...prev,
[dashboardId]: { ...currentDashboard },
}));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentDashboard]);
const updateLocalStorageDashboardVariables = (
id: string,
selectedValue: IDashboardVariable['selectedValue'],
allSelected: boolean,
): void => {
const newCurrentDashboard = {
...currentDashboard,
setCurrentDashboard((prev) => ({
...prev,
[id]: { selectedValue, allSelected },
};
const newAllDashboards = {
...allDashboards,
[dashboardId]: newCurrentDashboard,
};
try {
const serializedData = JSON.stringify(newAllDashboards);
setLocalStorageKey(LOCALSTORAGE.DASHBOARD_VARIABLES, serializedData);
} catch {
console.error('Failed to set dashboards in local storage');
}
setAllDashboards(newAllDashboards);
setCurrentDashboard(newCurrentDashboard);
}));
};
return {

View File

@ -53,6 +53,8 @@ const DashboardContext = createContext<IDashboardContext>({
toScrollWidgetId: '',
setToScrollWidgetId: () => {},
updateLocalStorageDashboardVariables: () => {},
variablesToGetUpdated: [],
setVariablesToGetUpdated: () => {},
});
interface Props {
@ -86,6 +88,10 @@ export function DashboardProvider({
exact: true,
});
const [variablesToGetUpdated, setVariablesToGetUpdated] = useState<string[]>(
[],
);
const [layouts, setLayouts] = useState<Layout[]>([]);
const { isLoggedIn } = useSelector<AppState, AppReducer>((state) => state.app);
@ -171,6 +177,7 @@ export function DashboardProvider({
return data;
};
console.log(variablesToGetUpdated);
const dashboardResponse = useQuery(
[REACT_QUERY_KEY.DASHBOARD_BY_ID, isDashboardPage?.params],
{
@ -323,6 +330,8 @@ export function DashboardProvider({
updatedTimeRef,
setToScrollWidgetId,
updateLocalStorageDashboardVariables,
variablesToGetUpdated,
setVariablesToGetUpdated,
}),
// eslint-disable-next-line react-hooks/exhaustive-deps
[
@ -335,6 +344,8 @@ export function DashboardProvider({
toScrollWidgetId,
updateLocalStorageDashboardVariables,
currentDashboard,
variablesToGetUpdated,
setVariablesToGetUpdated,
],
);

View File

@ -30,4 +30,6 @@ export interface IDashboardContext {
| undefined,
allSelected: boolean,
) => void;
variablesToGetUpdated: string[];
setVariablesToGetUpdated: React.Dispatch<React.SetStateAction<string[]>>;
}