From 7359c0a8256db230f4e384e5a9c2bad770a4805f Mon Sep 17 00:00:00 2001 From: Aarif Mohammad <97459053+Aarif5435@users.noreply.github.com> Date: Thu, 13 Feb 2025 09:48:18 +0530 Subject: [PATCH] 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 --- .../components/ExplorerCard/ExplorerCard.tsx | 18 ++++++- .../ExplorerCard/test/ExplorerCard.test.tsx | 7 +++ frontend/src/components/ExplorerCard/types.ts | 2 + frontend/src/components/ExplorerCard/utils.ts | 10 ++-- .../ExplorerOptions/ExplorerOptions.tsx | 54 ++++++++++++++----- frontend/src/providers/QueryBuilder.tsx | 8 ++- frontend/src/types/common/queryBuilder.ts | 2 + 7 files changed, 82 insertions(+), 19 deletions(-) diff --git a/frontend/src/components/ExplorerCard/ExplorerCard.tsx b/frontend/src/components/ExplorerCard/ExplorerCard.tsx index 73d7a24c74..a7e18e2c79 100644 --- a/frontend/src/components/ExplorerCard/ExplorerCard.tsx +++ b/frontend/src/components/ExplorerCard/ExplorerCard.tsx @@ -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), diff --git a/frontend/src/components/ExplorerCard/test/ExplorerCard.test.tsx b/frontend/src/components/ExplorerCard/test/ExplorerCard.test.tsx index 1fdb29d281..5fe90b283b 100644 --- a/frontend/src/components/ExplorerCard/test/ExplorerCard.test.tsx +++ b/frontend/src/components/ExplorerCard/test/ExplorerCard.test.tsx @@ -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', () => ({ diff --git a/frontend/src/components/ExplorerCard/types.ts b/frontend/src/components/ExplorerCard/types.ts index 94e7ab788f..f4f0426925 100644 --- a/frontend/src/components/ExplorerCard/types.ts +++ b/frontend/src/components/ExplorerCard/types.ts @@ -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 { diff --git a/frontend/src/components/ExplorerCard/utils.ts b/frontend/src/components/ExplorerCard/utils.ts index 0c1ef66469..41d7da040d 100644 --- a/frontend/src/components/ExplorerCard/utils.ts +++ b/frontend/src/components/ExplorerCard/utils.ts @@ -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, + ) ); }; diff --git a/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx b/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx index 8d81e69d0a..b6c12ec744 100644 --- a/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx +++ b/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx @@ -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, diff --git a/frontend/src/providers/QueryBuilder.tsx b/frontend/src/providers/QueryBuilder.tsx index 031ca9841f..2c157c0e1f 100644 --- a/frontend/src/providers/QueryBuilder.tsx +++ b/frontend/src/providers/QueryBuilder.tsx @@ -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], ); diff --git a/frontend/src/types/common/queryBuilder.ts b/frontend/src/types/common/queryBuilder.ts index fe77e1ad68..0ff38cc4a0 100644 --- a/frontend/src/types/common/queryBuilder.ts +++ b/frontend/src/types/common/queryBuilder.ts @@ -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; };