fix(ui): all assets not showing on my data widget (#13703)

* changed the api call to fetch owned assets in my data widget

* fixed unit tests
This commit is contained in:
Aniket Katkar 2023-10-25 21:06:21 +05:30 committed by GitHub
parent de544d2dca
commit a72fcec57f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 95 additions and 72 deletions

View File

@ -17,15 +17,20 @@ import { observer } from 'mobx-react';
import React, { useCallback, useEffect, useState } from 'react'; import React, { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import AppState from '../../../AppState'; import {
import { getUserPath, ROUTES } from '../../../constants/constants'; getUserPath,
import { AssetsType } from '../../../enums/entity.enum'; INITIAL_PAGING_VALUE,
import { EntityReference } from '../../../generated/entity/type'; PAGE_SIZE,
ROUTES,
} from '../../../constants/constants';
import { SearchIndex } from '../../../enums/search.enum';
import { WidgetCommonProps } from '../../../pages/CustomizablePage/CustomizablePage.interface'; import { WidgetCommonProps } from '../../../pages/CustomizablePage/CustomizablePage.interface';
import { getUserById } from '../../../rest/userAPI'; import { searchData } from '../../../rest/miscAPI';
import { Transi18next } from '../../../utils/CommonUtils'; import { Transi18next } from '../../../utils/CommonUtils';
import { getEntityName } from '../../../utils/EntityUtils'; import { getEntityName } from '../../../utils/EntityUtils';
import { getEntityIcon, getEntityLink } from '../../../utils/TableUtils'; import { getEntityIcon, getEntityLink } from '../../../utils/TableUtils';
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
import { SourceType } from '../../searched-data/SearchedData.interface';
import EntityListSkeleton from '../../Skeleton/MyData/EntityListSkeleton/EntityListSkeleton.component'; import EntityListSkeleton from '../../Skeleton/MyData/EntityListSkeleton/EntityListSkeleton.component';
import './MyDataWidget.less'; import './MyDataWidget.less';
@ -35,34 +40,43 @@ const MyDataWidgetInternal = ({
widgetKey, widgetKey,
}: WidgetCommonProps) => { }: WidgetCommonProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const currentUserDetails = AppState.getCurrentUserDetails(); const { currentUser } = useAuthContext();
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const [data, setData] = useState<EntityReference[]>([]); const [data, setData] = useState<SourceType[]>([]);
const [totalOwnedAssetsCount, setTotalOwnedAssetsCount] = useState<number>(0); const [totalOwnedAssetsCount, setTotalOwnedAssetsCount] = useState<number>(0);
const fetchMyDataAssets = async () => { const fetchMyDataAssets = async () => {
if (!currentUserDetails || !currentUserDetails.id) { if (!isUndefined(currentUser)) {
return; setIsLoading(true);
} try {
setIsLoading(true); const teamsIds = (currentUser.teams ?? []).map((team) => team.id);
try { const mergedIds = [
const userData = await getUserById(currentUserDetails?.id, 'owns'); ...teamsIds.map((id) => `owner.id:${id}`),
`owner.id:${currentUser.id}`,
].join(' OR ');
if (userData) { const queryFilter = `(${mergedIds})`;
const includeData = Object.values(AssetsType); const res = await searchData(
const owns: EntityReference[] = userData.owns ?? []; '',
INITIAL_PAGING_VALUE,
const includedOwnsData = owns.filter((data) => PAGE_SIZE,
includeData.includes(data.type as AssetsType) queryFilter,
'',
'',
SearchIndex.ALL
); );
setData(includedOwnsData.slice(0, 8)); // Extract useful details from the Response
setTotalOwnedAssetsCount(includedOwnsData.length); const totalOwnedAssets = res?.data?.hits?.total.value ?? 0;
const ownedAssets = res?.data?.hits?.hits;
setData(ownedAssets.map((hit) => hit._source).slice(0, 8));
setTotalOwnedAssetsCount(totalOwnedAssets);
} catch (err) {
setData([]);
} finally {
setIsLoading(false);
} }
} catch (err) {
setData([]);
} finally {
setIsLoading(false);
} }
}; };
@ -72,7 +86,7 @@ const MyDataWidgetInternal = ({
useEffect(() => { useEffect(() => {
fetchMyDataAssets(); fetchMyDataAssets();
}, [currentUserDetails]); }, [currentUser]);
return ( return (
<Card className="my-data-widget-container card-widget" loading={isLoading}> <Card className="my-data-widget-container card-widget" loading={isLoading}>
@ -86,7 +100,7 @@ const MyDataWidgetInternal = ({
{data.length ? ( {data.length ? (
<Link <Link
data-testid="view-all-link" data-testid="view-all-link"
to={getUserPath(currentUserDetails?.name || '', 'mydata')}> to={getUserPath(currentUser?.name ?? '', 'mydata')}>
<span className="text-grey-muted font-normal text-xs"> <span className="text-grey-muted font-normal text-xs">
{t('label.view-all')}{' '} {t('label.view-all')}{' '}
<span data-testid="my-data-total-count"> <span data-testid="my-data-total-count">
@ -132,14 +146,14 @@ const MyDataWidgetInternal = ({
<Link <Link
className="" className=""
to={getEntityLink( to={getEntityLink(
item.type || '', item.entityType ?? '',
item.fullyQualifiedName as string item.fullyQualifiedName as string
)}> )}>
<Button <Button
className="entity-button flex-center p-0 m--ml-1" className="entity-button flex-center p-0 m--ml-1"
icon={ icon={
<div className="entity-button-icon m-r-xs"> <div className="entity-button-icon m-r-xs">
{getEntityIcon(item.type || '')} {getEntityIcon(item.entityType ?? '')}
</div> </div>
} }
type="text"> type="text">

View File

@ -13,15 +13,46 @@
import { act, render, screen } from '@testing-library/react'; import { act, render, screen } from '@testing-library/react';
import React from 'react'; import React from 'react';
import { MemoryRouter } from 'react-router-dom'; import { MemoryRouter } from 'react-router-dom';
import { getUserById } from '../../../rest/userAPI'; import { User } from '../../../generated/entity/teams/user';
import { searchData } from '../../../rest/miscAPI';
import { MyDataWidget } from './MyDataWidget.component'; import { MyDataWidget } from './MyDataWidget.component';
const userDetails = { const mockUserData: User = {
id: '123', name: 'testUser1',
email: 'testUser1@email.com',
id: '113',
}; };
jest.mock('../../../rest/userAPI', () => ({ const mockSearchAPIResponse = {
getUserById: jest.fn().mockImplementation(() => data: {
hits: {
hits: [
{
_source: {
id: '1',
name: 'test 1',
fullyQualifiedName: 'test-1',
type: 'table',
},
},
{
_source: {
id: '2',
name: 'test 2',
fullyQualifiedName: 'test-2',
type: 'table',
},
},
],
total: {
value: 2,
},
},
},
};
jest.mock('../../../rest/miscAPI', () => ({
searchData: jest.fn().mockImplementation(() =>
Promise.resolve({ Promise.resolve({
owns: [], owns: [],
}) })
@ -37,10 +68,10 @@ jest.mock('../../../utils/TableUtils', () => ({
getEntityIcon: jest.fn().mockImplementation((obj) => obj.name), getEntityIcon: jest.fn().mockImplementation((obj) => obj.name),
})); }));
jest.mock('./../../../AppState', () => ({ jest.mock('../../authentication/auth-provider/AuthProvider', () => ({
getCurrentUserDetails: jest.fn().mockImplementation(() => { useAuthContext: jest.fn(() => ({
return userDetails; currentUser: mockUserData,
}), })),
})); }));
jest.mock( jest.mock(
@ -56,7 +87,15 @@ describe('MyDataWidget component', () => {
render(<MyDataWidget widgetKey="widgetKey" />, { wrapper: MemoryRouter }); render(<MyDataWidget widgetKey="widgetKey" />, { wrapper: MemoryRouter });
}); });
expect(getUserById).toHaveBeenCalledWith('123', 'owns'); expect(searchData).toHaveBeenCalledWith(
'',
1,
10,
'(owner.id:113)',
'',
'',
'all'
);
}); });
it.skip('should render header', () => { it.skip('should render header', () => {
@ -84,23 +123,8 @@ describe('MyDataWidget component', () => {
}); });
it('should render view all for data present', async () => { it('should render view all for data present', async () => {
(getUserById as jest.Mock).mockImplementationOnce(() => (searchData as jest.Mock).mockImplementationOnce(() =>
Promise.resolve({ Promise.resolve(mockSearchAPIResponse)
owns: [
{
id: '1',
name: 'test 1',
fullyQualifiedName: 'test-1',
type: 'table',
},
{
id: '2',
name: 'test 2',
fullyQualifiedName: 'test-2',
type: 'table',
},
],
})
); );
act(() => { act(() => {
render( render(
@ -114,22 +138,7 @@ describe('MyDataWidget component', () => {
}); });
it('should render table names', async () => { it('should render table names', async () => {
(getUserById as jest.Mock).mockResolvedValueOnce({ (searchData as jest.Mock).mockResolvedValueOnce(mockSearchAPIResponse);
owns: [
{
id: '1',
name: 'test 1',
fullyQualifiedName: 'test-1',
type: 'table',
},
{
id: '2',
name: 'test 2',
fullyQualifiedName: 'test-2',
type: 'table',
},
],
});
act(() => { act(() => {
render( render(
<MemoryRouter> <MemoryRouter>