From c729bd51eab4e702ff6d8f262d8242a9ca94b8cd Mon Sep 17 00:00:00 2001 From: Shrushti Polekar Date: Fri, 20 Jun 2025 11:23:29 +0530 Subject: [PATCH] Fix(ui): Additional query call in user profile page (#21856) * fix additional query call in user profile page * added unit test --- .../tabs/AssetsTabs.component.tsx | 14 +++++-- .../tabs/AssetsTabs.interface.ts | 2 +- .../Settings/Users/Users.component.test.tsx | 40 ++++++++++++++++++- .../Settings/Users/Users.component.tsx | 25 +----------- 4 files changed, 51 insertions(+), 30 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/AssetsTabs.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/AssetsTabs.component.tsx index 5c87629210b..9881176ca86 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/AssetsTabs.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/AssetsTabs.component.tsx @@ -137,6 +137,9 @@ const AssetsTabs = forwardRef( const [data, setData] = useState([]); const [quickFilterQuery, setQuickFilterQuery] = useState(); + const [totalAssetCount, setTotalAssetCount] = useState( + assetCount ?? 0 + ); const { currentPage, @@ -239,6 +242,9 @@ const AssetsTabs = forwardRef( handlePagingChange({ total: res.hits.total.value ?? 0 }); setData(hits); setAggregations(getAggregations(res?.aggregations)); + if (assetCount === undefined) { + setTotalAssetCount(res.hits.total.value ?? 0); + } hits[0] && setSelectedCard(hits[0]._source); } catch { // Nothing here @@ -246,7 +252,7 @@ const AssetsTabs = forwardRef( setIsLoading(false); } }, - [activeFilter, currentPage, pageSize, searchValue, queryParam] + [activeFilter, currentPage, pageSize, searchValue, queryParam, assetCount] ); const hideNotification = () => { @@ -815,10 +821,10 @@ const AssetsTabs = forwardRef( id="asset-tab"> - {assetCount > 0 && ( + {totalAssetCount > 0 && ( <> - {!isLoading && permissions?.EditAll && assetCount > 0 && ( + {!isLoading && permissions?.EditAll && totalAssetCount > 0 && (
0, diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/AssetsTabs.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/AssetsTabs.interface.ts index 9f458a943a2..53c8b83b818 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/AssetsTabs.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTerms/tabs/AssetsTabs.interface.ts @@ -31,7 +31,7 @@ export interface AssetsTabsProps { onRemoveAsset?: () => void; entityFqn?: string; permissions: OperationPermission; - assetCount: number; + assetCount?: number; onAssetClick?: (asset?: EntityDetailsObjectInterface) => void; isSummaryPanelOpen: boolean; isEntityDeleted?: boolean; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Users/Users.component.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Users/Users.component.test.tsx index 733668d81ea..733e4dc7871 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Users/Users.component.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Users/Users.component.test.tsx @@ -17,6 +17,7 @@ import React, { ReactNode } from 'react'; import { MemoryRouter } from 'react-router-dom'; import { AuthProvider } from '../../../generated/settings/settings'; import { useApplicationStore } from '../../../hooks/useApplicationStore'; +import { searchQuery } from '../../../rest/searchAPI'; import { mockAccessData, mockUserData, mockUserRole } from './mocks/User.mocks'; import Users from './Users.component'; import { UserPageTabs } from './Users.interface'; @@ -96,7 +97,19 @@ jest.mock( ); jest.mock('../../Glossary/GlossaryTerms/tabs/AssetsTabs.component', () => { - return jest.fn().mockReturnValue(

AssetsTabs

); + return jest.fn().mockImplementation((props) => { + React.useEffect(() => { + if (props.queryFilter === 'my-data') { + searchQuery({ + searchIndex: ['all'] as any, + query: '*', + filters: props.queryFilter, + }); + } + }, [props.queryFilter]); + + return

AssetsTabs

; + }); }); jest.mock( @@ -201,6 +214,16 @@ jest.mock('../../ProfileCard/ProfileSectionUserDetailsCard.component', () => { )); }); +jest.mock('../../../rest/searchAPI', () => ({ + searchQuery: jest.fn().mockResolvedValue({ + hits: { + hits: [], + total: { value: 0 }, + }, + aggregations: {}, + }), +})); + describe('Test User Component', () => { it('Should render user component', async () => { await act(async () => { @@ -357,4 +380,19 @@ describe('Test User Component', () => { (await screen.findByTestId('access-token'))?.closest('.ant-tabs-tab') ).toHaveClass('ant-tabs-tab-disabled'); }); + + it('MyData tab should make query call only once on initial load', async () => { + mockParams.tab = UserPageTabs.MY_DATA; + + await act(async () => { + render(, { + wrapper: MemoryRouter, + }); + }); + const assetComponent = await screen.findByText('AssetsTabs'); + + expect(assetComponent).toBeInTheDocument(); + + expect(searchQuery).toHaveBeenCalledTimes(1); + }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Users/Users.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Users/Users.component.tsx index 40af8e69526..b336f12121f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Users/Users.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Users/Users.component.tsx @@ -20,12 +20,10 @@ import { useHistory, useParams } from 'react-router-dom'; import { ROUTES } from '../../../constants/constants'; import { useLimitStore } from '../../../context/LimitsProvider/useLimitsStore'; import { EntityType } from '../../../enums/entity.enum'; -import { SearchIndex } from '../../../enums/search.enum'; import { useAuth } from '../../../hooks/authHooks'; import { useApplicationStore } from '../../../hooks/useApplicationStore'; import useCustomLocation from '../../../hooks/useCustomLocation/useCustomLocation'; import { useFqn } from '../../../hooks/useFqn'; -import { searchData } from '../../../rest/miscAPI'; import { restoreUser } from '../../../rest/userAPI'; import { DEFAULT_ENTITY_PERMISSION } from '../../../utils/PermissionsUtils'; import { getUserPath } from '../../../utils/RouterUtils'; @@ -62,7 +60,6 @@ const Users = ({ const { tab: activeTab = UserPageTabs.ACTIVITY, subTab } = useParams<{ tab: UserPageTabs; subTab: ActivityFeedTabs }>(); const { fqn: decodedUsername } = useFqn(); - const [assetCount, setAssetCount] = useState(0); const { isAdminUser } = useAuth(); const history = useHistory(); const location = useCustomLocation(); @@ -81,16 +78,6 @@ const Users = ({ [decodedUsername] ); - const fetchAssetsCount = async (query: string) => { - try { - const res = await searchData('', 1, 0, query, '', '', SearchIndex.ALL); - - setAssetCount(res.data.hits.total.value ?? 0); - } catch { - setAssetCount(0); - } - }; - const initLimits = async () => { const limits = await getResourceLimit('user', false); @@ -140,7 +127,6 @@ const Users = ({
history.push(ROUTES.EXPLORE)} @@ -160,7 +146,7 @@ const Users = ({ )} ), - [previewAsset, assetCount, handleAssetClick, setPreviewAsset, currentTab] + [previewAsset, handleAssetClick, setPreviewAsset, currentTab] ); useEffect(() => { if ( @@ -278,15 +264,6 @@ const Users = ({ ] ); - useEffect(() => { - if ([UserPageTabs.MY_DATA, UserPageTabs.FOLLOWING].includes(activeTab)) { - fetchAssetsCount( - activeTab === UserPageTabs.MY_DATA - ? queryFilters.myData - : queryFilters.following - ); - } - }, [activeTab]); const handleRestoreUser = useCallback(async () => { try { await restoreUser(userData.id);