diff --git a/openmetadata-ui/src/main/resources/ui/cypress/e2e/AddNewService/postgres.spec.js b/openmetadata-ui/src/main/resources/ui/cypress/e2e/AddNewService/postgres.spec.js
index beafc7175bc..e703819eebf 100644
--- a/openmetadata-ui/src/main/resources/ui/cypress/e2e/AddNewService/postgres.spec.js
+++ b/openmetadata-ui/src/main/resources/ui/cypress/e2e/AddNewService/postgres.spec.js
@@ -161,11 +161,7 @@ describe('Postgres Ingestion', () => {
);
visitEntityDetailsPage(tableName, serviceName, 'tables');
verifyResponseStatusCode('@entityDetailsPage', 200);
- interceptURL(
- 'GET',
- '/api/v1/search/query?q=&index=query_search_index*',
- 'queriesTab'
- );
+ interceptURL('GET', '/api/v1/queries?*', 'queriesTab');
cy.get('[data-testid="Queries"]').should('be.visible').trigger('click');
verifyResponseStatusCode('@queriesTab', 200);
// Validate that the triggered query is visible in the queries container
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/QueryFilters/QueryFilters.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/QueryFilters/QueryFilters.component.tsx
index 9de4d98c662..c7d0170d5a4 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/QueryFilters/QueryFilters.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/QueryFilters/QueryFilters.component.tsx
@@ -15,6 +15,7 @@ import { Space, Typography } from 'antd';
import SearchDropdown from 'components/SearchDropdown/SearchDropdown';
import { SearchDropdownOption } from 'components/SearchDropdown/SearchDropdown.interface';
import { WILD_CARD_CHAR } from 'constants/char.constants';
+import { INITIAL_PAGING_VALUE } from 'constants/constants';
import { QUERY_PAGE_FILTER } from 'constants/Query.constant';
import { PROMISE_STATE } from 'enums/common.enum';
import { debounce, isEmpty } from 'lodash';
@@ -59,7 +60,6 @@ const QueryFilters = ({ onFilterChange }: QueryFiltersProps) => {
) => {
setSelectedFilter((pre) => {
const updatedFilter = { ...pre, [searchKey]: value };
-
onFilterChange(updatedFilter);
return updatedFilter;
@@ -111,13 +111,13 @@ const QueryFilters = ({ onFilterChange }: QueryFiltersProps) => {
}
};
- const debounceOnUserSearch = debounce(onUserSearch, 400);
- const debounceOnTeamSearch = debounce(onTeamSearch, 400);
+ const debounceOnUserSearch = debounce(onUserSearch, 500);
+ const debounceOnTeamSearch = debounce(onTeamSearch, 500);
const getInitialUserAndTeam = () => {
const promise = [
- getSearchedUsers(WILD_CARD_CHAR, 1),
- getSearchedTeams(WILD_CARD_CHAR, 1),
+ getSearchedUsers(WILD_CARD_CHAR, INITIAL_PAGING_VALUE),
+ getSearchedTeams(WILD_CARD_CHAR, INITIAL_PAGING_VALUE),
];
Promise.allSettled(promise)
.then((res) => {
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/TableQueries.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/TableQueries.interface.ts
index e6633edda2a..607dbf5cf3e 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/TableQueries.interface.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/TableQueries.interface.ts
@@ -62,10 +62,13 @@ export interface QueryFiltersProps {
onFilterChange: (value: QueryFiltersType) => void;
}
-export type QuerySearchParams = QueryFiltersType & {
- page: string;
- tableId: string;
- query: string;
+export type QuerySearchParams = {
+ queryFrom?: number;
+ after?: string;
+ tableId?: string;
+ query?: string;
+ user?: SearchDropdownOption[];
+ team?: SearchDropdownOption[];
};
export type QuerySearchShouldFilterType = {
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/TableQueries.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/TableQueries.test.tsx
index 317a132ef5f..2a345598f61 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/TableQueries.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/TableQueries.test.tsx
@@ -19,8 +19,8 @@ import {
} from '@testing-library/react';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
-import { searchQuery } from 'rest/searchAPI';
-import { MOCK_QUERIES_ES_DATA } from '../../mocks/Queries.mock';
+import { getQueriesList } from 'rest/queryAPI';
+import { MOCK_QUERIES, MOCK_QUERIES_ES_DATA } from '../../mocks/Queries.mock';
import TableQueries from './TableQueries';
import { TableQueriesProp } from './TableQueries.interface';
@@ -49,6 +49,14 @@ jest.mock('rest/searchAPI', () => ({
})
),
}));
+jest.mock('rest/queryAPI', () => ({
+ ...jest.requireActual('rest/queryAPI'),
+ getQueriesList: jest
+ .fn()
+ .mockImplementation(() =>
+ Promise.resolve({ data: MOCK_QUERIES, paging: { total: 2 } })
+ ),
+}));
jest.mock('components/PermissionProvider/PermissionProvider', () => ({
usePermissionProvider: jest
.fn()
@@ -89,9 +97,10 @@ describe('Test TableQueries Component', () => {
});
it('Error placeholder should display if there is no data', async () => {
- (searchQuery as jest.Mock).mockImplementationOnce(() =>
+ (getQueriesList as jest.Mock).mockImplementationOnce(() =>
Promise.resolve({
- hits: { hits: [], total: { value: 0 } },
+ data: [],
+ paging: { total: 0 },
})
);
render(, {
@@ -105,9 +114,10 @@ describe('Test TableQueries Component', () => {
});
it('If paging count is more than 10, pagination should be visible', async () => {
- (searchQuery as jest.Mock).mockImplementationOnce(() =>
+ (getQueriesList as jest.Mock).mockImplementationOnce(() =>
Promise.resolve({
- hits: { hits: [], total: { value: 11 } },
+ data: MOCK_QUERIES,
+ paging: { total: 11 },
})
);
render(, {
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/TableQueries.tsx b/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/TableQueries.tsx
index e3105b426ae..e9a61e2f0ae 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/TableQueries.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/TableQueries/TableQueries.tsx
@@ -38,10 +38,20 @@ import Qs from 'qs';
import React, { FC, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useHistory, useLocation } from 'react-router-dom';
-import { getQueryById, patchQueries, updateQueryVote } from 'rest/queryAPI';
+import {
+ getQueriesList,
+ getQueryById,
+ ListQueriesParams,
+ patchQueries,
+ updateQueryVote,
+} from 'rest/queryAPI';
import { searchQuery } from 'rest/searchAPI';
import { DEFAULT_ENTITY_PERMISSION } from 'utils/PermissionsUtils';
-import { createQueryFilter, parseSearchParams } from 'utils/Query/QueryUtils';
+import {
+ createQueryFilter,
+ parseSearchParams,
+ stringifySearchParams,
+} from 'utils/Query/QueryUtils';
import { showErrorToast } from '../../utils/ToastUtils';
import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder';
import Loader from '../Loader/Loader';
@@ -65,10 +75,13 @@ const TableQueries: FC = ({
const { searchParams, selectedFilters } = useMemo(() => {
const searchData = parseSearchParams(location.search);
- const selectedFilters = {
- user: searchData.user || [],
- team: searchData.team || [],
- };
+ const selectedFilters =
+ searchData.user || searchData.team
+ ? {
+ user: searchData.user || [],
+ team: searchData.team || [],
+ }
+ : undefined;
return {
searchParams: searchData,
@@ -87,13 +100,19 @@ const TableQueries: FC = ({
DEFAULT_ENTITY_PERMISSION
);
const [currentPage, setCurrentPage] = useState(
- Number(searchParams.page) || INITIAL_PAGING_VALUE
+ Number(searchParams.queryFrom) || INITIAL_PAGING_VALUE
);
- const [appliedFilter, setAppliedFilter] =
- useState(selectedFilters);
+ const [appliedFilter, setAppliedFilter] = useState<
+ QueryFiltersType | undefined
+ >(selectedFilters);
const { getEntityPermission } = usePermissionProvider();
+ const isNumberBasedPaging = useMemo(
+ () => Boolean(appliedFilter?.team.length || appliedFilter?.user.length),
+ [appliedFilter]
+ );
+
const fetchResourcePermission = async () => {
if (isUndefined(selectedQuery)) {
return;
@@ -165,6 +184,45 @@ const TableQueries: FC = ({
showErrorToast(error as AxiosError);
}
};
+ const fetchTableQuery = async (
+ params?: ListQueriesParams,
+ activePage?: number
+ ) => {
+ setIsLoading((pre) => ({ ...pre, query: true }));
+ try {
+ const queries = await getQueriesList({
+ ...params,
+ limit: PAGE_SIZE,
+ entityId: tableId,
+ fields: 'owner,votes,tags,queryUsedIn',
+ });
+ if (queries.data.length === 0) {
+ setIsError((pre) => ({ ...pre, page: true }));
+ } else {
+ setTableQueries(queries);
+ const selectedQueryData = searchParams.query
+ ? queries.data.find((query) => query.id === searchParams.query) ||
+ queries.data[0]
+ : queries.data[0];
+ setSelectedQuery(selectedQueryData);
+
+ history.push({
+ search: stringifySearchParams({
+ tableId,
+ after: params?.after,
+ query: selectedQueryData.id,
+ queryFrom: activePage,
+ }),
+ });
+ }
+ } catch (error) {
+ showErrorToast(error as AxiosError);
+ setIsError((pre) => ({ ...pre, page: true }));
+ } finally {
+ setIsLoading((pre) => ({ ...pre, query: false }));
+ }
+ };
+
const fetchFilterData = async (value?: QueryFiltersType, page?: number) => {
setIsLoading((pre) => ({ ...pre, query: true }));
const allFilter = flatMap(value);
@@ -196,13 +254,13 @@ const TableQueries: FC = ({
: queries[0];
setSelectedQuery(selectedQueryData);
+
history.push({
- search: Qs.stringify({
- ...searchParams,
+ search: stringifySearchParams({
...value,
- page: pageNumber,
tableId,
query: selectedQueryData.id,
+ queryFrom: pageNumber,
}),
});
if (queries.length === 0) {
@@ -215,10 +273,14 @@ const TableQueries: FC = ({
}
};
- const pagingHandler = (cursorType: string | number) => {
+ const pagingHandler = (cursorType: string | number, activePage?: number) => {
+ const { paging } = tableQueries;
if (isNumber(cursorType)) {
setCurrentPage(cursorType);
fetchFilterData(appliedFilter, cursorType);
+ } else {
+ fetchTableQuery({ [cursorType]: paging[cursorType] }, activePage);
+ activePage && setCurrentPage(activePage);
}
};
@@ -238,20 +300,27 @@ const TableQueries: FC = ({
useEffect(() => {
setIsLoading((pre) => ({ ...pre, page: true }));
if (tableId && !isTableDeleted) {
- fetchFilterData(selectedFilters, Number(searchParams.page)).finally(
- () => {
- setIsLoading((pre) => ({ ...pre, page: false }));
- }
- );
+ const initialFetch = selectedFilters
+ ? fetchFilterData(selectedFilters, Number(searchParams.queryFrom))
+ : fetchTableQuery({ after: searchParams?.after });
+ initialFetch.finally(() => {
+ setIsLoading((pre) => ({ ...pre, page: false }));
+ });
} else {
setIsLoading((pre) => ({ ...pre, page: false }));
}
}, [tableId]);
const onOwnerFilterChange = (value: QueryFiltersType) => {
+ const { team, user } = value;
+
setIsError((pre) => ({ ...pre, search: false }));
setAppliedFilter(value);
- fetchFilterData(value, INITIAL_PAGING_VALUE);
+ if (team.length || user.length) {
+ fetchFilterData(value, INITIAL_PAGING_VALUE);
+ } else {
+ fetchTableQuery();
+ }
};
if (isLoading.page) {
@@ -265,6 +334,30 @@ const TableQueries: FC = ({
);
}
+ const queryTabBody = isError.search ? (
+
+
+
+ ) : (
+ tableQueries.data.map((query) => (
+
+
+
+ ))
+ );
+
return (
@@ -276,39 +369,13 @@ const TableQueries: FC = ({
- {isLoading.query ? (
-
- ) : isError.search ? (
-
-
-
- ) : (
- tableQueries.data.map((query) => (
-
-
-
- ))
- )}
+ {isLoading.query ? : queryTabBody}
+
{tableQueries.paging.total > PAGE_SIZE && (
{
// need to typecast into QuerySearchParams as Qs.parse returns as "Qs.ParsedQs" Type object
) as unknown as QuerySearchParams;
};
+export const stringifySearchParams = (param: QuerySearchParams) => {
+ return Qs.stringify(param);
+};