mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-27 09:55:36 +00:00
added sorting on explore page (#279)
* added sorting on explore page * minor change * chnaged filter position * addressing review comment
This commit is contained in:
parent
54358c959d
commit
4fe33d45ce
@ -23,7 +23,9 @@ export const searchData: Function = (
|
|||||||
queryString: string,
|
queryString: string,
|
||||||
from: number,
|
from: number,
|
||||||
size: number,
|
size: number,
|
||||||
filters: string
|
filters: string,
|
||||||
|
sortField: string,
|
||||||
|
sortOrder: string
|
||||||
): Promise<AxiosResponse> => {
|
): Promise<AxiosResponse> => {
|
||||||
const start = (from - 1) * size;
|
const start = (from - 1) * size;
|
||||||
const query = queryString ? `*${queryString}*` : '*';
|
const query = queryString ? `*${queryString}*` : '*';
|
||||||
@ -31,7 +33,9 @@ export const searchData: Function = (
|
|||||||
return APIClient.get(
|
return APIClient.get(
|
||||||
`/search/query?q=${query}${
|
`/search/query?q=${query}${
|
||||||
filters ? ` AND ${filters}` : ''
|
filters ? ` AND ${filters}` : ''
|
||||||
}&from=${start}&size=${size}`
|
}&from=${start}&size=${size}${sortField ? `&sort_field=${sortField}` : ''}${
|
||||||
|
sortOrder ? `&sort_order=${sortOrder}` : ''
|
||||||
|
}`
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ const DropDownList: FunctionComponent<DropDownListProp> = ({
|
|||||||
<span
|
<span
|
||||||
aria-disabled={item.disabled as boolean}
|
aria-disabled={item.disabled as boolean}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'tw-text-gray-700 tw-block tw-px-4 tw-py-2 tw-text-sm hover:tw-bg-body-hover',
|
'tw-text-gray-700 tw-block tw-px-4 tw-py-2 tw-text-sm hover:tw-bg-body-hover tw-cursor-pointer',
|
||||||
!isNil(value) && item.value === value ? 'tw-bg-primary-lite' : null
|
!isNil(value) && item.value === value ? 'tw-bg-primary-lite' : null
|
||||||
)}
|
)}
|
||||||
id={`menu-item-${index}`}
|
id={`menu-item-${index}`}
|
||||||
@ -89,7 +89,7 @@ const DropDownList: FunctionComponent<DropDownListProp> = ({
|
|||||||
aria-labelledby="menu-button"
|
aria-labelledby="menu-button"
|
||||||
aria-orientation="vertical"
|
aria-orientation="vertical"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'dropdown-list',
|
'dropdown-list tw-mt-0.5',
|
||||||
horzPosRight ? 'dd-horz-right' : 'dd-horz-left'
|
horzPosRight ? 'dd-horz-right' : 'dd-horz-left'
|
||||||
)}
|
)}
|
||||||
role="menu">
|
role="menu">
|
||||||
|
@ -48,6 +48,21 @@ export const tiers = [
|
|||||||
{ key: 'Tier.Tier5', doc_count: 0 },
|
{ key: 'Tier.Tier5', doc_count: 0 },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const sortingFields = [
|
||||||
|
{ name: 'Weekly Stats', value: 'weekly_stats' },
|
||||||
|
{ name: 'Daily Stats', value: 'daily_stats' },
|
||||||
|
{ name: 'Monthly Stats', value: 'monthly_stats' },
|
||||||
|
{
|
||||||
|
name: 'Last Updated Timestamp',
|
||||||
|
value: 'last_updated_timestamp',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const sortingOrder = [
|
||||||
|
{ name: 'Ascending', value: 'asc' },
|
||||||
|
{ name: 'Descending', value: 'desc' },
|
||||||
|
];
|
||||||
|
|
||||||
export const ROUTES = {
|
export const ROUTES = {
|
||||||
HOME: '/',
|
HOME: '/',
|
||||||
CALLBACK: '/callback',
|
CALLBACK: '/callback',
|
||||||
|
@ -26,14 +26,23 @@ import {
|
|||||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { useLocation, useParams } from 'react-router-dom';
|
import { useLocation, useParams } from 'react-router-dom';
|
||||||
import { searchData } from '../../axiosAPIs/miscAPI';
|
import { searchData } from '../../axiosAPIs/miscAPI';
|
||||||
|
import { Button } from '../../components/buttons/Button/Button';
|
||||||
import Error from '../../components/common/error/Error';
|
import Error from '../../components/common/error/Error';
|
||||||
import FacetFilter from '../../components/common/facetfilter/FacetFilter';
|
import FacetFilter from '../../components/common/facetfilter/FacetFilter';
|
||||||
|
import DropDownList from '../../components/dropdown/DropDownList';
|
||||||
import SearchedData from '../../components/searched-data/SearchedData';
|
import SearchedData from '../../components/searched-data/SearchedData';
|
||||||
import { ERROR404, ERROR500, PAGE_SIZE } from '../../constants/constants';
|
import {
|
||||||
|
ERROR404,
|
||||||
|
ERROR500,
|
||||||
|
PAGE_SIZE,
|
||||||
|
sortingFields,
|
||||||
|
sortingOrder,
|
||||||
|
} from '../../constants/constants';
|
||||||
import useToastContext from '../../hooks/useToastContext';
|
import useToastContext from '../../hooks/useToastContext';
|
||||||
import { getAggregationList } from '../../utils/AggregationUtils';
|
import { getAggregationList } from '../../utils/AggregationUtils';
|
||||||
import { formatDataResponse } from '../../utils/APIUtils';
|
import { formatDataResponse } from '../../utils/APIUtils';
|
||||||
import { getFilterString } from '../../utils/FilterUtils';
|
import { getFilterString } from '../../utils/FilterUtils';
|
||||||
|
import { dropdownIcon as DropDownIcon } from '../../utils/svgconstant';
|
||||||
import { getAggrWithDefaultValue } from './explore.constants';
|
import { getAggrWithDefaultValue } from './explore.constants';
|
||||||
import { Params } from './explore.interface';
|
import { Params } from './explore.interface';
|
||||||
|
|
||||||
@ -75,6 +84,10 @@ const ExplorePage: React.FC = (): React.ReactElement => {
|
|||||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||||
const [searchTag, setSearchTag] = useState<string>(location.search);
|
const [searchTag, setSearchTag] = useState<string>(location.search);
|
||||||
const [error, setError] = useState<string>('');
|
const [error, setError] = useState<string>('');
|
||||||
|
const [fieldListVisible, setFieldListVisible] = useState<boolean>(false);
|
||||||
|
const [orderListVisible, setOrderListVisible] = useState<boolean>(false);
|
||||||
|
const [sortField, setSortField] = useState<string>(sortingFields[3].value);
|
||||||
|
const [sortOrder, setSortOrder] = useState<string>(sortingOrder[1].value);
|
||||||
const isMounting = useRef(true);
|
const isMounting = useRef(true);
|
||||||
|
|
||||||
const handleSelectedFilter = (
|
const handleSelectedFilter = (
|
||||||
@ -162,25 +175,33 @@ const ExplorePage: React.FC = (): React.ReactElement => {
|
|||||||
searchText,
|
searchText,
|
||||||
currentPage,
|
currentPage,
|
||||||
PAGE_SIZE,
|
PAGE_SIZE,
|
||||||
getFilterString(filters)
|
getFilterString(filters),
|
||||||
|
sortField,
|
||||||
|
sortOrder
|
||||||
);
|
);
|
||||||
const serviceTypeAgg = searchData(
|
const serviceTypeAgg = searchData(
|
||||||
searchText,
|
searchText,
|
||||||
currentPage,
|
currentPage,
|
||||||
0,
|
0,
|
||||||
getFilterString(filters, ['service type'])
|
getFilterString(filters, ['service type']),
|
||||||
|
sortField,
|
||||||
|
sortOrder
|
||||||
);
|
);
|
||||||
const tierAgg = searchData(
|
const tierAgg = searchData(
|
||||||
searchText,
|
searchText,
|
||||||
currentPage,
|
currentPage,
|
||||||
0,
|
0,
|
||||||
getFilterString(filters, ['tier'])
|
getFilterString(filters, ['tier']),
|
||||||
|
sortField,
|
||||||
|
sortOrder
|
||||||
);
|
);
|
||||||
const tagAgg = searchData(
|
const tagAgg = searchData(
|
||||||
searchText,
|
searchText,
|
||||||
currentPage,
|
currentPage,
|
||||||
0,
|
0,
|
||||||
getFilterString(filters, ['tags'])
|
getFilterString(filters, ['tags']),
|
||||||
|
sortField,
|
||||||
|
sortOrder
|
||||||
);
|
);
|
||||||
|
|
||||||
Promise.all([searchResults, serviceTypeAgg, tierAgg, tagAgg])
|
Promise.all([searchResults, serviceTypeAgg, tierAgg, tagAgg])
|
||||||
@ -240,6 +261,73 @@ const ExplorePage: React.FC = (): React.ReactElement => {
|
|||||||
return facetFilters;
|
return facetFilters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleFieldDropDown = (
|
||||||
|
_e: React.MouseEvent<HTMLElement, MouseEvent>,
|
||||||
|
value?: string
|
||||||
|
) => {
|
||||||
|
setSortField(value || sortingFields[3].value);
|
||||||
|
setFieldListVisible(false);
|
||||||
|
};
|
||||||
|
const handleOrderDropDown = (
|
||||||
|
_e: React.MouseEvent<HTMLElement, MouseEvent>,
|
||||||
|
value?: string
|
||||||
|
) => {
|
||||||
|
setSortOrder(value || sortingOrder[1].value);
|
||||||
|
setOrderListVisible(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSortingElements = () => {
|
||||||
|
return (
|
||||||
|
<div className="tw-flex tw-justify-between">
|
||||||
|
<div />
|
||||||
|
<div className="tw-flex tw-gap-2">
|
||||||
|
<div className="tw-mt-2 tw-mb-4">
|
||||||
|
<span className="tw-mr-2">Sort by :</span>
|
||||||
|
<span className="tw-relative">
|
||||||
|
<Button
|
||||||
|
className="tw-underline"
|
||||||
|
size="custom"
|
||||||
|
theme="primary"
|
||||||
|
variant="link"
|
||||||
|
onClick={() => setFieldListVisible((visible) => !visible)}>
|
||||||
|
{sortingFields.find((field) => field.value === sortField)?.name}
|
||||||
|
<DropDownIcon />
|
||||||
|
</Button>
|
||||||
|
{fieldListVisible && (
|
||||||
|
<DropDownList
|
||||||
|
dropDownList={sortingFields}
|
||||||
|
value={sortField}
|
||||||
|
onSelect={handleFieldDropDown}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="tw-mt-2 tw-mb-4">
|
||||||
|
<span className="tw-mr-2">Order by :</span>
|
||||||
|
<span className="tw-relative">
|
||||||
|
<Button
|
||||||
|
className="tw-underline"
|
||||||
|
size="custom"
|
||||||
|
theme="primary"
|
||||||
|
variant="link"
|
||||||
|
onClick={() => setOrderListVisible((visible) => !visible)}>
|
||||||
|
{sortingOrder.find((order) => order.value === sortOrder)?.name}
|
||||||
|
<DropDownIcon />
|
||||||
|
</Button>
|
||||||
|
{orderListVisible && (
|
||||||
|
<DropDownList
|
||||||
|
dropDownList={sortingOrder}
|
||||||
|
value={sortOrder}
|
||||||
|
onSelect={handleOrderDropDown}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSearchText(searchQuery || '');
|
setSearchText(searchQuery || '');
|
||||||
setCurrentPage(1);
|
setCurrentPage(1);
|
||||||
@ -253,7 +341,7 @@ const ExplorePage: React.FC = (): React.ReactElement => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchTableData(true);
|
fetchTableData(true);
|
||||||
}, [searchText]);
|
}, [searchText, sortField, sortOrder]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isMounting.current) {
|
if (!isMounting.current) {
|
||||||
@ -290,8 +378,9 @@ const ExplorePage: React.FC = (): React.ReactElement => {
|
|||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
paginate={paginate}
|
paginate={paginate}
|
||||||
searchText={searchText}
|
searchText={searchText}
|
||||||
totalValue={totalNumberOfValue}
|
totalValue={totalNumberOfValue}>
|
||||||
/>
|
{getSortingElements()}
|
||||||
|
</SearchedData>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { CSSProperties } from 'react';
|
import React, { CSSProperties } from 'react';
|
||||||
|
|
||||||
export const dropdownIcon = ({ style }: { style: CSSProperties }) => {
|
export const dropdownIcon = ({ style }: { style?: CSSProperties }) => {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user