UI: Refector explore page (#925)

* UI: refactor explore page

* rename index to exlore.component for mock file and test file
This commit is contained in:
Shailesh Parmar 2021-10-26 13:19:57 +05:30 committed by GitHub
parent 42c4840f06
commit 6f46ebbfef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 545 additions and 253 deletions

View File

@ -16,21 +16,16 @@
*/
import { findAllByTestId, findByTestId, render } from '@testing-library/react';
import { SearchResponse } from 'Models';
import React from 'react';
import { MemoryRouter } from 'react-router';
import ExplorePage from './index';
import { mockResponse } from './index.mock';
import { mockResponse } from './exlore.mock';
import Explore from './Explore.component';
jest.mock('react-router-dom', () => ({
useHistory: jest.fn(),
useParams: jest.fn().mockImplementation(() => ({ searchQuery: '' })),
useLocation: jest.fn().mockImplementation(() => ({ search: '' })),
}));
jest.mock('../../axiosAPIs/miscAPI', () => ({
searchData: jest
.fn()
.mockImplementation(() => Promise.resolve({ data: mockResponse })),
}));
jest.mock('../../utils/FilterUtils', () => ({
getFilterString: jest.fn().mockImplementation(() => 'user.address'),
}));
@ -45,15 +40,47 @@ jest.mock('../../components/searched-data/SearchedData', () => {
));
});
jest.mock('../../hooks/useToastContext', () => {
return () => jest.fn();
});
const handleSearchText = jest.fn();
const updateTableCount = jest.fn();
const updateTopicCount = jest.fn();
const updateDashboardCount = jest.fn();
const updatePipelineCount = jest.fn();
const fetchData = jest.fn();
describe('Test Explore page', () => {
const mockSearchResult = {
resSearchResults: mockResponse as unknown as SearchResponse,
resAggServiceType: mockResponse as unknown as SearchResponse,
resAggTier: mockResponse as unknown as SearchResponse,
resAggTag: mockResponse as unknown as SearchResponse,
};
describe('Test Explore component', () => {
it('Component should render', async () => {
const { container } = render(<ExplorePage />, {
wrapper: MemoryRouter,
});
const { container } = render(
<Explore
error=""
fetchData={fetchData}
handleSearchText={handleSearchText}
isLoading={false}
searchQuery=""
searchResult={mockSearchResult}
searchText=""
tab=""
tabCounts={{
table: 15,
topic: 2,
dashboard: 8,
pipeline: 5,
}}
updateDashboardCount={updateDashboardCount}
updatePipelineCount={updatePipelineCount}
updateTableCount={updateTableCount}
updateTopicCount={updateTopicCount}
/>,
{
wrapper: MemoryRouter,
}
);
const pageContainer = await findByTestId(container, 'fluid-container');
const searchData = await findByTestId(container, 'search-data');
const wrappedContent = await findByTestId(container, 'wrapped-content');

View File

@ -15,20 +15,17 @@
* limitations under the License.
*/
import { AxiosError } from 'axios';
import classNames from 'classnames';
import { cloneDeep } from 'lodash';
import {
AggregationType,
Bucket,
FilterObject,
FormatedTableData,
SearchResponse,
} from 'Models';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useHistory, useLocation, useParams } from 'react-router-dom';
import { useHistory, useLocation } from 'react-router-dom';
import AppState from '../../AppState';
import { searchData } from '../../axiosAPIs/miscAPI';
import { Button } from '../../components/buttons/Button/Button';
import ErrorPlaceHolderES from '../../components/common/error-with-placeholder/ErrorPlaceHolderES';
import FacetFilter from '../../components/common/facetfilter/FacetFilter';
@ -36,7 +33,6 @@ import PageContainer from '../../components/containers/PageContainer';
import DropDownList from '../../components/dropdown/DropDownList';
import SearchedData from '../../components/searched-data/SearchedData';
import {
ERROR500,
getExplorePathWithSearch,
PAGE_SIZE,
tableSortingFields,
@ -44,16 +40,14 @@ import {
} from '../../constants/constants';
import { SearchIndex } from '../../enums/search.enum';
import { usePrevious } from '../../hooks/usePrevious';
import useToastContext from '../../hooks/useToastContext';
import { getAggregationList } from '../../utils/AggregationUtils';
import { formatDataResponse } from '../../utils/APIUtils';
import { getCountBadge } from '../../utils/CommonUtils';
import { getFilterString } from '../../utils/FilterUtils';
import { getTotalEntityCountByService } from '../../utils/ServiceUtils';
import { dropdownIcon as DropDownIcon } from '../../utils/svgconstant';
import SVGIcons from '../../utils/SvgUtils';
import { getAggrWithDefaultValue, tabsInfo } from './explore.constants';
import { Params } from './explore.interface';
import { ExploreProps } from './explore.interface';
const getQueryParam = (urlSearchQuery = ''): FilterObject => {
const arrSearchQuery = urlSearchQuery
@ -125,36 +119,43 @@ const getCurrentIndex = (tab: string) => {
return currentIndex;
};
const ExplorePage: React.FC = (): React.ReactElement => {
const Explore: React.FC<ExploreProps> = ({
tabCounts,
searchText,
tab,
searchQuery,
searchResult,
error,
isLoading,
handleSearchText,
fetchData,
updateTableCount,
updateTopicCount,
updateDashboardCount,
updatePipelineCount,
}: ExploreProps) => {
const location = useLocation();
const history = useHistory();
const filterObject: FilterObject = {
...{ tags: [], service: [], tier: [] },
...getQueryParam(location.search),
};
const showToast = useToastContext();
const { searchQuery, tab } = useParams<Params>();
const [searchText, setSearchText] = useState<string>(searchQuery || '');
const [data, setData] = useState<Array<FormatedTableData>>([]);
const [filters, setFilters] = useState<FilterObject>(filterObject);
const [currentPage, setCurrentPage] = useState<number>(1);
const [totalNumberOfValue, setTotalNumberOfValues] = useState<number>(0);
const [aggregations, setAggregations] = useState<Array<AggregationType>>([]);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [searchTag, setSearchTag] = useState<string>(location.search);
const [error, setError] = useState<string>('');
const [fieldListVisible, setFieldListVisible] = useState<boolean>(false);
const [sortField, setSortField] = useState<string>('');
const [sortOrder, setSortOrder] = useState<string>('desc');
const [searchIndex, setSearchIndex] = useState<string>(getCurrentIndex(tab));
const [currentTab, setCurrentTab] = useState<number>(getCurrentTab(tab));
const [tableCount, setTableCount] = useState<number>(0);
const [topicCount, setTopicCount] = useState<number>(0);
const [dashboardCount, setDashboardCount] = useState<number>(0);
const [pipelineCount, setPipelineCount] = useState<number>(0);
const [fieldList, setFieldList] =
useState<Array<{ name: string; value: string }>>(tableSortingFields);
const isMounting = useRef(true);
const forceSetAgg = useRef(false);
const previsouIndex = usePrevious(searchIndex);
const handleSelectedFilter = (
@ -238,19 +239,19 @@ const ExplorePage: React.FC = (): React.ReactElement => {
const setCount = (count = 0) => {
switch (searchIndex) {
case SearchIndex.TABLE:
setTableCount(count);
updateTableCount(count);
break;
case SearchIndex.DASHBOARD:
setDashboardCount(count);
updateDashboardCount(count);
break;
case SearchIndex.TOPIC:
setTopicCount(count);
updateTopicCount(count);
break;
case SearchIndex.PIPELINE:
setPipelineCount(count);
updatePipelineCount(count);
break;
default:
@ -258,176 +259,47 @@ const ExplorePage: React.FC = (): React.ReactElement => {
}
};
const fetchCounts = () => {
const emptyValue = '';
const tableCount = searchData(
searchText,
0,
0,
emptyValue,
emptyValue,
emptyValue,
SearchIndex.TABLE
);
const topicCount = searchData(
searchText,
0,
0,
emptyValue,
emptyValue,
emptyValue,
SearchIndex.TOPIC
);
const dashboardCount = searchData(
searchText,
0,
0,
emptyValue,
emptyValue,
emptyValue,
SearchIndex.DASHBOARD
);
const pipelineCount = searchData(
searchText,
0,
0,
emptyValue,
emptyValue,
emptyValue,
SearchIndex.PIPELINE
);
Promise.allSettled([
tableCount,
topicCount,
dashboardCount,
pipelineCount,
]).then(
([
table,
topic,
dashboard,
pipeline,
]: PromiseSettledResult<SearchResponse>[]) => {
setTableCount(
table.status === 'fulfilled'
? getTotalEntityCountByService(
table.value.data.aggregations?.['sterms#Service']
?.buckets as Bucket[]
)
: 0
);
setTopicCount(
topic.status === 'fulfilled'
? getTotalEntityCountByService(
topic.value.data.aggregations?.['sterms#Service']
?.buckets as Bucket[]
)
: 0
);
setDashboardCount(
dashboard.status === 'fulfilled'
? getTotalEntityCountByService(
dashboard.value.data.aggregations?.['sterms#Service']
?.buckets as Bucket[]
)
: 0
);
setPipelineCount(
pipeline.status === 'fulfilled'
? getTotalEntityCountByService(
pipeline.value.data.aggregations?.['sterms#Service']
?.buckets as Bucket[]
)
: 0
);
}
);
};
const fetchTableData = () => {
const fetchParams = [
{
queryString: searchText,
from: currentPage,
size: PAGE_SIZE,
filters: getFilterString(filters),
sortField: sortField,
sortOrder: sortOrder,
searchIndex: searchIndex,
},
{
queryString: searchText,
from: currentPage,
size: 0,
filters: getFilterString(filters, ['service']),
sortField: sortField,
sortOrder: sortOrder,
searchIndex: searchIndex,
},
{
queryString: searchText,
from: currentPage,
size: 0,
filters: getFilterString(filters, ['tier']),
sortField: sortField,
sortOrder: sortOrder,
searchIndex: searchIndex,
},
{
queryString: searchText,
from: currentPage,
size: 0,
filters: getFilterString(filters, ['tags']),
sortField: sortField,
sortOrder: sortOrder,
searchIndex: searchIndex,
},
];
const fetchTableData = (forceSetAgg: boolean) => {
setIsLoading(true);
const searchResults = searchData(
searchText,
currentPage,
PAGE_SIZE,
getFilterString(filters),
sortField,
sortOrder,
searchIndex
);
const serviceTypeAgg = searchData(
searchText,
currentPage,
0,
getFilterString(filters, ['service']),
sortField,
sortOrder,
searchIndex
);
const tierAgg = searchData(
searchText,
currentPage,
0,
getFilterString(filters, ['tier']),
sortField,
sortOrder,
searchIndex
);
const tagAgg = searchData(
searchText,
currentPage,
0,
getFilterString(filters, ['tags']),
sortField,
sortOrder,
searchIndex
);
Promise.all([searchResults, serviceTypeAgg, tierAgg, tagAgg])
.then(
([
resSearchResults,
resAggServiceType,
resAggTier,
resAggTag,
]: Array<SearchResponse>) => {
updateSearchResults(resSearchResults);
setCount(resSearchResults.data.hits.total.value);
if (forceSetAgg) {
setAggregations(
resSearchResults.data.hits.hits.length > 0
? getAggregationList(resSearchResults.data.aggregations)
: []
);
} else {
const aggServiceType = getAggregationList(
resAggServiceType.data.aggregations,
'service'
);
const aggTier = getAggregationList(
resAggTier.data.aggregations,
'tier'
);
const aggTag = getAggregationList(
resAggTag.data.aggregations,
'tags'
);
updateAggregationCount([...aggServiceType, ...aggTier, ...aggTag]);
}
setIsLoading(false);
}
)
.catch((err: AxiosError) => {
setError(err.response?.data?.responseMessage);
showToast({
variant: 'error',
body: err.response?.data?.responseMessage ?? ERROR500,
});
setIsLoading(false);
});
fetchData(fetchParams);
};
const getFacetedFilter = () => {
@ -515,13 +387,13 @@ const ExplorePage: React.FC = (): React.ReactElement => {
const getTabCount = (index: string) => {
switch (index) {
case SearchIndex.TABLE:
return getCountBadge(tableCount);
return getCountBadge(tabCounts.table);
case SearchIndex.TOPIC:
return getCountBadge(topicCount);
return getCountBadge(tabCounts.topic);
case SearchIndex.DASHBOARD:
return getCountBadge(dashboardCount);
return getCountBadge(tabCounts.dashboard);
case SearchIndex.PIPELINE:
return getCountBadge(pipelineCount);
return getCountBadge(tabCounts.pipeline);
default:
return getCountBadge();
}
@ -543,23 +415,23 @@ const ExplorePage: React.FC = (): React.ReactElement => {
<div className="tw-mb-3 tw--mt-4">
<nav className="tw-flex tw-flex-row tw-gh-tabs-container tw-px-4 tw-justify-between">
<div>
{tabsInfo.map((tab, index) => (
{tabsInfo.map((tabDetail, index) => (
<button
className={`tw-pb-2 tw-px-4 tw-gh-tabs ${getActiveTabClass(
tab.tab
tabDetail.tab
)}`}
data-testid="tab"
key={index}
onClick={() => {
onTabChange(tab.tab);
onTabChange(tabDetail.tab);
}}>
<SVGIcons
alt="icon"
className="tw-h-4 tw-w-4 tw-mr-2"
icon={tab.icon}
icon={tabDetail.icon}
/>
{tab.label}
{getTabCount(tab.index)}
{tabDetail.label}
{getTabCount(tabDetail.index)}
</button>
))}
</div>
@ -570,7 +442,7 @@ const ExplorePage: React.FC = (): React.ReactElement => {
};
useEffect(() => {
setSearchText(searchQuery || '');
handleSearchText(searchQuery || '');
setCurrentPage(1);
}, [searchQuery]);
@ -579,7 +451,6 @@ const ExplorePage: React.FC = (): React.ReactElement => {
setFieldList(tabsInfo[getCurrentTab(tab) - 1].sortingFields);
setSortField(tabsInfo[getCurrentTab(tab) - 1].sortField);
setSortOrder('desc');
setError('');
setCurrentTab(getCurrentTab(tab));
setSearchIndex(getCurrentIndex(tab));
setCurrentPage(1);
@ -592,18 +463,47 @@ const ExplorePage: React.FC = (): React.ReactElement => {
}, [searchText, filters]);
useEffect(() => {
fetchTableData(true);
forceSetAgg.current = true;
fetchTableData();
}, [searchText, searchIndex]);
useEffect(() => {
if (!isMounting.current && previsouIndex === getCurrentIndex(tab)) {
fetchTableData(false);
if (searchResult) {
updateSearchResults(searchResult.resSearchResults);
setCount(searchResult.resSearchResults.data.hits.total.value);
if (forceSetAgg.current) {
setAggregations(
searchResult.resSearchResults.data.hits.hits.length > 0
? getAggregationList(
searchResult.resSearchResults.data.aggregations
)
: []
);
} else {
const aggServiceType = getAggregationList(
searchResult.resAggServiceType.data.aggregations,
'service'
);
const aggTier = getAggregationList(
searchResult.resAggTier.data.aggregations,
'tier'
);
const aggTag = getAggregationList(
searchResult.resAggTag.data.aggregations,
'tags'
);
updateAggregationCount([...aggServiceType, ...aggTier, ...aggTag]);
}
}
}, [currentPage, filters, sortField, sortOrder]);
}, [searchResult]);
useEffect(() => {
fetchCounts();
}, [searchText]);
if (!isMounting.current && previsouIndex === getCurrentIndex(tab)) {
forceSetAgg.current = false;
fetchTableData();
}
}, [currentPage, filters, sortField, sortOrder]);
// alwyas Keep this useEffect at the end...
useEffect(() => {
@ -647,4 +547,4 @@ const ExplorePage: React.FC = (): React.ReactElement => {
);
};
export default ExplorePage;
export default Explore;

View File

@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-disable @typescript-eslint/camelcase */
const todayData = [
{
@ -209,17 +210,75 @@ export const entitiesData = [
export const tiers = ['Tier1', 'Tier2', 'Tier3', 'Tier4', 'Tier5'];
export const mockResponse = {
hits: {
data: {
hits: {
tableId: '09ac866c-a18d-4470-abc8-52deed3d90d6',
database: 'dwh',
tableName: 'fact_sale',
serviceName: 'MYSQL',
description: 'this is the table to hold data on fact_sale',
tableType: 'null',
total: {
value: 15,
relation: 'eq',
},
max_score: 5,
hits: [
{
_index: 'table_search_index',
_type: '_doc',
_id: 'b5860f51-a197-48c8-9506-ee67da190d83',
_score: 5,
_source: {
table_id: 'b5860f51-a197-48c8-9506-ee67da190d83',
database: 'bigquery.shopify',
service: 'bigquery',
service_type: 'BigQuery',
table_name: 'dim_address',
suggest: [
{
input: ['bigquery.shopify.dim_address'],
weight: 5,
},
{
input: ['dim_address'],
weight: 10,
},
],
description:
'This dimension table contains the billing and shipping addresses of customers. You can join this table.',
table_type: 'Regular',
last_updated_timestamp: 1634886627,
column_names: ['address_id', 'shop_id'],
column_descriptions: [
'Unique identifier for the address.',
'The ID of the store. This column is a foreign key reference to the shop_id column in the dim_shop table.',
],
tags: [],
fqdn: 'bigquery.shopify.dim_address',
tier: null,
schema_description: null,
owner: '',
followers: [],
},
},
],
},
total: {
value: 128,
aggregations: {
'sterms#Tier': {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [],
},
'sterms#Service': {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{
key: 'BigQuery',
doc_count: 15,
},
],
},
'sterms#Tags': {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [],
},
},
},
};

View File

@ -0,0 +1,76 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { SearchResponse } from 'Models';
export type Params = {
searchQuery: string;
tab: string;
};
export type Service = {
collection: {
name: string;
documentation: string;
href: string;
};
};
export type Team = {
id: string;
name: string;
displayName: string;
description: string;
href: string;
};
export type ExploreSearchData = {
resSearchResults: SearchResponse;
resAggServiceType: SearchResponse;
resAggTier: SearchResponse;
resAggTag: SearchResponse;
};
export interface FetchData {
queryString: string;
from: number;
size: number;
filters: string;
sortField: string;
sortOrder: string;
searchIndex: string;
}
export interface ExploreProps {
tabCounts: {
table: number;
topic: number;
dashboard: number;
pipeline: number;
};
searchText: string;
tab: string;
error: string;
isLoading: boolean;
searchQuery: string;
handleSearchText: (text: string) => void;
updateTableCount: (count: number) => void;
updateTopicCount: (count: number) => void;
updateDashboardCount: (count: number) => void;
updatePipelineCount: (count: number) => void;
fetchData: (value: FetchData[]) => void;
searchResult: ExploreSearchData | undefined;
}

View File

@ -15,22 +15,24 @@
* limitations under the License.
*/
export type Params = {
searchQuery: string;
tab: string;
};
import { findByTestId, render } from '@testing-library/react';
import React from 'react';
import ExplorePage from './ExplorePage.component';
export type Service = {
collection: {
name: string;
documentation: string;
href: string;
};
};
export type Team = {
id: string;
name: string;
displayName: string;
description: string;
href: string;
};
jest.mock('react-router-dom', () => ({
useParams: jest.fn().mockImplementation(() => ({ searchQuery: '' })),
}));
jest.mock('../../components/Explore/Explore.component', () => {
return jest.fn().mockReturnValue(<p>Explore Component</p>);
});
describe('Test Explore page', () => {
it('Page Should render', async () => {
const { container } = render(<ExplorePage />);
const explorePage = await findByTestId(container, 'explore-page');
expect(explorePage).toBeInTheDocument();
});
});

View File

@ -0,0 +1,228 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AxiosError } from 'axios';
import { Bucket, SearchResponse } from 'Models';
import React, { FunctionComponent, useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { searchData } from '../../axiosAPIs/miscAPI';
import Explore from '../../components/Explore/Explore.component';
import {
ExploreSearchData,
FetchData,
Params,
} from '../../components/Explore/explore.interface';
import Loader from '../../components/Loader/Loader';
import { ERROR500 } from '../../constants/constants';
import { SearchIndex } from '../../enums/search.enum';
import useToastContext from '../../hooks/useToastContext';
import { getTotalEntityCountByService } from '../../utils/ServiceUtils';
const ExplorePage: FunctionComponent = () => {
const showToast = useToastContext();
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string>('');
const { searchQuery, tab } = useParams<Params>();
const [searchText, setSearchText] = useState<string>(searchQuery || '');
const [tableCount, setTableCount] = useState<number>(0);
const [topicCount, setTopicCount] = useState<number>(0);
const [dashboardCount, setDashboardCount] = useState<number>(0);
const [pipelineCount, setPipelineCount] = useState<number>(0);
const [searchResult, setSearchResult] = useState<ExploreSearchData>();
const handleSearchText = (text: string) => {
setSearchText(text);
};
const handleTableCount = (count: number) => {
setTableCount(count);
};
const handleTopicCount = (count: number) => {
setTopicCount(count);
};
const handleDashboardCount = (count: number) => {
setDashboardCount(count);
};
const handlePipelineCount = (count: number) => {
setPipelineCount(count);
};
const fetchCounts = () => {
const emptyValue = '';
const tableCount = searchData(
searchText,
0,
0,
emptyValue,
emptyValue,
emptyValue,
SearchIndex.TABLE
);
const topicCount = searchData(
searchText,
0,
0,
emptyValue,
emptyValue,
emptyValue,
SearchIndex.TOPIC
);
const dashboardCount = searchData(
searchText,
0,
0,
emptyValue,
emptyValue,
emptyValue,
SearchIndex.DASHBOARD
);
const pipelineCount = searchData(
searchText,
0,
0,
emptyValue,
emptyValue,
emptyValue,
SearchIndex.PIPELINE
);
Promise.allSettled([
tableCount,
topicCount,
dashboardCount,
pipelineCount,
]).then(
([
table,
topic,
dashboard,
pipeline,
]: PromiseSettledResult<SearchResponse>[]) => {
setTableCount(
table.status === 'fulfilled'
? getTotalEntityCountByService(
table.value.data.aggregations?.['sterms#Service']
?.buckets as Bucket[]
)
: 0
);
setTopicCount(
topic.status === 'fulfilled'
? getTotalEntityCountByService(
topic.value.data.aggregations?.['sterms#Service']
?.buckets as Bucket[]
)
: 0
);
setDashboardCount(
dashboard.status === 'fulfilled'
? getTotalEntityCountByService(
dashboard.value.data.aggregations?.['sterms#Service']
?.buckets as Bucket[]
)
: 0
);
setPipelineCount(
pipeline.status === 'fulfilled'
? getTotalEntityCountByService(
pipeline.value.data.aggregations?.['sterms#Service']
?.buckets as Bucket[]
)
: 0
);
}
);
};
const fetchData = (value: FetchData[]) => {
setIsLoading(true);
const promiseValue = value.map((d) => {
return searchData(
d.queryString,
d.from,
d.size,
d.filters,
d.sortField,
d.sortOrder,
d.searchIndex
);
});
Promise.all(promiseValue)
.then(
([
resSearchResults,
resAggServiceType,
resAggTier,
resAggTag,
]: Array<SearchResponse>) => {
setSearchResult({
resSearchResults,
resAggServiceType,
resAggTier,
resAggTag,
});
}
)
.catch((err: AxiosError) => {
setError(err.response?.data?.responseMessage);
showToast({
variant: 'error',
body: err.response?.data?.responseMessage ?? ERROR500,
});
});
setIsLoading(false);
};
useEffect(() => {
fetchCounts();
}, [searchText]);
return (
<div data-testid="explore-page">
{isLoading ? (
<Loader />
) : (
<Explore
error={error}
fetchData={fetchData}
handleSearchText={handleSearchText}
isLoading={isLoading}
searchQuery={searchQuery}
searchResult={searchResult}
searchText={searchText}
tab={tab}
tabCounts={{
table: tableCount,
topic: topicCount,
dashboard: dashboardCount,
pipeline: pipelineCount,
}}
updateDashboardCount={handleDashboardCount}
updatePipelineCount={handlePipelineCount}
updateTableCount={handleTableCount}
updateTopicCount={handleTopicCount}
/>
)}
</div>
);
};
export default ExplorePage;

View File

@ -24,7 +24,7 @@ import { ROUTES } from '../constants/constants';
import MyDashBoardPage from '../pages/dashboard-details';
import DatabaseDetails from '../pages/database-details/index';
import DatasetDetailsPage from '../pages/DatasetDetailsPage/DatasetDetailsPage.component';
import ExplorePage from '../pages/explore';
import ExplorePage from '../pages/explore/ExplorePage.component';
import MyDataPage from '../pages/my-data';
import MyPipelinePage from '../pages/Pipeline-details';
import ReportsPage from '../pages/reports';