mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-02 12:26:42 +00:00
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:
parent
7035c9e107
commit
c729bd51ea
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user