import './discover_sidebar.scss' ; import React , { useCallback , useEffect , useState , useMemo } from 'react' ; import { i18n } from '@osd/i18n' ; import { EuiButtonIcon , EuiTitle , EuiSpacer } from '@elastic/eui' ; import { sortBy } from 'lodash' ; import { FormattedMessage , I18nProvider } from '@osd/i18n/react' ; import { DiscoverField } from './discover_field' ; import { DiscoverIndexPattern } from './discover_index_pattern' ; import { DiscoverFieldSearch } from './discover_field_search' ; import { IndexPatternAttributes } from '../../../../../data/common' ; import { SavedObject } from '../../../../../../core/types' ; import { FIELDS_LIMIT_SETTING } from '../../../../common' ; import { groupFields } from './lib/group_fields' ; import { IndexPatternField , IndexPattern , UI_SETTINGS } from '../../../../../data/public' ; import { getDetails } from './lib/get_details' ; import { getDefaultFieldFilter , setFieldFilterProp } from './lib/field_filter' ; import { getIndexPatternFieldList } from './lib/get_index_pattern_field_list' ; import { getServices } from '../../../opensearch_dashboards_services' ; export interface DiscoverSidebarProps { /**
     * the selected columns displayed in the doc table in discover
     */ columns : string [ ] ; /**
     * a statistics of the distribution of fields in the given hits
     */ fieldCounts : Record < string , number > ; /**
     * hits fetched from OpenSearch, displayed in the doc table
     */ hits : Array < Record < string , unknown > > ; /**
     * List of available index patterns
     */ indexPatternList : Array < SavedObject < IndexPatternAttributes > > ; /**
     * Callback function when selecting a field
     */ onAddField : ( fieldName : string ) => void ; /**
     * Callback function when adding a filter from sidebar
     */ onAddFilter : ( field : IndexPatternField | string , value : string , type : '+' | '-' ) => void ; param fieldName onRemoveField : ( fieldName : string ) => void ; /**
     * Currently selected index pattern
     */ selectedIndexPattern ? : IndexPattern ; /**
     * Callback function to select another index pattern
     */ setIndexPattern : ( id : string ) => void ; } export function DiscoverSidebar ( { columns , fieldCounts , hits , indexPatternList , onAddField , onAddFilter , onRemoveField , selectedIndexPattern , setIndexPattern , } ) { const [ showFields , setShowFields ] = useState ( false ) ; const [ fields , setFields ] = useState < IndexPatternField [ ] | null > ( null ) ; const [ fieldFilterState , setFieldFilterState ] = useState ( getDefaultFieldFilter ( ) ) ; const services = useMemo ( ( ) => getServices ( ) , [ ] ) ; useEffect ( ( ) => { const newFields = getIndexPatternFieldList ( selectedIndexPattern , fieldCounts ) ; setFields ( newFields ) ; } , [ selectedIndexPattern , fieldCounts , hits , services ] ) ; const onChangeFieldSearch = useCallback ( ( field , value ) => { const newState = setFieldFilterProp ( fieldFilterState , field , value ) ; setFieldFilterState ( newState ) ; } , [ fieldFilterState ] ) ; const getDetailsByField = useCallback ( ( ipField ) => getDetails ( ipField , hits , columns , selectedIndexPattern ) , [ hits , columns , selectedIndexPattern ] ) ; const popularLimit = services . uiSettings . get ( FIELDS_LIMIT_SETTING ) ; const useShortDots = services . uiSettings . get ( UI_SETTINGS . SHORT_DOTS_ENABLE ) ; const { selected : selectedFields , popular : popularFields , unpopular : unpopularFields , } = useMemo ( ( ) => groupFields ( fields , columns , popularLimit , fieldCounts , fieldFilterState ) , [ fields , columns , popularLimit , fieldCounts , fieldFilterState , ] ) ; const fieldTypes = useMemo ( ( ) => { const result = [ 'any' ] ; if ( Array . isArray ( fields ) ) { for ( const field of fields ) { if ( result . indexOf ( field . type ) === - 1 ) { result . push ( field . type ) ; } } } return result ; } , [ fields ] ) ; if ( ! selectedIndexPattern || ! fields ) { return null ; } return ( < I18nProvider > < section className = "sidebar-list" aria - label = { i18n . translate ( 'discover.fieldChooser.filter.indexAndFieldsSectionAriaLabel' , { defaultMessage : 'Index and fields' , } ) } > < DiscoverIndexPattern selectedIndexPattern = { selectedIndexPattern } setIndexPattern = { setIndexPattern } indexPatternList = { sortBy ( indexPatternList , ( o ) => o . attributes . title ) } /> < div className = "dscSidebar__item" > < form > < DiscoverFieldSearch onChange = { onChangeFieldSearch } value = { fieldFilterState . name } types = { fieldTypes } / > < /form> < /div> < div className = "sidebar-list" > { fields . length > 0 && ( < > < EuiTitle size = "xxxs" id = "selected_fields" > < h3 > < FormattedMessage id = "discover.fieldChooser.filter.selectedFieldsTitle" defaultMessage = "Selected fields" / > < /h3> < /EuiTitle> < EuiSpacer size = "xs" / > < ul className = "dscSidebarList dscFieldList--selected" aria - labelledby = "selected_fields" data - test - subj = { `fieldList-selected` } > { selectedFields . map ( ( field ) => { return ( < li key = { `field${ field . name }` } data - attr - field = { field . name } className = "dscSidebar__item" > < DiscoverField field = { field } indexPattern = { selectedIndexPattern } onAddField = { onAddField } onRemoveField = { onRemoveField } onAddFilter = { onAddFilter } getDetails = { getDetailsByField } selected = { true } useShortDots = { useShortDots } / > < /li>); } ) } < /ul> < div className = "euiFlexGroup euiFlexGroup--gutterMedium" > < EuiTitle size = "xxxs" id = "available_fields" className = "euiFlexItem" > < h3 > < FormattedMessage id = "discover.fieldChooser.filter.availableFieldsTitle" defaultMessage = "Available fields" / > < /h3> < /EuiTitle> < div className = "euiFlexItem euiFlexItem--flexGrowZero" > < EuiButtonIcon className = { 'visible-xs visible-sm dscFieldChooser__toggle' } iconType = { showFields ? 'arrowDown' : 'arrowRight' } onClick = { ( ) => setShowFields ( ! showFields ) } aria - label = { showFields ? i18n . translate ( 'discover.fieldChooser.filter.indexAndFieldsSectionHideAriaLabel' , { defaultMessage : 'Hide fields' , } ) : i18n . translate ( 'discover.fieldChooser.filter.indexAndFieldsSectionShowAriaLabel' , { defaultMessage : 'Show fields' , } ) } /> < /div> < /div> < />)} { popularFields . length > 0 && ( < div > < EuiTitle size = "xxxs" className = { `dscFieldListHeader ${ ! showFields ? 'hidden-sm hidden-xs' : '' }` } > < h4 style = { { fontWeight : 'normal' } } id = "available_fields_popular" > < FormattedMessage id = "discover.fieldChooser.filter.popularTitle" defaultMessage = "Popular" / > < /h4> < /EuiTitle> < ul className = { `dscFieldList dscFieldList--popular ${ ! showFields ? 'hidden-sm hidden-xs' : '' }` } aria - labelledby = "available_fields available_fields_popular" data - test - subj = { `fieldList-popular` } > { popularFields . map ( ( field ) => { return ( < li key = { `field${ field . name }` } data - attr - field = { field . name } className = "dscSidebar__item" > < DiscoverField field = { field } indexPattern = { selectedIndexPattern } onAddField = { onAddField } onRemoveField = { onRemoveField } onAddFilter = { onAddFilter } getDetails = { getDetailsByField } useShortDots = { useShortDots } / > < /li>); } ) } < /ul> < /div>)} < ul className = { `dscFieldList dscFieldList--unpopular ${ ! showFields ? 'hidden-sm hidden-xs' : '' }` } aria - labelledby = "available_fields" data - test - subj = { `fieldList-unpopular` } > { unpopularFields . map ( ( field ) => { return ( < li key = { `field${ field . name }` } data - attr - field = { field . name } className = "dscSidebar__item" > < DiscoverField field = { field } indexPattern = { selectedIndexPattern } onAddField = { onAddField } onRemoveField = { onRemoveField } onAddFilter = { onAddFilter } getDetails = { getDetailsByField } useShortDots = { useShortDots } / > < /li>); } ) } < /ul> < /div> < /section> < /I18nProvider>); }