import { EuiButtonEmpty , EuiFlexGroup , EuiFlexItem , EuiPopover , EuiResizeObserver , } from '@elastic/eui' ; import { FormattedMessage , InjectedIntl , injectI18n } from '@osd/i18n/react' ; import classNames from 'classnames' ; import React , { useState } from 'react' ; import { FilterEditor } from './filter_editor' ; import { FilterItem } from './filter_item' ; import { FilterOptions } from './filter_options' ; import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public' ; import { IIndexPattern } from '../..' ; import { buildEmptyFilter , Filter , enableFilter , disableFilter , pinFilter , toggleFilterDisabled , toggleFilterNegated , unpinFilter , UI_SETTINGS , } from '../../../common' ; interface Props { filters : Filter [ ] ; onFiltersUpdated ? : ( filters : Filter [ ] ) => void ; className : string ; indexPatterns : IIndexPattern [ ] ; intl : InjectedIntl ; } const maxFilterWidth = 600 ; function FilterBarUI ( props ) { const [ isAddFilterPopoverOpen , setIsAddFilterPopoverOpen ] = useState ( false ) ; const opensearchDashboards = useOpenSearchDashboards ( ) ; const [ filterWidth , setFilterWidth ] = useState ( maxFilterWidth ) ; const uiSettings = opensearchDashboards . services . uiSettings ; if ( ! uiSettings ) return null ; function onFiltersUpdated ( filters ) { if ( props . onFiltersUpdated ) { props . onFiltersUpdated ( filters ) ; } } function renderItems ( ) { return props . filters . map ( ( filter , i ) => ( < EuiFlexItem key = { i } grow = { false } className = "globalFilterBar__flexItem" > < FilterItem id = { `${ i }` } intl = { props . intl } filter = { filter } onUpdate = { ( newFilter ) => onUpdate ( i , newFilter ) } onRemove = { ( ) => onRemove ( i ) } indexPatterns = { props . indexPatterns } uiSettings = { uiSettings ! } / > < /EuiFlexItem>)); } function onResize ( dimensions ) { setFilterWidth ( dimensions . width ) ; } function renderAddFilter ( ) { const isPinned = uiSettings ! . get ( UI_SETTINGS . FILTERS_PINNED_BY_DEFAULT ) ; const [ indexPattern ] = props . indexPatterns ; const index = indexPattern && indexPattern . id ; const newFilter = buildEmptyFilter ( isPinned , index ) ; const button = ( < EuiButtonEmpty size = "xs" onClick = { ( ) => setIsAddFilterPopoverOpen ( true ) } data - test - subj = "addFilter" className = "globalFilterBar__addButton" > + { ' ' } < FormattedMessage id = "data.filter.filterBar.addFilterButtonLabel" defaultMessage = "Add filter" / > < /EuiButtonEmpty>); return ( < EuiFlexItem grow = { false } > < EuiPopover id = "addFilterPopover" button = { button } isOpen = { isAddFilterPopoverOpen } closePopover = { ( ) => setIsAddFilterPopoverOpen ( false ) } anchorPosition = "downLeft" withTitle panelPaddingSize = "none" ownFocus = { true } initialFocus = ".globalFilterEditor__fieldInput input" repositionOnScroll > < EuiResizeObserver onResize = { onResize } > { ( resizeRef ) => ( < div style = { { width : maxFilterWidth , maxWidth : '100%' } } ref = { resizeRef } > < EuiFlexItem style = { { width : filterWidth } } grow = { false } > < FilterEditor filter = { newFilter } indexPatterns = { props . indexPatterns } onSubmit = { onAdd } onCancel = { ( ) => setIsAddFilterPopoverOpen ( false ) } key = { JSON . stringify ( newFilter ) } / > < /EuiFlexItem> < /div>)} < /EuiResizeObserver> < /EuiPopover> < /EuiFlexItem>); } function onAdd ( filter ) { setIsAddFilterPopoverOpen ( false ) ; const filters = [ ... props . filters , filter ] ; onFiltersUpdated ( filters ) ; } function onRemove ( i ) { const filters = [ ... props . filters ] ; filters . splice ( i , 1 ) ; onFiltersUpdated ( filters ) ; } function onUpdate ( i , filter ) { const filters = [ ... props . filters ] ; filters [ i ] = filter ; onFiltersUpdated ( filters ) ; } function onEnableAll ( ) { const filters = props . filters . map ( enableFilter ) ; onFiltersUpdated ( filters ) ; } function onDisableAll ( ) { const filters = props . filters . map ( disableFilter ) ; onFiltersUpdated ( filters ) ; } function onPinAll ( ) { const filters = props . filters . map ( pinFilter ) ; onFiltersUpdated ( filters ) ; } function onUnpinAll ( ) { const filters = props . filters . map ( unpinFilter ) ; onFiltersUpdated ( filters ) ; } function onToggleAllNegated ( ) { const filters = props . filters . map ( toggleFilterNegated ) ; onFiltersUpdated ( filters ) ; } function onToggleAllDisabled ( ) { const filters = props . filters . map ( toggleFilterDisabled ) ; onFiltersUpdated ( filters ) ; } function onRemoveAll ( ) { onFiltersUpdated ( [ ] ) ; } const classes = classNames ( 'globalFilterBar' , props . className ) ; return ( < EuiFlexGroup className = "globalFilterGroup" gutterSize = "none" alignItems = "flexStart" responsive = { false } > < EuiFlexItem className = "globalFilterGroup__branch" grow = { false } > < FilterOptions onEnableAll = { onEnableAll } onDisableAll = { onDisableAll } onPinAll = { onPinAll } onUnpinAll = { onUnpinAll } onToggleAllNegated = { onToggleAllNegated } onToggleAllDisabled = { onToggleAllDisabled } onRemoveAll = { onRemoveAll } / > < /EuiFlexItem> < EuiFlexItem className = "globalFilterGroup__filterFlexItem" > < EuiFlexGroup className = { classes } wrap = { true } responsive = { false } gutterSize = "xs" alignItems = "center" > { renderItems ( ) } { renderAddFilter ( ) } < /EuiFlexGroup> < /EuiFlexItem> < /EuiFlexGroup>); } export const FilterBar = injectI18n ( FilterBarUI ) ;