1616 * specific language governing permissions and limitations
1717 * under the License.
1818 */
19- import React from 'react' ;
20- import { EuiButton } from '@elastic/eui' ;
19+ import React , { useState } from 'react' ;
20+ import { EuiPopover , EuiPopoverTitle , EuiButtonIcon , EuiToolTip } from '@elastic/eui' ;
2121import { i18n } from '@kbn/i18n' ;
2222import { DiscoverFieldDetails } from './discover_field_details' ;
23- import { FieldIcon } from '../../../../../kibana_react/public' ;
23+ import { FieldIcon , FieldButton } from '../../../../../kibana_react/public' ;
2424import { FieldDetails } from './types' ;
2525import { IndexPatternField , IndexPattern } from '../../../../../data/public' ;
2626import { shortenDottedString } from '../../helpers' ;
2727import { getFieldTypeName } from './lib/get_field_type_name' ;
28+ import './discover_field.scss' ;
2829
2930export interface DiscoverFieldProps {
3031 /**
@@ -48,14 +49,6 @@ export interface DiscoverFieldProps {
4849 * @param fieldName
4950 */
5051 onRemoveField : ( fieldName : string ) => void ;
51- /**
52- * Callback to hide/show details, buckets of the field
53- */
54- onShowDetails : ( show : boolean , field : IndexPatternField ) => void ;
55- /**
56- * Determines, whether details of the field are displayed
57- */
58- showDetails : boolean ;
5952 /**
6053 * Retrieve details data for the field
6154 */
@@ -76,22 +69,14 @@ export function DiscoverField({
7669 onAddField,
7770 onRemoveField,
7871 onAddFilter,
79- onShowDetails,
80- showDetails,
8172 getDetails,
8273 selected,
8374 useShortDots,
8475} : DiscoverFieldProps ) {
85- const addLabel = i18n . translate ( 'discover.fieldChooser.discoverField.addButtonLabel' , {
86- defaultMessage : 'Add' ,
87- } ) ;
8876 const addLabelAria = i18n . translate ( 'discover.fieldChooser.discoverField.addButtonAriaLabel' , {
8977 defaultMessage : 'Add {field} to table' ,
9078 values : { field : field . name } ,
9179 } ) ;
92- const removeLabel = i18n . translate ( 'discover.fieldChooser.discoverField.removeButtonLabel' , {
93- defaultMessage : 'Remove' ,
94- } ) ;
9580 const removeLabelAria = i18n . translate (
9681 'discover.fieldChooser.discoverField.removeButtonAriaLabel' ,
9782 {
@@ -100,6 +85,8 @@ export function DiscoverField({
10085 }
10186 ) ;
10287
88+ const [ infoIsOpen , setOpen ] = useState ( false ) ;
89+
10390 const toggleDisplay = ( f : IndexPatternField ) => {
10491 if ( selected ) {
10592 onRemoveField ( f . name ) ;
@@ -108,78 +95,114 @@ export function DiscoverField({
10895 }
10996 } ;
11097
98+ function togglePopover ( ) {
99+ setOpen ( ! infoIsOpen ) ;
100+ }
101+
111102 function wrapOnDot ( str ?: string ) {
112103 // u200B is a non-width white-space character, which allows
113104 // the browser to efficiently word-wrap right after the dot
114105 // without us having to draw a lot of extra DOM elements, etc
115106 return str ? str . replace ( / \. / g, '.\u200B' ) : '' ;
116107 }
117108
118- return (
119- < >
120- < div
121- className = { `dscSidebarField dscSidebarItem ${ showDetails ? 'dscSidebarItem--active' : '' } ` }
122- tabIndex = { 0 }
123- onClick = { ( ) => onShowDetails ( ! showDetails , field ) }
124- onKeyPress = { ( ) => onShowDetails ( ! showDetails , field ) }
125- data-test-subj = { `field-${ field . name } -showDetails` }
109+ const dscFieldIcon = (
110+ < FieldIcon type = { field . type } label = { getFieldTypeName ( field . type ) } scripted = { field . scripted } />
111+ ) ;
112+
113+ const fieldName = (
114+ < span
115+ data-test-subj = { `field-${ field . name } ` }
116+ title = { field . name }
117+ className = "dscSidebarField__name"
118+ >
119+ { useShortDots ? wrapOnDot ( shortenDottedString ( field . name ) ) : wrapOnDot ( field . displayName ) }
120+ </ span >
121+ ) ;
122+
123+ let actionButton ;
124+ if ( field . name !== '_source' && ! selected ) {
125+ actionButton = (
126+ < EuiToolTip
127+ delay = "long"
128+ content = { i18n . translate ( 'discover.fieldChooser.discoverField.addFieldTooltip' , {
129+ defaultMessage : 'Add field as column' ,
130+ } ) }
131+ >
132+ < EuiButtonIcon
133+ iconType = "plusInCircleFilled"
134+ className = "dscSidebarItem__action"
135+ onClick = { ( ev : React . MouseEvent < HTMLButtonElement > ) => {
136+ ev . preventDefault ( ) ;
137+ ev . stopPropagation ( ) ;
138+ toggleDisplay ( field ) ;
139+ } }
140+ data-test-subj = { `fieldToggle-${ field . name } ` }
141+ aria-label = { addLabelAria }
142+ />
143+ </ EuiToolTip >
144+ ) ;
145+ } else if ( field . name !== '_source' && selected ) {
146+ actionButton = (
147+ < EuiToolTip
148+ delay = "long"
149+ content = { i18n . translate ( 'discover.fieldChooser.discoverField.removeFieldTooltip' , {
150+ defaultMessage : 'Remove field from table' ,
151+ } ) }
126152 >
127- < span className = "dscSidebarField__fieldIcon" >
128- < FieldIcon
129- type = { field . type }
130- label = { getFieldTypeName ( field . type ) }
131- scripted = { field . scripted }
132- />
133- </ span >
134- < span
135- data-test-subj = { `field-${ field . name } ` }
136- title = { field . name }
137- className = "dscSidebarField__name"
138- >
139- { useShortDots ? wrapOnDot ( shortenDottedString ( field . name ) ) : wrapOnDot ( field . displayName ) }
140- </ span >
141- < span >
142- { field . name !== '_source' && ! selected && (
143- < EuiButton
144- fill
145- size = "s"
146- className = "dscSidebarItem__action"
147- onClick = { ( ev : React . MouseEvent < HTMLButtonElement > ) => {
148- ev . preventDefault ( ) ;
149- ev . stopPropagation ( ) ;
150- toggleDisplay ( field ) ;
151- } }
152- data-test-subj = { `fieldToggle-${ field . name } ` }
153- arial-label = { addLabelAria }
154- >
155- { addLabel }
156- </ EuiButton >
157- ) }
158- { field . name !== '_source' && selected && (
159- < EuiButton
160- color = "danger"
161- className = "dscSidebarItem__action"
162- onClick = { ( ev : React . MouseEvent < HTMLButtonElement > ) => {
163- ev . preventDefault ( ) ;
164- ev . stopPropagation ( ) ;
165- toggleDisplay ( field ) ;
166- } }
167- data-test-subj = { `fieldToggle-${ field . name } ` }
168- arial-label = { removeLabelAria }
169- >
170- { removeLabel }
171- </ EuiButton >
172- ) }
173- </ span >
174- </ div >
175- { showDetails && (
153+ < EuiButtonIcon
154+ color = "danger"
155+ iconType = "cross"
156+ className = "dscSidebarItem__action"
157+ onClick = { ( ev : React . MouseEvent < HTMLButtonElement > ) => {
158+ ev . preventDefault ( ) ;
159+ ev . stopPropagation ( ) ;
160+ toggleDisplay ( field ) ;
161+ } }
162+ data-test-subj = { `fieldToggle-${ field . name } ` }
163+ aria-label = { removeLabelAria }
164+ />
165+ </ EuiToolTip >
166+ ) ;
167+ }
168+
169+ return (
170+ < EuiPopover
171+ ownFocus
172+ display = "block"
173+ button = {
174+ < FieldButton
175+ size = "s"
176+ className = "dscSidebarItem"
177+ isActive = { infoIsOpen }
178+ onClick = { ( ) => {
179+ togglePopover ( ) ;
180+ } }
181+ buttonProps = { { 'data-test-subj' : `field-${ field . name } -showDetails` } }
182+ fieldIcon = { dscFieldIcon }
183+ fieldAction = { actionButton }
184+ fieldName = { fieldName }
185+ />
186+ }
187+ isOpen = { infoIsOpen }
188+ closePopover = { ( ) => setOpen ( false ) }
189+ anchorPosition = "rightUp"
190+ panelClassName = "dscSidebarItem__fieldPopoverPanel"
191+ >
192+ < EuiPopoverTitle >
193+ { ' ' }
194+ { i18n . translate ( 'discover.fieldChooser.discoverField.fieldTopValuesLabel' , {
195+ defaultMessage : 'Top 5 values' ,
196+ } ) }
197+ </ EuiPopoverTitle >
198+ { infoIsOpen && (
176199 < DiscoverFieldDetails
177200 indexPattern = { indexPattern }
178201 field = { field }
179202 details = { getDetails ( field ) }
180203 onAddFilter = { onAddFilter }
181204 />
182205 ) }
183- </ >
206+ </ EuiPopover >
184207 ) ;
185208}
0 commit comments