Fix(ui): Additional query call in user profile page (#21856)

* fix additional query call in user profile page

* added unit test
This commit is contained in:
Shrushti Polekar 2025-06-20 11:23:29 +05:30 committed by GitHub
parent 7035c9e107
commit c729bd51ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 51 additions and 30 deletions

View File

@ -137,6 +137,9 @@ const AssetsTabs = forwardRef(
const [data, setData] = useState<SearchedDataProps['data']>([]); const [data, setData] = useState<SearchedDataProps['data']>([]);
const [quickFilterQuery, setQuickFilterQuery] = const [quickFilterQuery, setQuickFilterQuery] =
useState<QueryFilterInterface>(); useState<QueryFilterInterface>();
const [totalAssetCount, setTotalAssetCount] = useState<number>(
assetCount ?? 0
);
const { const {
currentPage, currentPage,
@ -239,6 +242,9 @@ const AssetsTabs = forwardRef(
handlePagingChange({ total: res.hits.total.value ?? 0 }); handlePagingChange({ total: res.hits.total.value ?? 0 });
setData(hits); setData(hits);
setAggregations(getAggregations(res?.aggregations)); setAggregations(getAggregations(res?.aggregations));
if (assetCount === undefined) {
setTotalAssetCount(res.hits.total.value ?? 0);
}
hits[0] && setSelectedCard(hits[0]._source); hits[0] && setSelectedCard(hits[0]._source);
} catch { } catch {
// Nothing here // Nothing here
@ -246,7 +252,7 @@ const AssetsTabs = forwardRef(
setIsLoading(false); setIsLoading(false);
} }
}, },
[activeFilter, currentPage, pageSize, searchValue, queryParam] [activeFilter, currentPage, pageSize, searchValue, queryParam, assetCount]
); );
const hideNotification = () => { const hideNotification = () => {
@ -815,10 +821,10 @@ const AssetsTabs = forwardRef(
id="asset-tab"> id="asset-tab">
<Row <Row
className={classNames('filters-row gap-2 p-md', { className={classNames('filters-row gap-2 p-md', {
'h-full': assetCount === 0, 'h-full': totalAssetCount === 0,
})} })}
gutter={[0, 20]}> gutter={[0, 20]}>
{assetCount > 0 && ( {totalAssetCount > 0 && (
<> <>
<Col className="d-flex items-center gap-3" span={24}> <Col className="d-flex items-center gap-3" span={24}>
<Dropdown <Dropdown
@ -899,7 +905,7 @@ const AssetsTabs = forwardRef(
} }
/> />
</div> </div>
{!isLoading && permissions?.EditAll && assetCount > 0 && ( {!isLoading && permissions?.EditAll && totalAssetCount > 0 && (
<div <div
className={classNames('asset-tab-delete-notification', { className={classNames('asset-tab-delete-notification', {
visible: selectedItems.size > 0, visible: selectedItems.size > 0,

View File

@ -31,7 +31,7 @@ export interface AssetsTabsProps {
onRemoveAsset?: () => void; onRemoveAsset?: () => void;
entityFqn?: string; entityFqn?: string;
permissions: OperationPermission; permissions: OperationPermission;
assetCount: number; assetCount?: number;
onAssetClick?: (asset?: EntityDetailsObjectInterface) => void; onAssetClick?: (asset?: EntityDetailsObjectInterface) => void;
isSummaryPanelOpen: boolean; isSummaryPanelOpen: boolean;
isEntityDeleted?: boolean; isEntityDeleted?: boolean;

View File

@ -17,6 +17,7 @@ import React, { ReactNode } from 'react';
import { MemoryRouter } from 'react-router-dom'; import { MemoryRouter } from 'react-router-dom';
import { AuthProvider } from '../../../generated/settings/settings'; import { AuthProvider } from '../../../generated/settings/settings';
import { useApplicationStore } from '../../../hooks/useApplicationStore'; import { useApplicationStore } from '../../../hooks/useApplicationStore';
import { searchQuery } from '../../../rest/searchAPI';
import { mockAccessData, mockUserData, mockUserRole } from './mocks/User.mocks'; import { mockAccessData, mockUserData, mockUserRole } from './mocks/User.mocks';
import Users from './Users.component'; import Users from './Users.component';
import { UserPageTabs } from './Users.interface'; import { UserPageTabs } from './Users.interface';
@ -96,7 +97,19 @@ jest.mock(
); );
jest.mock('../../Glossary/GlossaryTerms/tabs/AssetsTabs.component', () => { jest.mock('../../Glossary/GlossaryTerms/tabs/AssetsTabs.component', () => {
return jest.fn().mockReturnValue(<p>AssetsTabs</p>); return jest.fn().mockImplementation((props) => {
React.useEffect(() => {
if (props.queryFilter === 'my-data') {
searchQuery({
searchIndex: ['all'] as any,
query: '*',
filters: props.queryFilter,
});
}
}, [props.queryFilter]);
return <p>AssetsTabs</p>;
});
}); });
jest.mock( 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', () => { describe('Test User Component', () => {
it('Should render user component', async () => { it('Should render user component', async () => {
await act(async () => { await act(async () => {
@ -357,4 +380,19 @@ describe('Test User Component', () => {
(await screen.findByTestId('access-token'))?.closest('.ant-tabs-tab') (await screen.findByTestId('access-token'))?.closest('.ant-tabs-tab')
).toHaveClass('ant-tabs-tab-disabled'); ).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(<Users userData={mockUserData} {...mockProp} />, {
wrapper: MemoryRouter,
});
});
const assetComponent = await screen.findByText('AssetsTabs');
expect(assetComponent).toBeInTheDocument();
expect(searchQuery).toHaveBeenCalledTimes(1);
});
}); });

View File

@ -20,12 +20,10 @@ import { useHistory, useParams } from 'react-router-dom';
import { ROUTES } from '../../../constants/constants'; import { ROUTES } from '../../../constants/constants';
import { useLimitStore } from '../../../context/LimitsProvider/useLimitsStore'; import { useLimitStore } from '../../../context/LimitsProvider/useLimitsStore';
import { EntityType } from '../../../enums/entity.enum'; import { EntityType } from '../../../enums/entity.enum';
import { SearchIndex } from '../../../enums/search.enum';
import { useAuth } from '../../../hooks/authHooks'; import { useAuth } from '../../../hooks/authHooks';
import { useApplicationStore } from '../../../hooks/useApplicationStore'; import { useApplicationStore } from '../../../hooks/useApplicationStore';
import useCustomLocation from '../../../hooks/useCustomLocation/useCustomLocation'; import useCustomLocation from '../../../hooks/useCustomLocation/useCustomLocation';
import { useFqn } from '../../../hooks/useFqn'; import { useFqn } from '../../../hooks/useFqn';
import { searchData } from '../../../rest/miscAPI';
import { restoreUser } from '../../../rest/userAPI'; import { restoreUser } from '../../../rest/userAPI';
import { DEFAULT_ENTITY_PERMISSION } from '../../../utils/PermissionsUtils'; import { DEFAULT_ENTITY_PERMISSION } from '../../../utils/PermissionsUtils';
import { getUserPath } from '../../../utils/RouterUtils'; import { getUserPath } from '../../../utils/RouterUtils';
@ -62,7 +60,6 @@ const Users = ({
const { tab: activeTab = UserPageTabs.ACTIVITY, subTab } = const { tab: activeTab = UserPageTabs.ACTIVITY, subTab } =
useParams<{ tab: UserPageTabs; subTab: ActivityFeedTabs }>(); useParams<{ tab: UserPageTabs; subTab: ActivityFeedTabs }>();
const { fqn: decodedUsername } = useFqn(); const { fqn: decodedUsername } = useFqn();
const [assetCount, setAssetCount] = useState<number>(0);
const { isAdminUser } = useAuth(); const { isAdminUser } = useAuth();
const history = useHistory(); const history = useHistory();
const location = useCustomLocation(); const location = useCustomLocation();
@ -81,16 +78,6 @@ const Users = ({
[decodedUsername] [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 initLimits = async () => {
const limits = await getResourceLimit('user', false); const limits = await getResourceLimit('user', false);
@ -140,7 +127,6 @@ const Users = ({
<Col flex="auto"> <Col flex="auto">
<div className="user-layout-scroll"> <div className="user-layout-scroll">
<AssetsTabs <AssetsTabs
assetCount={assetCount}
isSummaryPanelOpen={Boolean(previewAsset)} isSummaryPanelOpen={Boolean(previewAsset)}
permissions={{ ...DEFAULT_ENTITY_PERMISSION, Create: true }} permissions={{ ...DEFAULT_ENTITY_PERMISSION, Create: true }}
onAddAsset={() => history.push(ROUTES.EXPLORE)} onAddAsset={() => history.push(ROUTES.EXPLORE)}
@ -160,7 +146,7 @@ const Users = ({
)} )}
</Row> </Row>
), ),
[previewAsset, assetCount, handleAssetClick, setPreviewAsset, currentTab] [previewAsset, handleAssetClick, setPreviewAsset, currentTab]
); );
useEffect(() => { useEffect(() => {
if ( 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 () => { const handleRestoreUser = useCallback(async () => {
try { try {
await restoreUser(userData.id); await restoreUser(userData.id);