From e52dbacfd8236d6bfa2d23f95a44675f27f76045 Mon Sep 17 00:00:00 2001 From: Shailesh Parmar Date: Thu, 28 Oct 2021 13:43:40 +0530 Subject: [PATCH] Fix: loading and entity count bug fix for Landing page (#955) * resolved infinite loading bug onClick of active tab for landing page * fix count and loading issue for landing page * move const value to MyData.const file * move MyDataHeader component to its seprate folder and miner bug fix in MyDataPage component * add error handler at page level --- .../components/MyData/MyData.component.tsx | 113 ++++++------------ .../src/components/MyData/MyData.interface.ts | 4 +- .../ui/src/components/MyData/MyData.test.tsx | 9 +- .../MyDataHeader.component.tsx} | 8 +- .../MyDataHeader.test.tsx | 2 +- .../ui/src/constants/Mydata.constants.ts | 10 ++ .../resources/ui/src/interface/types.d.ts | 9 +- .../pages/MyDataPage/MyDataPage.component.tsx | 70 ++++++++--- .../src/pages/MyDataPage/MyDataPage.test.tsx | 2 +- 9 files changed, 120 insertions(+), 107 deletions(-) rename catalog-rest-service/src/main/resources/ui/src/components/{my-data/MyDataHeader.tsx => MyDataHeader/MyDataHeader.component.tsx} (96%) rename catalog-rest-service/src/main/resources/ui/src/components/{my-data => MyDataHeader}/MyDataHeader.test.tsx (98%) diff --git a/catalog-rest-service/src/main/resources/ui/src/components/MyData/MyData.component.tsx b/catalog-rest-service/src/main/resources/ui/src/components/MyData/MyData.component.tsx index 679ea90cc50..0bf4f71c793 100644 --- a/catalog-rest-service/src/main/resources/ui/src/components/MyData/MyData.component.tsx +++ b/catalog-rest-service/src/main/resources/ui/src/components/MyData/MyData.component.tsx @@ -16,16 +16,13 @@ */ import { isEmpty } from 'lodash'; -import { Bucket, FormatedTableData, Sterm } from 'Models'; +import { FormatedTableData } from 'Models'; import React, { useEffect, useRef, useState } from 'react'; import { Ownership } from '../../enums/mydata.enum'; import { formatDataResponse } from '../../utils/APIUtils'; import { getCurrentUserId } from '../../utils/CommonUtils'; -import { getEntityCountByService } from '../../utils/ServiceUtils'; -import ErrorPlaceHolderES from '../common/error-with-placeholder/ErrorPlaceHolderES'; import PageContainer from '../containers/PageContainer'; -import Loader from '../Loader/Loader'; -import MyDataHeader from '../my-data/MyDataHeader'; +import MyDataHeader from '../MyDataHeader/MyDataHeader.component'; import RecentlyViewed from '../recently-viewed/RecentlyViewed'; import SearchedData from '../searched-data/SearchedData'; import { MyDataProps } from './MyData.interface'; @@ -35,21 +32,16 @@ const MyData: React.FC = ({ userDetails, searchResult, fetchData, - error, + entityCounts, }: MyDataProps): React.ReactElement => { const [data, setData] = useState>([]); const [currentPage, setCurrentPage] = useState(1); const [totalNumberOfValue, setTotalNumberOfValues] = useState(0); - const [isLoading, setIsLoading] = useState(true); const [isEntityLoading, setIsEntityLoading] = useState(true); const [currentTab, setCurrentTab] = useState(1); const [filter, setFilter] = useState(''); - const [aggregations, setAggregations] = useState>(); - const [searchIndex] = useState( - 'dashboard_search_index,topic_search_index,table_search_index,pipeline_search_index' - ); - const isMounted = useRef(false); - const setAssetCount = useRef(true); + + const isMounted = useRef(false); const getActiveTabClass = (tab: number) => { return tab === currentTab ? 'active' : ''; @@ -68,21 +60,6 @@ const MyData: React.FC = ({ return `${filter}:${getCurrentUserId()}`; }; - const fetchTableData = () => { - if (!isEntityLoading) { - setIsLoading(true); - } - - fetchData({ - queryString: '', - from: currentPage, - filters: filter ? getFilters() : '', - sortField: '', - sortOrder: '', - searchIndex: searchIndex, - }); - }; - const handleTabChange = (tab: number, filter: string) => { if (currentTab !== tab) { setIsEntityLoading(true); @@ -127,8 +104,16 @@ const MyData: React.FC = ({ }; useEffect(() => { - setAssetCount.current = !isMounted.current; - fetchTableData(); + if (isMounted.current) { + setIsEntityLoading(true); + fetchData({ + queryString: '', + from: currentPage, + filters: filter ? getFilters() : '', + sortField: '', + sortOrder: '', + }); + } }, [currentPage, filter]); useEffect(() => { @@ -137,22 +122,12 @@ const MyData: React.FC = ({ if (hits.length > 0) { setTotalNumberOfValues(searchResult.data.hits.total.value); setData(formatDataResponse(hits)); - if (setAssetCount.current) { - setAggregations(searchResult.data.aggregations); - setAssetCount.current = false; - } - setIsLoading(false); - setIsEntityLoading(false); } else { setData([]); setTotalNumberOfValues(0); - setIsLoading(false); - setIsEntityLoading(false); } - } else { - setIsLoading(false); - setIsEntityLoading(false); } + setIsEntityLoading(false); }, [searchResult]); useEffect(() => { @@ -160,41 +135,27 @@ const MyData: React.FC = ({ }, []); return ( - <> - {error ? ( - - ) : ( - <> - {isLoading ? ( - - ) : ( - -
- - {getTabs()} - 0 ? true : false} - totalValue={totalNumberOfValue}> - {currentTab === 1 ? : null} - -
-
- )} - - )} - + +
+ + {getTabs()} + 0 ? true : false} + totalValue={totalNumberOfValue}> + {currentTab === 1 ? : null} + +
+
); }; diff --git a/catalog-rest-service/src/main/resources/ui/src/components/MyData/MyData.interface.ts b/catalog-rest-service/src/main/resources/ui/src/components/MyData/MyData.interface.ts index f08efd15ee0..f70c2dbff3f 100644 --- a/catalog-rest-service/src/main/resources/ui/src/components/MyData/MyData.interface.ts +++ b/catalog-rest-service/src/main/resources/ui/src/components/MyData/MyData.interface.ts @@ -1,10 +1,10 @@ -import { SearchDataFunctionType, SearchResponse } from 'Models'; +import { EntityCounts, SearchDataFunctionType, SearchResponse } from 'Models'; import { User } from '../../generated/entity/teams/user'; export interface MyDataProps { countServices: number; userDetails: User; - error: string; searchResult: SearchResponse | undefined; fetchData: (value: SearchDataFunctionType) => void; + entityCounts: EntityCounts; } diff --git a/catalog-rest-service/src/main/resources/ui/src/components/MyData/MyData.test.tsx b/catalog-rest-service/src/main/resources/ui/src/components/MyData/MyData.test.tsx index 0c2a6b91a8d..efd64b70426 100644 --- a/catalog-rest-service/src/main/resources/ui/src/components/MyData/MyData.test.tsx +++ b/catalog-rest-service/src/main/resources/ui/src/components/MyData/MyData.test.tsx @@ -237,7 +237,7 @@ jest.mock('../../components/recently-viewed/RecentlyViewed', () => { return jest.fn().mockReturnValue(

RecentlyViewed

); }); -jest.mock('../../components/my-data/MyDataHeader', () => { +jest.mock('../MyDataHeader/MyDataHeader.component', () => { return jest.fn().mockReturnValue(

MyDataHeader

); }); @@ -258,7 +258,12 @@ describe('Test MyData page', () => { const { container } = render( { it('Component should render', () => { diff --git a/catalog-rest-service/src/main/resources/ui/src/constants/Mydata.constants.ts b/catalog-rest-service/src/main/resources/ui/src/constants/Mydata.constants.ts index 4fdb406b5d8..1091d9c4534 100644 --- a/catalog-rest-service/src/main/resources/ui/src/constants/Mydata.constants.ts +++ b/catalog-rest-service/src/main/resources/ui/src/constants/Mydata.constants.ts @@ -19,6 +19,16 @@ import { FilterObject } from 'Models'; import { getCurrentUserId } from '../utils/CommonUtils'; import { getFilterString } from '../utils/FilterUtils'; +export const myDataSearchIndex = + 'dashboard_search_index,topic_search_index,table_search_index,pipeline_search_index'; + +export const myDataEntityCounts = { + tableCount: 0, + topicCount: 0, + dashboardCount: 0, + pipelineCount: 0, +}; + export const myDataFilterType = [ { key: 'Owned', value: 'owner' }, { key: 'Following', value: 'followers' }, diff --git a/catalog-rest-service/src/main/resources/ui/src/interface/types.d.ts b/catalog-rest-service/src/main/resources/ui/src/interface/types.d.ts index 483fbda636a..7aa70132ab4 100644 --- a/catalog-rest-service/src/main/resources/ui/src/interface/types.d.ts +++ b/catalog-rest-service/src/main/resources/ui/src/interface/types.d.ts @@ -331,7 +331,14 @@ declare module 'Models' { filters: string; sortField: string; sortOrder: string; - searchIndex: string; + searchIndex?: string; + }; + + export type EntityCounts = { + tableCount: number; + topicCount: number; + dashboardCount: number; + pipelineCount: number; }; // topic interface start diff --git a/catalog-rest-service/src/main/resources/ui/src/pages/MyDataPage/MyDataPage.component.tsx b/catalog-rest-service/src/main/resources/ui/src/pages/MyDataPage/MyDataPage.component.tsx index 92b20a0223b..8cd744e98e6 100644 --- a/catalog-rest-service/src/main/resources/ui/src/pages/MyDataPage/MyDataPage.component.tsx +++ b/catalog-rest-service/src/main/resources/ui/src/pages/MyDataPage/MyDataPage.component.tsx @@ -16,25 +16,35 @@ */ import { AxiosError } from 'axios'; +import { isUndefined } from 'lodash'; import { observer } from 'mobx-react'; -import { SearchDataFunctionType, SearchResponse } from 'Models'; +import { EntityCounts, SearchDataFunctionType, SearchResponse } from 'Models'; import React, { useEffect, useState } from 'react'; import AppState from '../../AppState'; import { searchData } from '../../axiosAPIs/miscAPI'; +import ErrorPlaceHolderES from '../../components/common/error-with-placeholder/ErrorPlaceHolderES'; import Loader from '../../components/Loader/Loader'; import MyData from '../../components/MyData/MyData.component'; import { ERROR500, PAGE_SIZE } from '../../constants/constants'; +import { + myDataEntityCounts, + myDataSearchIndex, +} from '../../constants/Mydata.constants'; import useToastContext from '../../hooks/useToastContext'; -import { getAllServices } from '../../utils/ServiceUtils'; +import { + getAllServices, + getEntityCountByService, +} from '../../utils/ServiceUtils'; const MyDataPage = () => { const showToast = useToastContext(); const [error, setError] = useState(''); - const [countServices, setCountServices] = useState(0); + const [countServices, setCountServices] = useState(); const [isLoading, setIsLoading] = useState(true); const [searchResult, setSearchResult] = useState(); + const [entityCounts, setEntityCounts] = useState(); - const fetchData = (value: SearchDataFunctionType) => { + const fetchData = (value: SearchDataFunctionType, fetchService = false) => { searchData( value.queryString, value.from, @@ -42,10 +52,17 @@ const MyDataPage = () => { value.filters, value.sortField, value.sortOrder, - value.searchIndex + myDataSearchIndex ) .then((res: SearchResponse) => { setSearchResult(res); + if (isUndefined(entityCounts)) { + setEntityCounts( + getEntityCountByService( + res.data.aggregations?.['sterms#Service']?.buckets + ) + ); + } }) .catch((err: AxiosError) => { setError(err.response?.data?.responseMessage); @@ -53,28 +70,45 @@ const MyDataPage = () => { variant: 'error', body: err.response?.data?.responseMessage ?? ERROR500, }); + setEntityCounts(myDataEntityCounts); }); + if (fetchService) { + getAllServices() + .then((res) => setCountServices(res.length)) + .catch(() => setCountServices(0)); + } + setIsLoading(false); }; useEffect(() => { - getAllServices() - .then((res) => setCountServices(res.length)) - .catch(() => setCountServices(0)); - setIsLoading(false); + fetchData( + { + queryString: '', + from: 1, + filters: '', + sortField: '', + sortOrder: '', + }, + isUndefined(countServices) + ); }, []); return (
- {isLoading ? ( - + {countServices && entityCounts && !isLoading ? ( + error ? ( + + ) : ( + + ) ) : ( - + )}
); diff --git a/catalog-rest-service/src/main/resources/ui/src/pages/MyDataPage/MyDataPage.test.tsx b/catalog-rest-service/src/main/resources/ui/src/pages/MyDataPage/MyDataPage.test.tsx index eb9812b6724..eb32562cae8 100644 --- a/catalog-rest-service/src/main/resources/ui/src/pages/MyDataPage/MyDataPage.test.tsx +++ b/catalog-rest-service/src/main/resources/ui/src/pages/MyDataPage/MyDataPage.test.tsx @@ -19,7 +19,7 @@ import { findByTestId, render } from '@testing-library/react'; import React from 'react'; import MyDataPageComponent from './MyDataPage.component'; -jest.mock('../../components/LandingPage/MyData.component', () => { +jest.mock('../../components/MyData/MyData.component', () => { return jest.fn().mockReturnValue(

Mydata component

); });