fix: explore quick filters should behave like facet filters (#12206)

* fix: explore quick filters

* fix: code smells
This commit is contained in:
karanh37 2023-06-28 22:34:13 +05:30 committed by GitHub
parent 1e1ab31e9c
commit f7fe9ff75d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 316 additions and 311 deletions

View File

@ -1,12 +1,22 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <!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 --> <!-- 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"> <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_bgCarrier" stroke-width="0"/>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/> <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
<g id="SVGRepo_iconCarrier"> <g id="SVGRepo_iconCarrier">
<title>ionicons-v5-m</title> <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"/> <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="192" y1="320" x2="320" y2="192" style="fill:none;stroke:#7147E8;stroke-linecap:round;stroke-linejoin:round;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> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 948 B

After

Width:  |  Height:  |  Size: 948 B

View File

@ -514,9 +514,9 @@ export const DataAssetsHeader = ({
<Typography.Text>{followers}</Typography.Text> <Typography.Text>{followers}</Typography.Text>
</Button> </Button>
<Tooltip <Tooltip
open={!isEmpty(copyTooltip)}
placement="bottomRight" placement="bottomRight"
title={copyTooltip} title={copyTooltip}>
visible={!isEmpty(copyTooltip)}>
<Button <Button
icon={<Icon component={ShareIcon} />} icon={<Icon component={ShareIcon} />}
onClick={handleShareButtonClick} onClick={handleShareButtonClick}

View File

@ -63,7 +63,7 @@ const KPILatestResultsV1: FC<Props> = ({ kpiLatestResultsRecord }) => {
return ( return (
<Row key={name}> <Row key={name}>
<Col className="flex-center" span={24}> <Col className="d-flex items-center" span={24}>
<div <div
className="kpi-days-section" className="kpi-days-section"
style={{ style={{
@ -77,7 +77,7 @@ const KPILatestResultsV1: FC<Props> = ({ kpiLatestResultsRecord }) => {
{t('label.day-left', { day: 'days' })} {t('label.day-left', { day: 'days' })}
</Typography.Text> </Typography.Text>
</div> </div>
<div className="m-l-sm"> <div className="m-l-sm flex-1">
<Typography.Text className="text-xs"> <Typography.Text className="text-xs">
{resultData.displayName ?? name} {resultData.displayName ?? name}
</Typography.Text> </Typography.Text>

View File

@ -13,6 +13,8 @@
@import url('../../styles/variables.less'); @import url('../../styles/variables.less');
@sidebar-width: 100px;
.custom-react-flow { .custom-react-flow {
.react-flow__node-input.selectable.selected { .react-flow__node-input.selectable.selected {
box-shadow: none; box-shadow: none;
@ -90,8 +92,8 @@
width: 400px; width: 400px;
height: 32px; height: 32px;
} }
.custom-control-search-box-edit-mode { .ant-select.custom-control-search-box-edit-mode {
margin-left: 83px; margin-left: @sidebar-width;
} }
.custom-control-basic-button { .custom-control-basic-button {
padding-left: 4px; padding-left: 4px;
@ -157,3 +159,24 @@
.lineage-card .react-flow__edge.animated path { .lineage-card .react-flow__edge.animated path {
animation: none; 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;
}

View File

@ -11,12 +11,14 @@
* limitations under the License. * limitations under the License.
*/ */
import { Aggregations } from 'interface/search.interface';
import { SearchIndex } from '../../enums/search.enum'; import { SearchIndex } from '../../enums/search.enum';
import { ExploreQuickFilterField } from './explore.interface'; import { ExploreQuickFilterField } from './explore.interface';
export interface ExploreQuickFiltersProps { export interface ExploreQuickFiltersProps {
index: SearchIndex; index: SearchIndex;
fields: Array<ExploreQuickFilterField>; fields: Array<ExploreQuickFilterField>;
aggregations?: Aggregations;
onFieldValueSelect: (field: ExploreQuickFilterField) => void; onFieldValueSelect: (field: ExploreQuickFilterField) => void;
onAdvanceSearch: () => void; onAdvanceSearch: () => void;
showDeleted?: boolean; showDeleted?: boolean;

View File

@ -15,6 +15,7 @@ import { Space } from 'antd';
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import { SearchIndex } from 'enums/search.enum'; import { SearchIndex } from 'enums/search.enum';
import { isEqual, isUndefined, uniqWith } from 'lodash'; import { isEqual, isUndefined, uniqWith } from 'lodash';
import { Bucket } from 'Models';
import React, { FC, useState } from 'react'; import React, { FC, useState } from 'react';
import { import {
getAdvancedFieldDefaultOptions, getAdvancedFieldDefaultOptions,
@ -29,6 +30,7 @@ import {
} from '../../constants/AdvancedSearch.constants'; } from '../../constants/AdvancedSearch.constants';
import { import {
getAdvancedField, getAdvancedField,
getOptionsFromAggregationBucket,
getOptionTextFromKey, getOptionTextFromKey,
} from '../../utils/AdvancedSearchUtils'; } from '../../utils/AdvancedSearchUtils';
import { showErrorToast } from '../../utils/ToastUtils'; import { showErrorToast } from '../../utils/ToastUtils';
@ -39,15 +41,22 @@ import { ExploreQuickFiltersProps } from './ExploreQuickFilters.interface';
const ExploreQuickFilters: FC<ExploreQuickFiltersProps> = ({ const ExploreQuickFilters: FC<ExploreQuickFiltersProps> = ({
fields, fields,
index, index,
aggregations,
onFieldValueSelect, onFieldValueSelect,
}) => { }) => {
const [options, setOptions] = useState<SearchDropdownOption[]>(); const [options, setOptions] = useState<SearchDropdownOption[]>();
const [isOptionsLoading, setIsOptionsLoading] = useState<boolean>(false); const [isOptionsLoading, setIsOptionsLoading] = useState<boolean>(false);
const [tierOptions, setTierOptions] = useState<SearchDropdownOption[]>();
const fetchDefaultOptions = async ( const fetchDefaultOptions = async (
index: SearchIndex | SearchIndex[], index: SearchIndex | SearchIndex[],
key: string key: string
) => { ) => {
let buckets: Bucket[] = [];
if (aggregations?.[key] && key !== 'tier.tagFQN') {
buckets = aggregations[key].buckets;
} else {
const [res, tierTags] = await Promise.all([ const [res, tierTags] = await Promise.all([
getAdvancedFieldDefaultOptions(index, key), getAdvancedFieldDefaultOptions(index, key),
key === 'tier.tagFQN' key === 'tier.tagFQN'
@ -55,17 +64,10 @@ const ExploreQuickFilters: FC<ExploreQuickFiltersProps> = ({
: Promise.resolve(null), : Promise.resolve(null),
]); ]);
const buckets = res.data.aggregations[`sterms#${key}`].buckets; 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) { if (key === 'tier.tagFQN' && tierTags) {
options = tierTags.data.map((option) => { const options = tierTags.data.map((option) => {
const bucketItem = buckets.find( const bucketItem = buckets.find(
(item) => item.key === option.fullyQualifiedName (item) => item.key === option.fullyQualifiedName
); );
@ -76,11 +78,14 @@ const ExploreQuickFilters: FC<ExploreQuickFiltersProps> = ({
count: bucketItem?.doc_count ?? 0, count: bucketItem?.doc_count ?? 0,
}; };
}); });
} else { setTierOptions(uniqWith(options, isEqual));
options = optionsArray; setOptions(uniqWith(options, isEqual));
return;
}
} }
setOptions(uniqWith(options, isEqual)); setOptions(uniqWith(getOptionsFromAggregationBucket(buckets), isEqual));
}; };
const getInitialOptions = async (key: string) => { const getInitialOptions = async (key: string) => {
@ -106,14 +111,27 @@ const ExploreQuickFilters: FC<ExploreQuickFiltersProps> = ({
setIsOptionsLoading(true); setIsOptionsLoading(true);
setOptions([]); setOptions([]);
try { try {
if (value) { if (!value) {
const advancedField = getAdvancedField(key); getInitialOptions(key);
if (!MISC_FIELDS.includes(key)) {
const res = await getAdvancedFieldOptions( return;
value, }
index, if (aggregations?.[key] && key !== 'tier.tagFQN') {
advancedField 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 = const suggestOptions =
res.data.suggest['metadata-suggest'][0].options ?? []; res.data.suggest['metadata-suggest'][0].options ?? [];
@ -128,8 +146,7 @@ const ExploreQuickFilters: FC<ExploreQuickFiltersProps> = ({
}); });
setOptions(uniqWith(formattedSuggestions, isEqual)); setOptions(uniqWith(formattedSuggestions, isEqual));
} else { } else if (key === 'tags.tagFQN') {
if (key === 'tags.tagFQN') {
const res = await getTagSuggestions(value); const res = await getTagSuggestions(value);
const suggestOptions = const suggestOptions =
@ -158,10 +175,6 @@ const ExploreQuickFilters: FC<ExploreQuickFiltersProps> = ({
setOptions(uniqWith(formattedSuggestions, isEqual)); setOptions(uniqWith(formattedSuggestions, isEqual));
} }
}
} else {
getInitialOptions(key);
}
} catch (error) { } catch (error) {
showErrorToast(error as AxiosError); showErrorToast(error as AxiosError);
} finally { } finally {

View File

@ -29,7 +29,6 @@ import { Table } from '../../generated/entity/data/table';
import { Topic } from '../../generated/entity/data/topic'; import { Topic } from '../../generated/entity/data/topic';
import { Aggregations, SearchResponse } from '../../interface/search.interface'; import { Aggregations, SearchResponse } from '../../interface/search.interface';
import { SearchDropdownOption } from '../SearchDropdown/SearchDropdown.interface'; import { SearchDropdownOption } from '../SearchDropdown/SearchDropdown.interface';
import { FilterObject } from './AdvanceSearchProvider/AdvanceSearchProvider.interface';
export type UrlParams = { export type UrlParams = {
searchQuery: string; searchQuery: string;
@ -67,9 +66,6 @@ export interface ExploreProps {
queryFilter: QueryFilterInterface | undefined queryFilter: QueryFilterInterface | undefined
) => void; ) => void;
facetFilters?: FilterObject;
onChangeFacetFilters: (filter: FilterObject) => void;
searchIndex: ExploreSearchIndex; searchIndex: ExploreSearchIndex;
onChangeSearchIndex: (searchIndex: ExploreSearchIndex) => void; onChangeSearchIndex: (searchIndex: ExploreSearchIndex) => void;

View File

@ -61,10 +61,10 @@ import Loader from '../Loader/Loader';
import './ExploreV1.style.less'; import './ExploreV1.style.less';
const ExploreV1: React.FC<ExploreProps> = ({ const ExploreV1: React.FC<ExploreProps> = ({
aggregations,
searchResults, searchResults,
tabCounts, tabCounts,
onChangeAdvancedSearchQuickFilters, onChangeAdvancedSearchQuickFilters,
facetFilters,
searchIndex, searchIndex,
onChangeSearchIndex, onChangeSearchIndex,
sortOrder, sortOrder,
@ -79,7 +79,6 @@ const ExploreV1: React.FC<ExploreProps> = ({
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { tab } = useParams<{ tab: string }>(); const { tab } = useParams<{ tab: string }>();
const [selectedQuickFilters, setSelectedQuickFilters] = useState< const [selectedQuickFilters, setSelectedQuickFilters] = useState<
ExploreQuickFilterField[] ExploreQuickFilterField[]
>([] as ExploreQuickFilterField[]); >([] as ExploreQuickFilterField[]);
@ -144,7 +143,7 @@ const ExploreV1: React.FC<ExploreProps> = ({
}) })
); );
return searchQueryParam && !facetFilters return searchQueryParam
? items.filter((tabItem) => { ? items.filter((tabItem) => {
return tabItem.count > 0 || tabItem.key === searchCriteria; return tabItem.count > 0 || tabItem.key === searchCriteria;
}) })
@ -287,6 +286,7 @@ const ExploreV1: React.FC<ExploreProps> = ({
<div className="explore-page bg-white"> <div className="explore-page bg-white">
<div className="w-full h-full"> <div className="w-full h-full">
{tabItems.length > 0 && ( {tabItems.length > 0 && (
<>
<Row gutter={[8, 0]} wrap={false}> <Row gutter={[8, 0]} wrap={false}>
<Col span={24}> <Col span={24}>
<Tabs <Tabs
@ -307,6 +307,7 @@ const ExploreV1: React.FC<ExploreProps> = ({
span={24}> span={24}>
{showFilters && ( {showFilters && (
<ExploreQuickFilters <ExploreQuickFilters
aggregations={aggregations}
fields={selectedQuickFilters} fields={selectedQuickFilters}
index={activeTabKey} index={activeTabKey}
showDeleted={showDeleted} showDeleted={showDeleted}
@ -390,8 +391,6 @@ const ExploreV1: React.FC<ExploreProps> = ({
</Row> </Row>
</Col> </Col>
</Row> </Row>
)}
</div>
<PageLayoutV1 <PageLayoutV1
className="p-0 explore-page-layout" className="p-0 explore-page-layout"
pageTitle={t('label.explore')} pageTitle={t('label.explore')}
@ -423,10 +422,15 @@ const ExploreV1: React.FC<ExploreProps> = ({
)} )}
</Col> </Col>
</Row> </Row>
</PageLayoutV1>
</>
)}
</div>
{searchQueryParam && tabItems.length === 0 && !loading && ( {searchQueryParam && tabItems.length === 0 && !loading && (
<Space <Space
align="center" align="center"
className="w-full h-full flex-center" className="w-full flex-center full-height"
data-testid="no-search-results" data-testid="no-search-results"
direction="vertical" direction="vertical"
size={48}> size={48}>
@ -437,7 +441,6 @@ const ExploreV1: React.FC<ExploreProps> = ({
</Space> </Space>
)} )}
{searchQueryParam && tabItems.length === 0 && loading && <Loader />} {searchQueryParam && tabItems.length === 0 && loading && <Loader />}
</PageLayoutV1>
</div> </div>
); );
}; };

View File

@ -44,18 +44,18 @@ export const COMMON_DROPDOWN_ITEMS = [
}, },
{ {
label: t('label.service'), label: t('label.service'),
key: 'service.name', key: 'service.name.keyword',
}, },
]; ];
export const TABLE_DROPDOWN_ITEMS = [ export const TABLE_DROPDOWN_ITEMS = [
{ {
label: t('label.database'), label: t('label.database'),
key: 'database.name', key: 'database.name.keyword',
}, },
{ {
label: t('label.schema'), label: t('label.schema'),
key: 'databaseSchema.name', key: 'databaseSchema.name.keyword',
}, },
{ {
label: t('label.column'), label: t('label.column'),

View File

@ -1040,9 +1040,7 @@ const TagsPage = () => {
{isUpdateLoading ? ( {isUpdateLoading ? (
<Loader /> <Loader />
) : ( ) : (
<div <div className="p-x-md" data-testid="tags-container">
className="full-height page-container"
data-testid="tags-container">
{currentClassification && ( {currentClassification && (
<Row data-testid="header" wrap={false}> <Row data-testid="header" wrap={false}>
<Col flex="auto"> <Col flex="auto">

View File

@ -37,7 +37,6 @@ import React, {
} from 'react'; } from 'react';
import { useHistory, useLocation, useParams } from 'react-router-dom'; import { useHistory, useLocation, useParams } from 'react-router-dom';
import { searchQuery } from 'rest/searchAPI'; import { searchQuery } from 'rest/searchAPI';
import useDeepCompareEffect from 'use-deep-compare-effect';
import { import {
getCombinedQueryFilterObject, getCombinedQueryFilterObject,
getUpdatedAggregateFieldValue, getUpdatedAggregateFieldValue,
@ -51,10 +50,6 @@ import {
} from '../../constants/explore.constants'; } from '../../constants/explore.constants';
import { SearchIndex } from '../../enums/search.enum'; import { SearchIndex } from '../../enums/search.enum';
import { Aggregations, SearchResponse } from '../../interface/search.interface'; import { Aggregations, SearchResponse } from '../../interface/search.interface';
import {
filterObjectToElasticsearchQuery,
isFilterObject,
} from '../../utils/FilterUtils';
import { showErrorToast } from '../../utils/ToastUtils'; import { showErrorToast } from '../../utils/ToastUtils';
import { import {
QueryFieldInterface, QueryFieldInterface,
@ -109,19 +104,6 @@ const ExplorePageV1: FunctionComponent = () => {
[location.search] [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) => { const handlePageChange: ExploreProps['onChangePage'] = (page, size) => {
history.push({ history.push({
search: Qs.stringify({ ...parsedSearch, page, size: size ?? PAGE_SIZE }), search: Qs.stringify({ ...parsedSearch, page, size: size ?? PAGE_SIZE }),
@ -197,14 +179,6 @@ const ExplorePageV1: FunctionComponent = () => {
[history, parsedSearch] [history, parsedSearch]
); );
const handleFacetFilterChange: ExploreProps['onChangeFacetFilters'] = (
facetFilter
) => {
history.push({
search: Qs.stringify({ ...parsedSearch, facetFilter, page: 1 }),
});
};
const handleShowDeletedChange: ExploreProps['onChangeShowDeleted'] = ( const handleShowDeletedChange: ExploreProps['onChangeShowDeleted'] = (
showDeleted showDeleted
) => { ) => {
@ -301,11 +275,10 @@ const ExplorePageV1: FunctionComponent = () => {
fetchFilterAggregationsWithoutFilters(); fetchFilterAggregationsWithoutFilters();
}, [searchIndex]); }, [searchIndex]);
useDeepCompareEffect(() => { useEffect(() => {
const updatedQuickFilters = getAdvancedSearchQuickFilters(); const updatedQuickFilters = getAdvancedSearchQuickFilters();
const combinedQueryFilter = getCombinedQueryFilterObject( const combinedQueryFilter = getCombinedQueryFilterObject(
elasticsearchQueryFilter as unknown as QueryFilterInterface,
updatedQuickFilters as QueryFilterInterface, updatedQuickFilters as QueryFilterInterface,
queryFilter as unknown as QueryFilterInterface queryFilter as unknown as QueryFilterInterface
); );
@ -390,7 +363,6 @@ const ExplorePageV1: FunctionComponent = () => {
sortValue, sortValue,
sortOrder, sortOrder,
showDeleted, showDeleted,
elasticsearchQueryFilter,
searchIndex, searchIndex,
page, page,
size, size,
@ -440,7 +412,6 @@ const ExplorePageV1: FunctionComponent = () => {
return ( return (
<ExploreV1 <ExploreV1
aggregations={updatedAggregations} aggregations={updatedAggregations}
facetFilters={facetFilters}
loading={isLoading && !isTourOpen} loading={isLoading && !isTourOpen}
quickFilters={advancesSearchQuickFilters} quickFilters={advancesSearchQuickFilters}
searchIndex={searchIndex} searchIndex={searchIndex}
@ -454,7 +425,6 @@ const ExplorePageV1: FunctionComponent = () => {
sortValue={sortValue} sortValue={sortValue}
tabCounts={searchHitCounts} tabCounts={searchHitCounts}
onChangeAdvancedSearchQuickFilters={handleAdvanceSearchQuickFiltersChange} onChangeAdvancedSearchQuickFilters={handleAdvanceSearchQuickFiltersChange}
onChangeFacetFilters={handleFacetFilterChange}
onChangePage={handlePageChange} onChangePage={handlePageChange}
onChangeSearchIndex={handleSearchIndexChange} onChangeSearchIndex={handleSearchIndexChange}
onChangeShowDeleted={handleShowDeletedChange} onChangeShowDeleted={handleShowDeletedChange}

View File

@ -439,3 +439,7 @@ a[href].link-text-grey,
.global-border-radius { .global-border-radius {
border-radius: 10px; border-radius: 10px;
} }
.full-height {
height: calc(100vh - 64px); // removing only navbar height
}

View File

@ -828,27 +828,6 @@ body .list-option.rdw-option-active {
/* EntityLineage Sidebar CSS */ /* 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 */
.login-slider.slick-dots li.slick-active button:before { .login-slider.slick-dots li.slick-active button:before {

View File

@ -709,12 +709,6 @@ body .profiler-graph .recharts-active-dot circle {
width: calc(100% - 330px); width: calc(100% - 330px);
} }
/* page-container v1 */
.full-height {
height: calc(100vh - 110px);
}
/* 64 header + ( 16 + 16 )spacing Y = 96*/ /* 64 header + ( 16 + 16 )spacing Y = 96*/
#left-panel { #left-panel {
position: fixed; position: fixed;

View File

@ -17,6 +17,7 @@ import ProfilePicture from 'components/common/ProfilePicture/ProfilePicture';
import { SearchDropdownOption } from 'components/SearchDropdown/SearchDropdown.interface'; import { SearchDropdownOption } from 'components/SearchDropdown/SearchDropdown.interface';
import i18next from 'i18next'; import i18next from 'i18next';
import { import {
Bucket,
ContainerSearchSource, ContainerSearchSource,
DashboardSearchSource, DashboardSearchSource,
ExploreSearchSource, 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,
}));
};