import { find , template } from 'lodash' ; import { stringify } from 'query-string' ; import $ from 'jquery' ; import rison from 'rison-node' ; import '../../doc_viewer' ; import openRowHtml from './table_row/open.html' ; import detailsHtml from './table_row/details.html' ; import { dispatchRenderComplete , url } from '../../../../../../opensearch_dashboards_utils/public' ; import { DOC_HIDE_TIME_COLUMN_SETTING } from '../../../../../common' ; import cellTemplateHtml from '../components/table_row/cell.html' ; import truncateByHeightTemplateHtml from '../components/table_row/truncate_by_height.html' ; import { opensearchFilters } from '../../../../../../data/public' ; import { getServices } from '../../../../opensearch_dashboards_services' ; const TAGS_WITH_WS = />\s+</g ; /**
 * Remove all of the whitespace between html tags
 * so that inline elements don't have extra spaces.
 */ export function noWhiteSpace ( html ) { return html . replace ( TAGS_WITH_WS , '><' ) ; } const MIN_LINE_LENGTH = 20 ; interface LazyScope extends ng . IScope { [ key ] : any ; } export function createTableRowDirective ( $compile ) { const cellTemplate = template ( noWhiteSpace ( cellTemplateHtml ) ) ; const truncateByHeightTemplate = template ( noWhiteSpace ( truncateByHeightTemplateHtml ) ) ; return { restrict : 'A' , scope : { columns : '=' , filter : '=' , indexPattern : '=' , row : '=osdTableRow' , onAddColumn : '=?' , onRemoveColumn : '=?' , } , link : ( $scope , $el ) => { $el . after ( '<tr data-test-subj="docTableDetailsRow" class="osdDocTableDetails__row">' ) ; $el . empty ( ) ; let $detailsScope ; let $toggleScope ; $scope . toggleRow = ( ) => { const $detailsTr = $el . next ( ) ; $scope . open = ! $scope . open ; $detailsTr . toggle ( $scope . open ) ; if ( ! $scope . open ) { $detailsScope . $destroy ( ) ; return ; } else { $detailsScope = $scope . $new ( ) ; } $detailsTr . html ( detailsHtml ) ; $detailsScope . row = $scope . row ; $detailsScope . hit = $scope . row ; $detailsScope . uriEncodedId = encodeURIComponent ( $detailsScope . hit . _id ) ; $compile ( $detailsTr ) ( $detailsScope ) ; } ; $scope . $watchMulti ( [ 'indexPattern.timeFieldName' , 'row.highlight' , '[]columns' ] , ( ) => { createSummaryRow ( $scope . row ) ; } ) ; $scope . inlineFilter = function inlineFilter ( $event , type ) { const column = $ ( $event . currentTarget ) . data ( ) . column ; const field = $scope . indexPattern . fields . getByName ( column ) ; $scope . filter ( field , $scope . flattenedRow [ column ] , type ) ; } ; $scope . getContextAppHref = ( ) => { const globalFilters = getServices ( ) . filterManager . getGlobalFilters ( ) ; const appFilters = getServices ( ) . filterManager . getAppFilters ( ) ; const hash = stringify ( url . encodeQuery ( { _g : rison . encode ( { filters : globalFilters || [ ] , } ) , _a : rison . encode ( { columns : $scope . columns , filters : ( appFilters || [ ] ) . map ( opensearchFilters . disableFilter ) , } ) , } ) , { encode : false , sort : false } ) ; return `#/context/${ encodeURIComponent ( $scope . indexPattern . id ) }/${ encodeURIComponent ( $scope . row . _id ) }?${ hash }` ; } ; function createSummaryRow ( row ) { const indexPattern = $scope . indexPattern ; $scope . flattenedRow = indexPattern . flattenHit ( row ) ; const newHtmls = [ openRowHtml ] ; const mapping = indexPattern . fields . getByName ; const hideTimeColumn = getServices ( ) . uiSettings . get ( DOC_HIDE_TIME_COLUMN_SETTING , false ) ; if ( indexPattern . timeFieldName && ! hideTimeColumn ) { newHtmls . push ( cellTemplate ( { timefield : true , formatted : _displayField ( row , indexPattern . timeFieldName ) , filterable : mapping ( indexPattern . timeFieldName ) . filterable && $scope . filter , column : indexPattern . timeFieldName , } ) ) ; } $scope . columns . forEach ( function ( column ) { const isFilterable = mapping ( column ) && mapping ( column ) . filterable && $scope . filter ; newHtmls . push ( cellTemplate ( { timefield : false , sourcefield : column === '_source' , formatted : _displayField ( row , column , true ) , filterable : isFilterable , column , } ) ) ; } ) ; let $cells = $el . children ( ) ; newHtmls . forEach ( function ( html , i ) { const $cell = $cells . eq ( i ) ; if ( $cell . data ( 'discover:html' ) === html ) return ; const reuse = find ( $cells . slice ( i + 1 ) , function ( cell ) { return $ . data ( cell , 'discover:html' ) === html ; } ) ; const $target = reuse ? $ ( reuse ) . detach ( ) : $ ( html ) ; $target . data ( 'discover:html' , html ) ; const $before = $cells . eq ( i - 1 ) ; if ( $before . length ) { $before . after ( $target ) ; } else { $el . append ( $target ) ; } $cells = $el . children ( ) ; if ( ! reuse ) { $toggleScope = $scope . $new ( ) ; $compile ( $target ) ( $toggleScope ) ; } } ) ; if ( $scope . open ) { $detailsScope . row = row ; } $cells . filter ( ':gt(' + ( newHtmls . length - 1 ) + ')' ) . remove ( ) ; dispatchRenderComplete ( $el [ 0 ] ) ; } /**
             * Fill an element with the value of a field
             */ function _displayField ( row , fieldName , truncate = false ) { const indexPattern = $scope . indexPattern ; const text = indexPattern . formatField ( row , fieldName ) ; if ( truncate && text . length > MIN_LINE_LENGTH ) { return truncateByHeightTemplate ( { body : text , } ) ; } return text ; } } , } ; }