import _ from 'lodash' ; import { Subject } from 'rxjs' ; import { IUiSettingsClient } from 'src/core/public' ; import { sortFilters } from './lib/sort_filters' ; import { mapAndFlattenFilters } from './lib/map_and_flatten_filters' ; import { onlyDisabledFiltersChanged } from './lib/only_disabled' ; import { PartitionedFilters } from './types' ; import { FilterStateStore , Filter , uniqFilters , isFilterPinned , compareFilters , COMPARE_ALL_OPTIONS , UI_SETTINGS , } from '../../../common' ; export class FilterManager { private filters : Filter [ ] = [ ] ; private updated$ : Subject < void > = new Subject ( ) ; private fetch$ : Subject < void > = new Subject ( ) ; private uiSettings : IUiSettingsClient ; constructor ( uiSettings ) { this . uiSettings = uiSettings ; } private mergeIncomingFilters ( partitionedFilters ) { const globalFilters = partitionedFilters . globalFilters ; const appFilters = partitionedFilters . appFilters ; const cleanedAppFilters = [ ] ; _ . each ( appFilters , function ( filter , i ) { const match = _ . find ( globalFilters , function ( globalFilter ) { return compareFilters ( globalFilter , filter ) ; } ) ; if ( ! match ) { return cleanedAppFilters . push ( filter ) ; } _ . assignIn ( match . meta , filter . meta ) ; } ) ; return FilterManager . mergeFilters ( cleanedAppFilters , globalFilters ) ; } private static mergeFilters ( appFilters , globalFilters ) { return uniqFilters ( appFilters . reverse ( ) . concat ( globalFilters . reverse ( ) ) ) . reverse ( ) ; } private static partitionFilters ( filters ) { const [ globalFilters , appFilters ] = _ . partition ( filters , isFilterPinned ) ; return { globalFilters , appFilters , } ; } private handleStateUpdate ( newFilters ) { newFilters . sort ( sortFilters ) ; const filtersUpdated = ! compareFilters ( this . filters , newFilters , COMPARE_ALL_OPTIONS ) ; const updatedOnlyDisabledFilters = onlyDisabledFiltersChanged ( newFilters , this . filters ) ; this . filters = newFilters ; if ( filtersUpdated ) { this . updated$ . next ( ) ; if ( ! updatedOnlyDisabledFilters ) { this . fetch$ . next ( ) ; } } } public getFilters ( ) { return _ . cloneDeep ( this . filters ) ; } public getAppFilters ( ) { const { appFilters } = this . getPartitionedFilters ( ) ; return appFilters ; } public getGlobalFilters ( ) { const { globalFilters } = this . getPartitionedFilters ( ) ; return globalFilters ; } public getPartitionedFilters ( ) { return FilterManager . partitionFilters ( this . getFilters ( ) ) ; } public getUpdates$ ( ) { return this . updated$ . asObservable ( ) ; } public getFetches$ ( ) { return this . fetch$ . asObservable ( ) ; } public addFilters ( filters , pinFilterStatus = this . uiSettings . get ( UI_SETTINGS . FILTERS_PINNED_BY_DEFAULT ) ) { if ( ! Array . isArray ( filters ) ) { filters = [ filters ] ; } if ( filters . length === 0 ) { return ; } const store = pinFilterStatus ? FilterStateStore . GLOBAL_STATE : FilterStateStore . APP_STATE ; FilterManager . setFiltersStore ( filters , store ) ; const mappedFilters = mapAndFlattenFilters ( filters ) ; const newPartitionedFilters = FilterManager . partitionFilters ( mappedFilters ) ; const currentFilters = this . getPartitionedFilters ( ) ; currentFilters . appFilters . push ( ... newPartitionedFilters . appFilters ) ; currentFilters . globalFilters . push ( ... newPartitionedFilters . globalFilters ) ; const newFilters = this . mergeIncomingFilters ( currentFilters ) ; this . handleStateUpdate ( newFilters ) ; } public setFilters ( newFilters , pinFilterStatus = this . uiSettings . get ( UI_SETTINGS . FILTERS_PINNED_BY_DEFAULT ) ) { const store = pinFilterStatus ? FilterStateStore . GLOBAL_STATE : FilterStateStore . APP_STATE ; FilterManager . setFiltersStore ( newFilters , store ) ; const mappedFilters = mapAndFlattenFilters ( newFilters ) ; const newPartitionedFilters = FilterManager . partitionFilters ( mappedFilters ) ; const mergedFilters = this . mergeIncomingFilters ( newPartitionedFilters ) ; this . handleStateUpdate ( mergedFilters ) ; } param newGlobalFilters public setGlobalFilters ( newGlobalFilters ) { newGlobalFilters = mapAndFlattenFilters ( newGlobalFilters ) ; FilterManager . setFiltersStore ( newGlobalFilters , FilterStateStore . GLOBAL_STATE , true ) ; const { appFilters } = this . getPartitionedFilters ( ) ; const newFilters = this . mergeIncomingFilters ( { appFilters , globalFilters : newGlobalFilters , } ) ; this . handleStateUpdate ( newFilters ) ; } param newAppFilters public setAppFilters ( newAppFilters ) { newAppFilters = mapAndFlattenFilters ( newAppFilters ) ; FilterManager . setFiltersStore ( newAppFilters , FilterStateStore . APP_STATE , true ) ; const { globalFilters } = this . getPartitionedFilters ( ) ; const newFilters = this . mergeIncomingFilters ( { globalFilters , appFilters : newAppFilters , } ) ; this . handleStateUpdate ( newFilters ) ; } public removeFilter ( filter ) { const filterIndex = _ . findIndex ( this . filters , ( item ) => { return _ . isEqual ( item . meta , filter . meta ) && _ . isEqual ( item . query , filter . query ) ; } ) ; if ( filterIndex >= 0 ) { const newFilters = _ . cloneDeep ( this . filters ) ; newFilters . splice ( filterIndex , 1 ) ; this . handleStateUpdate ( newFilters ) ; } } public removeAll ( ) { this . setFilters ( [ ] ) ; } public static setFiltersStore ( filters , store , shouldOverrideStore = false ) { _ . map ( filters , ( filter ) => { if ( shouldOverrideStore || filter . $state === undefined ) { filter . $state = { store } ; } } ) ; } }