fix[FE]: fix the update view button not visible on changes to Not Updating in Logs and Traces List View. (#6454)

* fix[FE]: fix the update view button not visible on changes to columns in logs and traces list view

* fix: pass the missing options to isStagedQueryUpdated in ExplorerCard

* test: mock useHistory hook for ExplorerCard tests

---------

Co-authored-by: ahmadshaheer <ashaheerki@gmail.com>
This commit is contained in:
Aarif Mohammad 2025-02-13 09:48:18 +05:30 committed by GitHub
parent 846b6a9346
commit 7359c0a825
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 82 additions and 19 deletions

View File

@ -18,7 +18,9 @@ import {
import axios from 'axios';
import TextToolTip from 'components/TextToolTip';
import { SOMETHING_WENT_WRONG } from 'constants/api';
import { LOCALSTORAGE } from 'constants/localStorage';
import { QueryParams } from 'constants/query';
import { useOptionsMenu } from 'container/OptionsMenu';
import { useGetSearchQueryParam } from 'hooks/queryBuilder/useGetSearchQueryParam';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { useDeleteView } from 'hooks/saveViews/useDeleteView';
@ -29,6 +31,7 @@ import { useNotifications } from 'hooks/useNotifications';
import { mapCompositeQueryFromQuery } from 'lib/newQueryBuilder/queryBuilderMappers/mapCompositeQueryFromQuery';
import { useState } from 'react';
import { useCopyToClipboard } from 'react-use';
import { DataSource, StringOperators } from 'types/common/queryBuilder';
import { popupContainer } from 'utils/selectPopupContainer';
import { ExploreHeaderToolTip, SaveButtonText } from './constants';
@ -83,7 +86,20 @@ function ExplorerCard({
const viewKey = useGetSearchQueryParam(QueryParams.viewKey) || '';
const isQueryUpdated = isStagedQueryUpdated(viewsData?.data?.data, viewKey);
const { options } = useOptionsMenu({
storageKey:
sourcepage === DataSource.TRACES
? LOCALSTORAGE.TRACES_LIST_OPTIONS
: LOCALSTORAGE.LOGS_LIST_OPTIONS,
dataSource: sourcepage,
aggregateOperator: StringOperators.NOOP,
});
const isQueryUpdated = isStagedQueryUpdated(
viewsData?.data?.data,
viewKey,
options,
);
const { mutateAsync: updateViewAsync } = useUpdateView({
compositeQuery: mapCompositeQueryFromQuery(currentQuery, panelType),

View File

@ -6,11 +6,18 @@ import { DataSource } from 'types/common/queryBuilder';
import { viewMockData } from '../__mock__/viewData';
import ExplorerCard from '../ExplorerCard';
const historyReplace = jest.fn();
// eslint-disable-next-line sonarjs/no-duplicate-string
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useLocation: (): { pathname: string } => ({
pathname: `${process.env.FRONTEND_API_ENDPOINT}/${ROUTES.TRACES_EXPLORER}/`,
}),
useHistory: (): any => ({
...jest.requireActual('react-router-dom').useHistory(),
replace: historyReplace,
}),
}));
jest.mock('hooks/queryBuilder/useGetPanelTypesQueryParam', () => ({

View File

@ -2,6 +2,7 @@ import { FormInstance } from 'antd';
import { NotificationInstance } from 'antd/es/notification/interface';
import { AxiosResponse } from 'axios';
import { PANEL_TYPES } from 'constants/queryBuilder';
import { OptionsQuery } from 'container/OptionsMenu/types';
import { UseMutateAsyncFunction } from 'react-query';
import { ICompositeMetricQuery } from 'types/api/alerts/compositeQuery';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
@ -36,6 +37,7 @@ export interface IsQueryUpdatedInViewProps {
data: ViewProps[] | undefined;
stagedQuery: Query | null;
currentPanelType: PANEL_TYPES | null;
options: OptionsQuery;
}
export interface SaveViewWithNameProps {

View File

@ -80,12 +80,13 @@ export const isQueryUpdatedInView = ({
data,
stagedQuery,
currentPanelType,
options,
}: IsQueryUpdatedInViewProps): boolean => {
const currentViewDetails = getViewDetailsUsingViewKey(viewKey, data);
if (!currentViewDetails) {
return false;
}
const { query, panelType } = currentViewDetails;
const { query, panelType, extraData } = currentViewDetails;
// Omitting id from aggregateAttribute and groupBy
const updatedCurrentQuery = omitIdFromQuery(stagedQuery);
@ -97,12 +98,15 @@ export const isQueryUpdatedInView = ({
) {
return false;
}
return (
panelType !== currentPanelType ||
!isEqual(query.builder, updatedCurrentQuery?.builder) ||
!isEqual(query.clickhouse_sql, updatedCurrentQuery?.clickhouse_sql) ||
!isEqual(query.promql, updatedCurrentQuery?.promql)
!isEqual(query.promql, updatedCurrentQuery?.promql) ||
!isEqual(
options?.selectColumns,
extraData && JSON.parse(extraData)?.selectColumns,
)
);
};

View File

@ -212,13 +212,46 @@ function ExplorerOptions({
0.08,
);
const { options, handleOptionsChange } = useOptionsMenu({
storageKey:
sourcepage === DataSource.TRACES
? LOCALSTORAGE.TRACES_LIST_OPTIONS
: LOCALSTORAGE.LOGS_LIST_OPTIONS,
dataSource: sourcepage,
aggregateOperator: StringOperators.NOOP,
});
const getUpdatedExtraData = (
extraData: string | undefined,
newSelectedColumns: BaseAutocompleteData[],
): string => {
let updatedExtraData;
if (extraData) {
const parsedExtraData = JSON.parse(extraData);
parsedExtraData.selectColumns = newSelectedColumns;
updatedExtraData = JSON.stringify(parsedExtraData);
} else {
updatedExtraData = JSON.stringify({
color: Color.BG_SIENNA_500,
selectColumns: newSelectedColumns,
});
}
return updatedExtraData;
};
const updatedExtraData = getUpdatedExtraData(
extraData,
options?.selectColumns,
);
const {
mutateAsync: updateViewAsync,
isLoading: isViewUpdating,
} = useUpdateView({
compositeQuery,
viewKey,
extraData: extraData || JSON.stringify({ color: Color.BG_SIENNA_500 }),
extraData: updatedExtraData,
sourcePage: sourcepage,
viewName,
});
@ -230,13 +263,11 @@ function ExplorerOptions({
};
const onUpdateQueryHandler = (): void => {
const extraData = viewsData?.data?.data?.find((view) => view.uuid === viewKey)
?.extraData;
updateViewAsync(
{
compositeQuery: mapCompositeQueryFromQuery(currentQuery, panelType),
viewKey,
extraData: extraData || JSON.stringify({ color: Color.BG_SIENNA_500 }),
extraData: updatedExtraData,
sourcePage: sourcepage,
viewName,
},
@ -258,15 +289,6 @@ function ExplorerOptions({
const { handleExplorerTabChange } = useHandleExplorerTabChange();
const { options, handleOptionsChange } = useOptionsMenu({
storageKey:
sourcepage === DataSource.TRACES
? LOCALSTORAGE.TRACES_LIST_OPTIONS
: LOCALSTORAGE.LOGS_LIST_OPTIONS,
dataSource: sourcepage,
aggregateOperator: StringOperators.NOOP,
});
type ExtraData = {
selectColumns?: BaseAutocompleteData[];
version?: number;
@ -422,7 +444,11 @@ function ExplorerOptions({
history.replace(DATASOURCE_VS_ROUTES[sourcepage]);
};
const isQueryUpdated = isStagedQueryUpdated(viewsData?.data?.data, viewKey);
const isQueryUpdated = isStagedQueryUpdated(
viewsData?.data?.data,
viewKey,
options,
);
const {
isLoading: isSaveViewLoading,

View File

@ -20,6 +20,7 @@ import {
panelTypeDataSourceFormValuesMap,
PartialPanelTypes,
} from 'container/NewWidget/utils';
import { OptionsQuery } from 'container/OptionsMenu/types';
import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam';
import { updateStepInterval } from 'hooks/queryBuilder/useStepInterval';
import useUrlQuery from 'hooks/useUrlQuery';
@ -747,12 +748,17 @@ export function QueryBuilderProvider({
);
const isStagedQueryUpdated = useCallback(
(viewData: ViewProps[] | undefined, viewKey: string): boolean =>
(
viewData: ViewProps[] | undefined,
viewKey: string,
options: OptionsQuery,
): boolean =>
isQueryUpdatedInView({
currentPanelType: panelType,
data: viewData,
stagedQuery,
viewKey,
options,
}),
[panelType, stagedQuery],
);

View File

@ -1,6 +1,7 @@
import { PANEL_TYPES } from 'constants/queryBuilder';
import ROUTES from 'constants/routes';
import { Format } from 'container/NewWidget/RightContainer/types';
import { OptionsQuery } from 'container/OptionsMenu/types';
import { Dispatch, SetStateAction } from 'react';
import {
IBuilderFormula,
@ -246,6 +247,7 @@ export type QueryBuilderContextType = {
isStagedQueryUpdated: (
viewData: ViewProps[] | undefined,
viewKey: string,
options: OptionsQuery,
) => boolean;
isDefaultQuery: (props: IsDefaultQueryProps) => boolean;
};