33 * or more contributor license agreements. Licensed under the Elastic License;
44 * you may not use this file except in compliance with the Elastic License.
55 */
6- import React , { useEffect , useState , Fragment } from 'react' ;
6+ import React , { useEffect , useState } from 'react' ;
7+ import styled from 'styled-components' ;
78import { i18n } from '@kbn/i18n' ;
89import { FormattedMessage } from '@kbn/i18n/react' ;
910import {
1011 EuiFlexGroup ,
1112 EuiFlexItem ,
12- EuiSelectable ,
13- EuiSpacer ,
13+ EuiComboBox ,
14+ EuiComboBoxOptionOption ,
1415 EuiTextColor ,
1516 EuiPortal ,
16- EuiButtonEmpty ,
17+ EuiFormRow ,
18+ EuiLink ,
1719} from '@elastic/eui' ;
1820import { Error } from '../../../components' ;
1921import { AgentConfig , PackageInfo , GetAgentConfigsResponseItem } from '../../../types' ;
@@ -23,16 +25,39 @@ import {
2325 useGetAgentConfigs ,
2426 sendGetOneAgentConfig ,
2527 useCapabilities ,
28+ useFleetStatus ,
2629} from '../../../hooks' ;
2730import { CreateAgentConfigFlyout } from '../list_page/components' ;
2831
32+ const AgentConfigWrapper = styled ( EuiFormRow ) `
33+ .euiFormRow__label {
34+ width: 100%;
35+ }
36+ ` ;
37+
38+ // Custom styling for drop down list items due to:
39+ // 1) the max-width and overflow properties is added to prevent long config
40+ // names/descriptions from overflowing the flex items
41+ // 2) max-width is built from the grow property on the flex items because the value
42+ // changes based on if Fleet is enabled/setup or not
43+ const AgentConfigNameColumn = styled ( EuiFlexItem ) `
44+ max-width: ${ ( props ) => `${ ( ( props . grow as number ) / 9 ) * 100 } %` } ;
45+ overflow: hidden;
46+ ` ;
47+ const AgentConfigDescriptionColumn = styled ( EuiFlexItem ) `
48+ max-width: ${ ( props ) => `${ ( ( props . grow as number ) / 9 ) * 100 } %` } ;
49+ overflow: hidden;
50+ ` ;
51+
2952export const StepSelectConfig : React . FunctionComponent < {
3053 pkgkey : string ;
3154 updatePackageInfo : ( packageInfo : PackageInfo | undefined ) => void ;
3255 agentConfig : AgentConfig | undefined ;
3356 updateAgentConfig : ( config : AgentConfig | undefined ) => void ;
3457 setIsLoadingSecondStep : ( isLoading : boolean ) => void ;
3558} > = ( { pkgkey, updatePackageInfo, agentConfig, updateAgentConfig, setIsLoadingSecondStep } ) => {
59+ const { isReady : isFleetReady } = useFleetStatus ( ) ;
60+
3661 // Selected config state
3762 const [ selectedConfigId , setSelectedConfigId ] = useState < string | undefined > (
3863 agentConfig ? agentConfig . id : undefined
@@ -106,6 +131,40 @@ export const StepSelectConfig: React.FunctionComponent<{
106131 }
107132 } , [ selectedConfigId , agentConfig , updateAgentConfig , setIsLoadingSecondStep ] ) ;
108133
134+ const agentConfigOptions : Array < EuiComboBoxOptionOption < string > > = packageInfoData
135+ ? agentConfigs . map ( ( agentConf ) => {
136+ const alreadyHasLimitedPackage =
137+ ( isLimitedPackage &&
138+ doesAgentConfigAlreadyIncludePackage ( agentConf , packageInfoData . response . name ) ) ||
139+ false ;
140+ return {
141+ label : agentConf . name ,
142+ value : agentConf . id ,
143+ disabled : alreadyHasLimitedPackage ,
144+ 'data-test-subj' : 'agentConfigItem' ,
145+ } ;
146+ } )
147+ : [ ] ;
148+
149+ const selectedConfigOption = agentConfigOptions . find (
150+ ( option ) => option . value === selectedConfigId
151+ ) ;
152+
153+ // Try to select default agent config
154+ useEffect ( ( ) => {
155+ if ( ! selectedConfigId && agentConfigs . length && agentConfigOptions . length ) {
156+ const defaultAgentConfig = agentConfigs . find ( ( config ) => config . is_default ) ;
157+ if ( defaultAgentConfig ) {
158+ const defaultAgentConfigOption = agentConfigOptions . find (
159+ ( option ) => option . value === defaultAgentConfig . id
160+ ) ;
161+ if ( defaultAgentConfigOption && ! defaultAgentConfigOption . disabled ) {
162+ setSelectedConfigId ( defaultAgentConfig . id ) ;
163+ }
164+ }
165+ }
166+ } , [ agentConfigs , agentConfigOptions , selectedConfigId ] ) ;
167+
109168 // Display package error if there is one
110169 if ( packageInfoError ) {
111170 return (
@@ -154,77 +213,95 @@ export const StepSelectConfig: React.FunctionComponent<{
154213 ) : null }
155214 < EuiFlexGroup direction = "column" gutterSize = "m" >
156215 < EuiFlexItem >
157- < EuiSelectable
158- searchable
159- allowExclusions = { false }
160- singleSelection = { true }
161- isLoading = { isAgentConfigsLoading || isPackageInfoLoading }
162- options = { agentConfigs . map ( ( agentConf ) => {
163- const alreadyHasLimitedPackage =
164- ( isLimitedPackage &&
165- packageInfoData &&
166- doesAgentConfigAlreadyIncludePackage ( agentConf , packageInfoData . response . name ) ) ||
167- false ;
168- return {
169- label : agentConf . name ,
170- key : agentConf . id ,
171- checked : selectedConfigId === agentConf . id ? 'on' : undefined ,
172- disabled : alreadyHasLimitedPackage ,
173- 'data-test-subj' : 'agentConfigItem' ,
174- } ;
175- } ) }
176- renderOption = { ( option ) => (
177- < EuiFlexGroup >
178- < EuiFlexItem grow = { false } > { option . label } </ EuiFlexItem >
216+ < AgentConfigWrapper
217+ fullWidth = { true }
218+ label = {
219+ < EuiFlexGroup justifyContent = "spaceBetween" >
179220 < EuiFlexItem >
180- < EuiTextColor color = "subdued" >
181- { agentConfigsById [ option . key ! ] . description }
182- </ EuiTextColor >
221+ < FormattedMessage
222+ id = "xpack.ingestManager.createPackageConfig.StepSelectConfig.agentConfigLabel"
223+ defaultMessage = "Agent configuration"
224+ />
183225 </ EuiFlexItem >
184226 < EuiFlexItem grow = { false } >
185- < EuiTextColor color = "subdued" >
186- < FormattedMessage
187- id = "xpack.ingestManager.createPackageConfig.StepSelectConfig.agentConfigAgentsCountText"
188- defaultMessage = "{count, plural, one {# agent} other {# agents}}"
189- values = { {
190- count : agentConfigsById [ option . key ! ] . agents || 0 ,
191- } }
192- />
193- </ EuiTextColor >
227+ < div >
228+ < EuiLink
229+ disabled = { ! hasWriteCapabilites }
230+ onClick = { ( ) => setIsCreateAgentConfigFlyoutOpen ( true ) }
231+ >
232+ < FormattedMessage
233+ id = "xpack.ingestManager.createPackageConfig.StepSelectConfig.addButton"
234+ defaultMessage = "Create agent configuration"
235+ />
236+ </ EuiLink >
237+ </ div >
194238 </ EuiFlexItem >
195239 </ EuiFlexGroup >
196- ) }
197- listProps = { {
198- bordered : true ,
199- } }
200- searchProps = { {
201- placeholder : i18n . translate (
202- 'xpack.ingestManager.createPackageConfig.StepSelectConfig.filterAgentConfigsInputPlaceholder' ,
240+ }
241+ helpText = {
242+ isFleetReady && selectedConfigId ? (
243+ < FormattedMessage
244+ id = "xpack.ingestManager.createPackageConfig.StepSelectConfig.agentConfigAgentsDescriptionText"
245+ defaultMessage = "{count, plural, one {# agent} other {# agents}} are enrolled with the selected agent configuration."
246+ values = { {
247+ count : agentConfigsById [ selectedConfigId ] . agents || 0 ,
248+ } }
249+ />
250+ ) : null
251+ }
252+ >
253+ < EuiComboBox
254+ placeholder = { i18n . translate (
255+ 'xpack.ingestManager.createPackageConfig.StepSelectConfig.agentConfigPlaceholderText' ,
203256 {
204- defaultMessage : 'Search for agent configurations ' ,
257+ defaultMessage : 'Select an agent configuration to add this integration to ' ,
205258 }
206- ) ,
207- } }
208- height = { 180 }
209- onChange = { ( options ) => {
210- const selectedOption = options . find ( ( option ) => option . checked === 'on' ) ;
211- if ( selectedOption ) {
212- if ( selectedOption . key !== selectedConfigId ) {
213- setSelectedConfigId ( selectedOption . key ) ;
259+ ) }
260+ singleSelection = { { asPlainText : true } }
261+ isClearable = { false }
262+ fullWidth = { true }
263+ isLoading = { isAgentConfigsLoading || isPackageInfoLoading }
264+ options = { agentConfigOptions }
265+ renderOption = { ( option : EuiComboBoxOptionOption < string > ) => {
266+ return (
267+ < EuiFlexGroup >
268+ < AgentConfigNameColumn grow = { 2 } >
269+ < span className = "eui-textTruncate" > { option . label } </ span >
270+ </ AgentConfigNameColumn >
271+ < AgentConfigDescriptionColumn grow = { isFleetReady ? 5 : 7 } >
272+ < EuiTextColor className = "eui-textTruncate" color = "subdued" >
273+ { agentConfigsById [ option . value ! ] . description }
274+ </ EuiTextColor >
275+ </ AgentConfigDescriptionColumn >
276+ { isFleetReady ? (
277+ < EuiFlexItem grow = { 2 } className = "eui-textRight" >
278+ < EuiTextColor color = "subdued" >
279+ < FormattedMessage
280+ id = "xpack.ingestManager.createPackageConfig.StepSelectConfig.agentConfigAgentsCountText"
281+ defaultMessage = "{count, plural, one {# agent} other {# agents}} enrolled"
282+ values = { {
283+ count : agentConfigsById [ option . value ! ] . agents || 0 ,
284+ } }
285+ />
286+ </ EuiTextColor >
287+ </ EuiFlexItem >
288+ ) : null }
289+ </ EuiFlexGroup >
290+ ) ;
291+ } }
292+ selectedOptions = { selectedConfigOption ? [ selectedConfigOption ] : [ ] }
293+ onChange = { ( options ) => {
294+ const selectedOption = options [ 0 ] || undefined ;
295+ if ( selectedOption ) {
296+ if ( selectedOption . value !== selectedConfigId ) {
297+ setSelectedConfigId ( selectedOption . value ) ;
298+ }
299+ } else {
300+ setSelectedConfigId ( undefined ) ;
214301 }
215- } else {
216- setSelectedConfigId ( undefined ) ;
217- }
218- } }
219- >
220- { ( list , search ) => (
221- < Fragment >
222- { search }
223- < EuiSpacer size = "m" />
224- { list }
225- </ Fragment >
226- ) }
227- </ EuiSelectable >
302+ } }
303+ />
304+ </ AgentConfigWrapper >
228305 </ EuiFlexItem >
229306 { /* Display selected agent config error if there is one */ }
230307 { selectedConfigError ? (
@@ -240,22 +317,6 @@ export const StepSelectConfig: React.FunctionComponent<{
240317 />
241318 </ EuiFlexItem >
242319 ) : null }
243- < EuiFlexItem >
244- < div >
245- < EuiButtonEmpty
246- iconType = "plusInCircle"
247- isDisabled = { ! hasWriteCapabilites }
248- onClick = { ( ) => setIsCreateAgentConfigFlyoutOpen ( true ) }
249- flush = "left"
250- size = "s"
251- >
252- < FormattedMessage
253- id = "xpack.ingestManager.createPackageConfig.StepSelectConfig.addButton"
254- defaultMessage = "New agent configuration"
255- />
256- </ EuiButtonEmpty >
257- </ div >
258- </ EuiFlexItem >
259320 </ EuiFlexGroup >
260321 </ >
261322 ) ;
0 commit comments