mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-31 12:39:01 +00:00
fix: explore quick filters should behave like facet filters (#12206)
* fix: explore quick filters * fix: code smells
This commit is contained in:
parent
1e1ab31e9c
commit
f7fe9ff75d
@ -1,12 +1,22 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" fill="#7147E8" stroke="#7147E8">
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<g id="SVGRepo_iconCarrier">
|
||||
<title>ionicons-v5-m</title>
|
||||
<path d="M448,256c0-106-86-192-192-192S64,150,64,256s86,192,192,192S448,362,448,256Z" style="fill:none;stroke:#7147E8;stroke-miterlimit:10;stroke-width:32px"/>
|
||||
<line x1="320" y1="320" x2="192" y2="192" style="fill:none;stroke:#7147E8;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/>
|
||||
<line x1="192" y1="320" x2="320" y2="192" style="fill:none;stroke:#7147E8;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" fill="#0968da" stroke="#0968da">
|
||||
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
|
||||
<g id="SVGRepo_iconCarrier">
|
||||
|
||||
<title>ionicons-v5-m</title>
|
||||
|
||||
<path d="M448,256c0-106-86-192-192-192S64,150,64,256s86,192,192,192S448,362,448,256Z" style="fill:none;stroke:#0968da;stroke-miterlimit:10;stroke-width:32px"/>
|
||||
|
||||
<line x1="320" y1="320" x2="192" y2="192" style="fill:none;stroke:#0968da;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/>
|
||||
|
||||
<line x1="192" y1="320" x2="320" y2="192" style="fill:none;stroke:#0968da;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/>
|
||||
|
||||
</g>
|
||||
|
||||
</svg>
|
Before Width: | Height: | Size: 948 B After Width: | Height: | Size: 948 B |
@ -514,9 +514,9 @@ export const DataAssetsHeader = ({
|
||||
<Typography.Text>{followers}</Typography.Text>
|
||||
</Button>
|
||||
<Tooltip
|
||||
open={!isEmpty(copyTooltip)}
|
||||
placement="bottomRight"
|
||||
title={copyTooltip}
|
||||
visible={!isEmpty(copyTooltip)}>
|
||||
title={copyTooltip}>
|
||||
<Button
|
||||
icon={<Icon component={ShareIcon} />}
|
||||
onClick={handleShareButtonClick}
|
||||
|
@ -63,7 +63,7 @@ const KPILatestResultsV1: FC<Props> = ({ kpiLatestResultsRecord }) => {
|
||||
|
||||
return (
|
||||
<Row key={name}>
|
||||
<Col className="flex-center" span={24}>
|
||||
<Col className="d-flex items-center" span={24}>
|
||||
<div
|
||||
className="kpi-days-section"
|
||||
style={{
|
||||
@ -77,7 +77,7 @@ const KPILatestResultsV1: FC<Props> = ({ kpiLatestResultsRecord }) => {
|
||||
{t('label.day-left', { day: 'days' })}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
<div className="m-l-sm">
|
||||
<div className="m-l-sm flex-1">
|
||||
<Typography.Text className="text-xs">
|
||||
{resultData.displayName ?? name}
|
||||
</Typography.Text>
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
@import url('../../styles/variables.less');
|
||||
|
||||
@sidebar-width: 100px;
|
||||
|
||||
.custom-react-flow {
|
||||
.react-flow__node-input.selectable.selected {
|
||||
box-shadow: none;
|
||||
@ -90,8 +92,8 @@
|
||||
width: 400px;
|
||||
height: 32px;
|
||||
}
|
||||
.custom-control-search-box-edit-mode {
|
||||
margin-left: 83px;
|
||||
.ant-select.custom-control-search-box-edit-mode {
|
||||
margin-left: @sidebar-width;
|
||||
}
|
||||
.custom-control-basic-button {
|
||||
padding-left: 4px;
|
||||
@ -157,3 +159,24 @@
|
||||
.lineage-card .react-flow__edge.animated path {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.entity-lineage.sidebar {
|
||||
height: 110%;
|
||||
background: @white;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: @sidebar-width;
|
||||
z-index: 200;
|
||||
overflow-y: auto;
|
||||
padding: 8px;
|
||||
transform: translateX(100%);
|
||||
display: none;
|
||||
border-right: 1px solid @border-color;
|
||||
transition: transform 0.3s ease-out;
|
||||
}
|
||||
|
||||
.entity-lineage.sidebar.open {
|
||||
transform: translateX(0);
|
||||
display: block;
|
||||
}
|
||||
|
@ -11,12 +11,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Aggregations } from 'interface/search.interface';
|
||||
import { SearchIndex } from '../../enums/search.enum';
|
||||
import { ExploreQuickFilterField } from './explore.interface';
|
||||
|
||||
export interface ExploreQuickFiltersProps {
|
||||
index: SearchIndex;
|
||||
fields: Array<ExploreQuickFilterField>;
|
||||
aggregations?: Aggregations;
|
||||
onFieldValueSelect: (field: ExploreQuickFilterField) => void;
|
||||
onAdvanceSearch: () => void;
|
||||
showDeleted?: boolean;
|
||||
|
@ -15,6 +15,7 @@ import { Space } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import { SearchIndex } from 'enums/search.enum';
|
||||
import { isEqual, isUndefined, uniqWith } from 'lodash';
|
||||
import { Bucket } from 'Models';
|
||||
import React, { FC, useState } from 'react';
|
||||
import {
|
||||
getAdvancedFieldDefaultOptions,
|
||||
@ -29,6 +30,7 @@ import {
|
||||
} from '../../constants/AdvancedSearch.constants';
|
||||
import {
|
||||
getAdvancedField,
|
||||
getOptionsFromAggregationBucket,
|
||||
getOptionTextFromKey,
|
||||
} from '../../utils/AdvancedSearchUtils';
|
||||
import { showErrorToast } from '../../utils/ToastUtils';
|
||||
@ -39,48 +41,51 @@ import { ExploreQuickFiltersProps } from './ExploreQuickFilters.interface';
|
||||
const ExploreQuickFilters: FC<ExploreQuickFiltersProps> = ({
|
||||
fields,
|
||||
index,
|
||||
aggregations,
|
||||
onFieldValueSelect,
|
||||
}) => {
|
||||
const [options, setOptions] = useState<SearchDropdownOption[]>();
|
||||
const [isOptionsLoading, setIsOptionsLoading] = useState<boolean>(false);
|
||||
const [tierOptions, setTierOptions] = useState<SearchDropdownOption[]>();
|
||||
|
||||
const fetchDefaultOptions = async (
|
||||
index: SearchIndex | SearchIndex[],
|
||||
key: string
|
||||
) => {
|
||||
const [res, tierTags] = await Promise.all([
|
||||
getAdvancedFieldDefaultOptions(index, key),
|
||||
key === 'tier.tagFQN'
|
||||
? getTags({ parent: 'Tier' })
|
||||
: Promise.resolve(null),
|
||||
]);
|
||||
let buckets: Bucket[] = [];
|
||||
|
||||
const buckets = res.data.aggregations[`sterms#${key}`].buckets;
|
||||
|
||||
const optionsArray = buckets.map((option) => ({
|
||||
key: option.key,
|
||||
label: option.key,
|
||||
count: option.doc_count ?? 0,
|
||||
}));
|
||||
|
||||
let options;
|
||||
if (key === 'tier.tagFQN' && tierTags) {
|
||||
options = tierTags.data.map((option) => {
|
||||
const bucketItem = buckets.find(
|
||||
(item) => item.key === option.fullyQualifiedName
|
||||
);
|
||||
|
||||
return {
|
||||
key: option.fullyQualifiedName ?? '',
|
||||
label: option.name,
|
||||
count: bucketItem?.doc_count ?? 0,
|
||||
};
|
||||
});
|
||||
if (aggregations?.[key] && key !== 'tier.tagFQN') {
|
||||
buckets = aggregations[key].buckets;
|
||||
} else {
|
||||
options = optionsArray;
|
||||
const [res, tierTags] = await Promise.all([
|
||||
getAdvancedFieldDefaultOptions(index, key),
|
||||
key === 'tier.tagFQN'
|
||||
? getTags({ parent: 'Tier' })
|
||||
: Promise.resolve(null),
|
||||
]);
|
||||
|
||||
buckets = res.data.aggregations[`sterms#${key}`].buckets;
|
||||
|
||||
if (key === 'tier.tagFQN' && tierTags) {
|
||||
const options = tierTags.data.map((option) => {
|
||||
const bucketItem = buckets.find(
|
||||
(item) => item.key === option.fullyQualifiedName
|
||||
);
|
||||
|
||||
return {
|
||||
key: option.fullyQualifiedName ?? '',
|
||||
label: option.name,
|
||||
count: bucketItem?.doc_count ?? 0,
|
||||
};
|
||||
});
|
||||
setTierOptions(uniqWith(options, isEqual));
|
||||
setOptions(uniqWith(options, isEqual));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setOptions(uniqWith(options, isEqual));
|
||||
setOptions(uniqWith(getOptionsFromAggregationBucket(buckets), isEqual));
|
||||
};
|
||||
|
||||
const getInitialOptions = async (key: string) => {
|
||||
@ -106,61 +111,69 @@ const ExploreQuickFilters: FC<ExploreQuickFiltersProps> = ({
|
||||
setIsOptionsLoading(true);
|
||||
setOptions([]);
|
||||
try {
|
||||
if (value) {
|
||||
const advancedField = getAdvancedField(key);
|
||||
if (!MISC_FIELDS.includes(key)) {
|
||||
const res = await getAdvancedFieldOptions(
|
||||
value,
|
||||
index,
|
||||
advancedField
|
||||
);
|
||||
|
||||
const suggestOptions =
|
||||
res.data.suggest['metadata-suggest'][0].options ?? [];
|
||||
|
||||
const formattedSuggestions = suggestOptions.map((option) => {
|
||||
const optionsText = getOptionTextFromKey(index, option, key);
|
||||
|
||||
return {
|
||||
key: optionsText,
|
||||
label: optionsText,
|
||||
};
|
||||
});
|
||||
|
||||
setOptions(uniqWith(formattedSuggestions, isEqual));
|
||||
} else {
|
||||
if (key === 'tags.tagFQN') {
|
||||
const res = await getTagSuggestions(value);
|
||||
|
||||
const suggestOptions =
|
||||
res.data.suggest['metadata-suggest'][0].options ?? [];
|
||||
|
||||
const formattedSuggestions = suggestOptions
|
||||
.filter((op) => !isUndefined(op._source.fullyQualifiedName))
|
||||
.map((op) => op._source.fullyQualifiedName as string);
|
||||
|
||||
const optionsArray = formattedSuggestions.map((op) => ({
|
||||
key: op,
|
||||
label: op,
|
||||
}));
|
||||
|
||||
setOptions(uniqWith(optionsArray, isEqual));
|
||||
} else {
|
||||
const res = await getUserSuggestions(value);
|
||||
|
||||
const suggestOptions =
|
||||
res.data.suggest['metadata-suggest'][0].options ?? [];
|
||||
|
||||
const formattedSuggestions = suggestOptions.map((op) => ({
|
||||
key: op._source.displayName ?? op._source.name,
|
||||
label: op._source.displayName ?? op._source.name,
|
||||
}));
|
||||
|
||||
setOptions(uniqWith(formattedSuggestions, isEqual));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!value) {
|
||||
getInitialOptions(key);
|
||||
|
||||
return;
|
||||
}
|
||||
if (aggregations?.[key] && key !== 'tier.tagFQN') {
|
||||
const defaultOptions = getOptionsFromAggregationBucket(
|
||||
aggregations[key].buckets
|
||||
);
|
||||
const filteredOptions = defaultOptions.filter((option) => {
|
||||
return option.label.toLowerCase().includes(value.toLowerCase());
|
||||
});
|
||||
setOptions(filteredOptions);
|
||||
} else if (key === 'tier.tagFQN') {
|
||||
const filteredOptions = tierOptions?.filter((option) => {
|
||||
return option.label.toLowerCase().includes(value.toLowerCase());
|
||||
});
|
||||
setOptions(filteredOptions);
|
||||
} else if (!MISC_FIELDS.includes(key)) {
|
||||
const advancedField = getAdvancedField(key);
|
||||
const res = await getAdvancedFieldOptions(value, index, advancedField);
|
||||
|
||||
const suggestOptions =
|
||||
res.data.suggest['metadata-suggest'][0].options ?? [];
|
||||
|
||||
const formattedSuggestions = suggestOptions.map((option) => {
|
||||
const optionsText = getOptionTextFromKey(index, option, key);
|
||||
|
||||
return {
|
||||
key: optionsText,
|
||||
label: optionsText,
|
||||
};
|
||||
});
|
||||
|
||||
setOptions(uniqWith(formattedSuggestions, isEqual));
|
||||
} else if (key === 'tags.tagFQN') {
|
||||
const res = await getTagSuggestions(value);
|
||||
|
||||
const suggestOptions =
|
||||
res.data.suggest['metadata-suggest'][0].options ?? [];
|
||||
|
||||
const formattedSuggestions = suggestOptions
|
||||
.filter((op) => !isUndefined(op._source.fullyQualifiedName))
|
||||
.map((op) => op._source.fullyQualifiedName as string);
|
||||
|
||||
const optionsArray = formattedSuggestions.map((op) => ({
|
||||
key: op,
|
||||
label: op,
|
||||
}));
|
||||
|
||||
setOptions(uniqWith(optionsArray, isEqual));
|
||||
} else {
|
||||
const res = await getUserSuggestions(value);
|
||||
|
||||
const suggestOptions =
|
||||
res.data.suggest['metadata-suggest'][0].options ?? [];
|
||||
|
||||
const formattedSuggestions = suggestOptions.map((op) => ({
|
||||
key: op._source.displayName ?? op._source.name,
|
||||
label: op._source.displayName ?? op._source.name,
|
||||
}));
|
||||
|
||||
setOptions(uniqWith(formattedSuggestions, isEqual));
|
||||
}
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
|
@ -29,7 +29,6 @@ import { Table } from '../../generated/entity/data/table';
|
||||
import { Topic } from '../../generated/entity/data/topic';
|
||||
import { Aggregations, SearchResponse } from '../../interface/search.interface';
|
||||
import { SearchDropdownOption } from '../SearchDropdown/SearchDropdown.interface';
|
||||
import { FilterObject } from './AdvanceSearchProvider/AdvanceSearchProvider.interface';
|
||||
|
||||
export type UrlParams = {
|
||||
searchQuery: string;
|
||||
@ -67,9 +66,6 @@ export interface ExploreProps {
|
||||
queryFilter: QueryFilterInterface | undefined
|
||||
) => void;
|
||||
|
||||
facetFilters?: FilterObject;
|
||||
onChangeFacetFilters: (filter: FilterObject) => void;
|
||||
|
||||
searchIndex: ExploreSearchIndex;
|
||||
onChangeSearchIndex: (searchIndex: ExploreSearchIndex) => void;
|
||||
|
||||
|
@ -61,10 +61,10 @@ import Loader from '../Loader/Loader';
|
||||
import './ExploreV1.style.less';
|
||||
|
||||
const ExploreV1: React.FC<ExploreProps> = ({
|
||||
aggregations,
|
||||
searchResults,
|
||||
tabCounts,
|
||||
onChangeAdvancedSearchQuickFilters,
|
||||
facetFilters,
|
||||
searchIndex,
|
||||
onChangeSearchIndex,
|
||||
sortOrder,
|
||||
@ -79,7 +79,6 @@ const ExploreV1: React.FC<ExploreProps> = ({
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { tab } = useParams<{ tab: string }>();
|
||||
|
||||
const [selectedQuickFilters, setSelectedQuickFilters] = useState<
|
||||
ExploreQuickFilterField[]
|
||||
>([] as ExploreQuickFilterField[]);
|
||||
@ -144,7 +143,7 @@ const ExploreV1: React.FC<ExploreProps> = ({
|
||||
})
|
||||
);
|
||||
|
||||
return searchQueryParam && !facetFilters
|
||||
return searchQueryParam
|
||||
? items.filter((tabItem) => {
|
||||
return tabItem.count > 0 || tabItem.key === searchCriteria;
|
||||
})
|
||||
@ -287,157 +286,161 @@ const ExploreV1: React.FC<ExploreProps> = ({
|
||||
<div className="explore-page bg-white">
|
||||
<div className="w-full h-full">
|
||||
{tabItems.length > 0 && (
|
||||
<Row gutter={[8, 0]} wrap={false}>
|
||||
<Col span={24}>
|
||||
<Tabs
|
||||
activeKey={activeTabKey}
|
||||
className="explore-page-tabs"
|
||||
defaultActiveKey={defaultActiveTab}
|
||||
items={tabItems}
|
||||
onChange={(tab) => {
|
||||
tab && onChangeSearchIndex(tab as ExploreSearchIndex);
|
||||
setShowSummaryPanel(false);
|
||||
}}
|
||||
/>
|
||||
<Row className="filters-row">
|
||||
<Col className="searched-data-container w-full">
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col
|
||||
className="d-flex items-center justify-between"
|
||||
span={24}>
|
||||
{showFilters && (
|
||||
<ExploreQuickFilters
|
||||
fields={selectedQuickFilters}
|
||||
index={activeTabKey}
|
||||
showDeleted={showDeleted}
|
||||
onAdvanceSearch={() => toggleModal(true)}
|
||||
onChangeShowDeleted={onChangeShowDeleted}
|
||||
onFieldValueSelect={handleQuickFiltersValueSelect}
|
||||
/>
|
||||
)}
|
||||
<div className="d-flex items-center gap-4 m-l-auto m-r-xs">
|
||||
<span className="flex-center">
|
||||
<Switch
|
||||
checked={showDeleted}
|
||||
data-testid="show-deleted"
|
||||
onChange={onChangeShowDeleted}
|
||||
<>
|
||||
<Row gutter={[8, 0]} wrap={false}>
|
||||
<Col span={24}>
|
||||
<Tabs
|
||||
activeKey={activeTabKey}
|
||||
className="explore-page-tabs"
|
||||
defaultActiveKey={defaultActiveTab}
|
||||
items={tabItems}
|
||||
onChange={(tab) => {
|
||||
tab && onChangeSearchIndex(tab as ExploreSearchIndex);
|
||||
setShowSummaryPanel(false);
|
||||
}}
|
||||
/>
|
||||
<Row className="filters-row">
|
||||
<Col className="searched-data-container w-full">
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col
|
||||
className="d-flex items-center justify-between"
|
||||
span={24}>
|
||||
{showFilters && (
|
||||
<ExploreQuickFilters
|
||||
aggregations={aggregations}
|
||||
fields={selectedQuickFilters}
|
||||
index={activeTabKey}
|
||||
showDeleted={showDeleted}
|
||||
onAdvanceSearch={() => toggleModal(true)}
|
||||
onChangeShowDeleted={onChangeShowDeleted}
|
||||
onFieldValueSelect={handleQuickFiltersValueSelect}
|
||||
/>
|
||||
<Typography.Text className="p-l-xs text-grey-muted">
|
||||
{t('label.deleted')}
|
||||
</Typography.Text>
|
||||
</span>
|
||||
{(quickFilters || sqlQuery) && (
|
||||
)}
|
||||
<div className="d-flex items-center gap-4 m-l-auto m-r-xs">
|
||||
<span className="flex-center">
|
||||
<Switch
|
||||
checked={showDeleted}
|
||||
data-testid="show-deleted"
|
||||
onChange={onChangeShowDeleted}
|
||||
/>
|
||||
<Typography.Text className="p-l-xs text-grey-muted">
|
||||
{t('label.deleted')}
|
||||
</Typography.Text>
|
||||
</span>
|
||||
{(quickFilters || sqlQuery) && (
|
||||
<Typography.Text
|
||||
className="text-primary self-center cursor-pointer"
|
||||
onClick={() => clearFilters()}>
|
||||
{t('label.clear-entity', {
|
||||
entity: '',
|
||||
})}
|
||||
</Typography.Text>
|
||||
)}
|
||||
|
||||
<Typography.Text
|
||||
className="text-primary self-center cursor-pointer"
|
||||
onClick={() => clearFilters()}>
|
||||
{t('label.clear-entity', {
|
||||
data-testid="advance-search-button"
|
||||
onClick={() => toggleModal(true)}>
|
||||
{t('label.advanced-entity', {
|
||||
entity: '',
|
||||
})}
|
||||
</Typography.Text>
|
||||
)}
|
||||
|
||||
<Typography.Text
|
||||
className="text-primary self-center cursor-pointer"
|
||||
data-testid="advance-search-button"
|
||||
onClick={() => toggleModal(true)}>
|
||||
{t('label.advanced-entity', {
|
||||
entity: '',
|
||||
})}
|
||||
</Typography.Text>
|
||||
<span className="sorting-dropdown-container">
|
||||
<SortingDropDown
|
||||
fieldList={tabsInfo[searchIndex].sortingFields}
|
||||
handleFieldDropDown={onChangeSortValue}
|
||||
sortField={sortValue}
|
||||
/>
|
||||
<Button
|
||||
className="p-0"
|
||||
size="small"
|
||||
type="text"
|
||||
onClick={() =>
|
||||
onChangeSortOder(
|
||||
isAscSortOrder
|
||||
? SORT_ORDER.DESC
|
||||
: SORT_ORDER.ASC
|
||||
)
|
||||
}>
|
||||
{isAscSortOrder ? (
|
||||
<SortAscendingOutlined
|
||||
style={{ fontSize: '14px' }}
|
||||
{...sortProps}
|
||||
/>
|
||||
) : (
|
||||
<SortDescendingOutlined
|
||||
style={{ fontSize: '14px' }}
|
||||
{...sortProps}
|
||||
/>
|
||||
)}
|
||||
</Button>
|
||||
</span>
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
{sqlQuery && (
|
||||
<Col span={24}>
|
||||
<AppliedFilterText
|
||||
filterText={sqlQuery}
|
||||
onEdit={() => toggleModal(true)}
|
||||
/>
|
||||
<span className="sorting-dropdown-container">
|
||||
<SortingDropDown
|
||||
fieldList={tabsInfo[searchIndex].sortingFields}
|
||||
handleFieldDropDown={onChangeSortValue}
|
||||
sortField={sortValue}
|
||||
/>
|
||||
<Button
|
||||
className="p-0"
|
||||
size="small"
|
||||
type="text"
|
||||
onClick={() =>
|
||||
onChangeSortOder(
|
||||
isAscSortOrder
|
||||
? SORT_ORDER.DESC
|
||||
: SORT_ORDER.ASC
|
||||
)
|
||||
}>
|
||||
{isAscSortOrder ? (
|
||||
<SortAscendingOutlined
|
||||
style={{ fontSize: '14px' }}
|
||||
{...sortProps}
|
||||
/>
|
||||
) : (
|
||||
<SortDescendingOutlined
|
||||
style={{ fontSize: '14px' }}
|
||||
{...sortProps}
|
||||
/>
|
||||
)}
|
||||
</Button>
|
||||
</span>
|
||||
</div>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
|
||||
{sqlQuery && (
|
||||
<Col span={24}>
|
||||
<AppliedFilterText
|
||||
filterText={sqlQuery}
|
||||
onEdit={() => toggleModal(true)}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
<PageLayoutV1
|
||||
className="p-0 explore-page-layout"
|
||||
pageTitle={t('label.explore')}
|
||||
rightPanel={
|
||||
showSummaryPanel &&
|
||||
entityDetails && (
|
||||
<EntitySummaryPanel
|
||||
entityDetails={{ details: entityDetails }}
|
||||
handleClosePanel={handleClosePanel}
|
||||
/>
|
||||
)
|
||||
}
|
||||
rightPanelWidth={400}>
|
||||
<Row className="p-t-xs">
|
||||
<Col lg={{ offset: 3, span: 18 }} md={{ offset: 0, span: 24 }}>
|
||||
{!loading ? (
|
||||
<SearchedData
|
||||
isFilterSelected
|
||||
data={searchResults?.hits.hits ?? []}
|
||||
filter={parsedSearch}
|
||||
handleSummaryPanelDisplay={handleSummaryPanelDisplay}
|
||||
isSummaryPanelVisible={showSummaryPanel}
|
||||
selectedEntityId={entityDetails?.id || ''}
|
||||
totalValue={searchResults?.hits.total.value ?? 0}
|
||||
onPaginationChange={onChangePage}
|
||||
/>
|
||||
) : (
|
||||
<Loader />
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</PageLayoutV1>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<PageLayoutV1
|
||||
className="p-0 explore-page-layout"
|
||||
pageTitle={t('label.explore')}
|
||||
rightPanel={
|
||||
showSummaryPanel &&
|
||||
entityDetails && (
|
||||
<EntitySummaryPanel
|
||||
entityDetails={{ details: entityDetails }}
|
||||
handleClosePanel={handleClosePanel}
|
||||
/>
|
||||
)
|
||||
}
|
||||
rightPanelWidth={400}>
|
||||
<Row className="p-t-xs">
|
||||
<Col lg={{ offset: 3, span: 18 }} md={{ offset: 0, span: 24 }}>
|
||||
{!loading ? (
|
||||
<SearchedData
|
||||
isFilterSelected
|
||||
data={searchResults?.hits.hits ?? []}
|
||||
filter={parsedSearch}
|
||||
handleSummaryPanelDisplay={handleSummaryPanelDisplay}
|
||||
isSummaryPanelVisible={showSummaryPanel}
|
||||
selectedEntityId={entityDetails?.id || ''}
|
||||
totalValue={searchResults?.hits.total.value ?? 0}
|
||||
onPaginationChange={onChangePage}
|
||||
/>
|
||||
) : (
|
||||
<Loader />
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
{searchQueryParam && tabItems.length === 0 && !loading && (
|
||||
<Space
|
||||
align="center"
|
||||
className="w-full h-full flex-center"
|
||||
data-testid="no-search-results"
|
||||
direction="vertical"
|
||||
size={48}>
|
||||
<ErrorPlaceHolder
|
||||
className="mt-0-important"
|
||||
type={ERROR_PLACEHOLDER_TYPE.FILTER}
|
||||
/>
|
||||
</Space>
|
||||
)}
|
||||
{searchQueryParam && tabItems.length === 0 && loading && <Loader />}
|
||||
</PageLayoutV1>
|
||||
|
||||
{searchQueryParam && tabItems.length === 0 && !loading && (
|
||||
<Space
|
||||
align="center"
|
||||
className="w-full flex-center full-height"
|
||||
data-testid="no-search-results"
|
||||
direction="vertical"
|
||||
size={48}>
|
||||
<ErrorPlaceHolder
|
||||
className="mt-0-important"
|
||||
type={ERROR_PLACEHOLDER_TYPE.FILTER}
|
||||
/>
|
||||
</Space>
|
||||
)}
|
||||
{searchQueryParam && tabItems.length === 0 && loading && <Loader />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -44,18 +44,18 @@ export const COMMON_DROPDOWN_ITEMS = [
|
||||
},
|
||||
{
|
||||
label: t('label.service'),
|
||||
key: 'service.name',
|
||||
key: 'service.name.keyword',
|
||||
},
|
||||
];
|
||||
|
||||
export const TABLE_DROPDOWN_ITEMS = [
|
||||
{
|
||||
label: t('label.database'),
|
||||
key: 'database.name',
|
||||
key: 'database.name.keyword',
|
||||
},
|
||||
{
|
||||
label: t('label.schema'),
|
||||
key: 'databaseSchema.name',
|
||||
key: 'databaseSchema.name.keyword',
|
||||
},
|
||||
{
|
||||
label: t('label.column'),
|
||||
|
@ -1040,9 +1040,7 @@ const TagsPage = () => {
|
||||
{isUpdateLoading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<div
|
||||
className="full-height page-container"
|
||||
data-testid="tags-container">
|
||||
<div className="p-x-md" data-testid="tags-container">
|
||||
{currentClassification && (
|
||||
<Row data-testid="header" wrap={false}>
|
||||
<Col flex="auto">
|
||||
|
@ -37,7 +37,6 @@ import React, {
|
||||
} from 'react';
|
||||
import { useHistory, useLocation, useParams } from 'react-router-dom';
|
||||
import { searchQuery } from 'rest/searchAPI';
|
||||
import useDeepCompareEffect from 'use-deep-compare-effect';
|
||||
import {
|
||||
getCombinedQueryFilterObject,
|
||||
getUpdatedAggregateFieldValue,
|
||||
@ -51,10 +50,6 @@ import {
|
||||
} from '../../constants/explore.constants';
|
||||
import { SearchIndex } from '../../enums/search.enum';
|
||||
import { Aggregations, SearchResponse } from '../../interface/search.interface';
|
||||
import {
|
||||
filterObjectToElasticsearchQuery,
|
||||
isFilterObject,
|
||||
} from '../../utils/FilterUtils';
|
||||
import { showErrorToast } from '../../utils/ToastUtils';
|
||||
import {
|
||||
QueryFieldInterface,
|
||||
@ -109,19 +104,6 @@ const ExplorePageV1: FunctionComponent = () => {
|
||||
[location.search]
|
||||
);
|
||||
|
||||
const facetFilters = useMemo(
|
||||
() =>
|
||||
isFilterObject(parsedSearch.facetFilter)
|
||||
? parsedSearch.facetFilter
|
||||
: undefined,
|
||||
[parsedSearch.facetFilter]
|
||||
);
|
||||
|
||||
const elasticsearchQueryFilter = useMemo(
|
||||
() => filterObjectToElasticsearchQuery(facetFilters),
|
||||
[facetFilters]
|
||||
);
|
||||
|
||||
const handlePageChange: ExploreProps['onChangePage'] = (page, size) => {
|
||||
history.push({
|
||||
search: Qs.stringify({ ...parsedSearch, page, size: size ?? PAGE_SIZE }),
|
||||
@ -197,14 +179,6 @@ const ExplorePageV1: FunctionComponent = () => {
|
||||
[history, parsedSearch]
|
||||
);
|
||||
|
||||
const handleFacetFilterChange: ExploreProps['onChangeFacetFilters'] = (
|
||||
facetFilter
|
||||
) => {
|
||||
history.push({
|
||||
search: Qs.stringify({ ...parsedSearch, facetFilter, page: 1 }),
|
||||
});
|
||||
};
|
||||
|
||||
const handleShowDeletedChange: ExploreProps['onChangeShowDeleted'] = (
|
||||
showDeleted
|
||||
) => {
|
||||
@ -301,11 +275,10 @@ const ExplorePageV1: FunctionComponent = () => {
|
||||
fetchFilterAggregationsWithoutFilters();
|
||||
}, [searchIndex]);
|
||||
|
||||
useDeepCompareEffect(() => {
|
||||
useEffect(() => {
|
||||
const updatedQuickFilters = getAdvancedSearchQuickFilters();
|
||||
|
||||
const combinedQueryFilter = getCombinedQueryFilterObject(
|
||||
elasticsearchQueryFilter as unknown as QueryFilterInterface,
|
||||
updatedQuickFilters as QueryFilterInterface,
|
||||
queryFilter as unknown as QueryFilterInterface
|
||||
);
|
||||
@ -390,7 +363,6 @@ const ExplorePageV1: FunctionComponent = () => {
|
||||
sortValue,
|
||||
sortOrder,
|
||||
showDeleted,
|
||||
elasticsearchQueryFilter,
|
||||
searchIndex,
|
||||
page,
|
||||
size,
|
||||
@ -440,7 +412,6 @@ const ExplorePageV1: FunctionComponent = () => {
|
||||
return (
|
||||
<ExploreV1
|
||||
aggregations={updatedAggregations}
|
||||
facetFilters={facetFilters}
|
||||
loading={isLoading && !isTourOpen}
|
||||
quickFilters={advancesSearchQuickFilters}
|
||||
searchIndex={searchIndex}
|
||||
@ -454,7 +425,6 @@ const ExplorePageV1: FunctionComponent = () => {
|
||||
sortValue={sortValue}
|
||||
tabCounts={searchHitCounts}
|
||||
onChangeAdvancedSearchQuickFilters={handleAdvanceSearchQuickFiltersChange}
|
||||
onChangeFacetFilters={handleFacetFilterChange}
|
||||
onChangePage={handlePageChange}
|
||||
onChangeSearchIndex={handleSearchIndexChange}
|
||||
onChangeShowDeleted={handleShowDeletedChange}
|
||||
|
@ -439,3 +439,7 @@ a[href].link-text-grey,
|
||||
.global-border-radius {
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.full-height {
|
||||
height: calc(100vh - 64px); // removing only navbar height
|
||||
}
|
||||
|
@ -828,27 +828,6 @@ body .list-option.rdw-option-active {
|
||||
|
||||
/* EntityLineage Sidebar CSS */
|
||||
|
||||
.entity-lineage.sidebar {
|
||||
height: 110%;
|
||||
background: white;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100px;
|
||||
z-index: 200;
|
||||
overflow-y: auto;
|
||||
padding: 8px;
|
||||
transform: translateX(100%);
|
||||
display: none;
|
||||
border-right: 1px solid #d9ceee;
|
||||
transition: transform 0.3s ease-out;
|
||||
}
|
||||
|
||||
.entity-lineage.sidebar.open {
|
||||
transform: translateX(0);
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* login slider */
|
||||
|
||||
.login-slider.slick-dots li.slick-active button:before {
|
||||
|
@ -709,12 +709,6 @@ body .profiler-graph .recharts-active-dot circle {
|
||||
width: calc(100% - 330px);
|
||||
}
|
||||
|
||||
/* page-container v1 */
|
||||
|
||||
.full-height {
|
||||
height: calc(100vh - 110px);
|
||||
}
|
||||
|
||||
/* 64 header + ( 16 + 16 )spacing Y = 96*/
|
||||
#left-panel {
|
||||
position: fixed;
|
||||
|
@ -17,6 +17,7 @@ import ProfilePicture from 'components/common/ProfilePicture/ProfilePicture';
|
||||
import { SearchDropdownOption } from 'components/SearchDropdown/SearchDropdown.interface';
|
||||
import i18next from 'i18next';
|
||||
import {
|
||||
Bucket,
|
||||
ContainerSearchSource,
|
||||
DashboardSearchSource,
|
||||
ExploreSearchSource,
|
||||
@ -389,3 +390,15 @@ export const getOptionTextFromKey = (
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const getOptionsFromAggregationBucket = (buckets: Bucket[]) => {
|
||||
if (!buckets) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return buckets.map((option) => ({
|
||||
key: option.key,
|
||||
label: option.key,
|
||||
count: option.doc_count ?? 0,
|
||||
}));
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user