import { get } from 'lodash' ; import { i18n } from '@osd/i18n' ; import { OSD_FIELD_TYPES , UI_SETTINGS } from '../../../../common' ; import { AggTypesDependencies } from '../agg_types' ; import { BaseAggParams } from '../types' ; import { BucketAggType , IBucketAggConfig } from './bucket_agg_type' ; import { createFilterHistogram } from './create_filter/histogram' ; import { BUCKET_TYPES } from './bucket_agg_types' ; import { ExtendedBounds } from './lib/extended_bounds' ; import { isAutoInterval , autoInterval } from './_interval_options' ; import { calculateHistogramInterval } from './lib/histogram_calculate_interval' ; export interface AutoBounds { min : number ; max : number ; } export interface HistogramBucketAggDependencies { getConfig : < T = any > ( key : string ) => T ; getFieldFormatsStart : AggTypesDependencies [ 'getFieldFormatsStart' ] ; } export interface IBucketHistogramAggConfig extends IBucketAggConfig { setAutoBounds : ( bounds : AutoBounds ) => void ; getAutoBounds : ( ) => AutoBounds ; } export interface AggParamsHistogram extends BaseAggParams { field : string ; interval : string ; maxBars ? : number ; intervalBase ? : number ; min_doc_count ? : boolean ; has_extended_bounds ? : boolean ; extended_bounds ? : ExtendedBounds ; } export const getHistogramBucketAgg = ( { getConfig , getFieldFormatsStart , } ) => new BucketAggType < IBucketHistogramAggConfig > ( { name : BUCKET_TYPES . HISTOGRAM , title : i18n . translate ( 'data.search.aggs.buckets.histogramTitle' , { defaultMessage : 'Histogram' , } ) , ordered : { } , makeLabel ( aggConfig ) { return aggConfig . getFieldDisplayName ( ) ; } , createFilter : createFilterHistogram ( getFieldFormatsStart ) , decorateAggConfig ( ) { let autoBounds ; return { setAutoBounds : { configurable : true , value ( newValue ) { autoBounds = newValue ; } , } , getAutoBounds : { configurable : true , value ( ) { return autoBounds ; } , } , } ; } , params : [ { name : 'field' , type : 'field' , filterFieldTypes : OSD_FIELD_TYPES . NUMBER , } , { name : 'intervalBase' , default : null , write : ( ) => { } , } , { name : 'interval' , default : autoInterval , modifyAggConfigOnSearchRequestStart ( aggConfig , searchSource , options ) { const field = aggConfig . getField ( ) ; const aggBody = field . scripted ? { script : { source : field . script , lang : field . lang } } : { field : field . name } ; const childSearchSource = searchSource . createChild ( ) . setField ( 'size' , 0 ) . setField ( 'aggs' , { maxAgg : { max : aggBody , } , minAgg : { min : aggBody , } , } ) ; return childSearchSource . fetch ( options ) . then ( ( resp ) => { const min = resp . aggregations ?. minAgg ?. value ?? 0 ; const max = resp . aggregations ?. maxAgg ?. value ?? 0 ; aggConfig . setAutoBounds ( { min , max , } ) ; } ) . catch ( ( e ) => { if ( e . name === 'AbortError' ) return ; throw new Error ( i18n . translate ( 'data.search.aggs.histogram.missingMaxMinValuesWarning' , { defaultMessage : 'Unable to retrieve max and min values to auto-scale histogram buckets. This may lead to poor visualization performance.' , } ) ) ; } ) ; } , write ( aggConfig , output ) { const values = aggConfig . getAutoBounds ( ) ; output . params . interval = calculateHistogramInterval ( { values , interval : aggConfig . params . interval , maxBucketsUiSettings : getConfig ( UI_SETTINGS . HISTOGRAM_MAX_BARS ) , maxBucketsUserInput : aggConfig . params . maxBars , intervalBase : aggConfig . params . intervalBase , esTypes : aggConfig . params . field ?. spec ?. esTypes || [ ] , } ) ; } , } , { name : 'maxBars' , shouldShow ( agg ) { return isAutoInterval ( get ( agg , 'params.interval' ) ) ; } , write : ( ) => { } , } , { name : 'min_doc_count' , default : false , write ( aggConfig , output ) { if ( aggConfig . params . min_doc_count ) { output . params . min_doc_count = 0 ; } else { output . params . min_doc_count = 1 ; } } , } , { name : 'has_extended_bounds' , default : false , write : ( ) => { } , } , { name : 'extended_bounds' , default : { min : '' , max : '' , } , write ( aggConfig , output ) { const { min , max } = aggConfig . params . extended_bounds ; if ( aggConfig . params . has_extended_bounds && ( min || min === 0 ) && ( max || max === 0 ) ) { output . params . extended_bounds = { min , max } ; } } , shouldShow : ( aggConfig ) => aggConfig . params . has_extended_bounds , } , ] , } ) ;