Skip to content

Commit 6187fa6

Browse files
[Ingest Manager] Convert select agent config step to use combo box (#73172) (#73394)
* Initial pass at using combo box instead of selectable for agent configs * Hide agent count messaging if fleet isn't set up * Fix types * Fix i18n * Fix i18n again * Add comment explaining styling Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
1 parent db26c01 commit 6187fa6

File tree

4 files changed

+145
-86
lines changed

4 files changed

+145
-86
lines changed

x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx

Lines changed: 144 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,19 @@
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';
78
import { i18n } from '@kbn/i18n';
89
import { FormattedMessage } from '@kbn/i18n/react';
910
import {
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';
1820
import { Error } from '../../../components';
1921
import { AgentConfig, PackageInfo, GetAgentConfigsResponseItem } from '../../../types';
@@ -23,16 +25,39 @@ import {
2325
useGetAgentConfigs,
2426
sendGetOneAgentConfig,
2527
useCapabilities,
28+
useFleetStatus,
2629
} from '../../../hooks';
2730
import { 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+
2952
export 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
);

x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/list_page/components/create_config.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ export const CreateAgentConfigFlyout: React.FunctionComponent<Props> = ({
160160
);
161161

162162
return (
163-
<FlyoutWithHigherZIndex onClose={onClose} size="l" maxWidth={400} {...restOfProps}>
163+
<FlyoutWithHigherZIndex onClose={() => onClose()} size="l" maxWidth={400} {...restOfProps}>
164164
{header}
165165
{body}
166166
{footer}

x-pack/plugins/translations/translations/ja-JP.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8125,7 +8125,6 @@
81258125
"xpack.ingestManager.createPackageConfig.StepSelectConfig.errorLoadingAgentConfigsTitle": "エージェント構成の読み込みエラー",
81268126
"xpack.ingestManager.createPackageConfig.StepSelectConfig.errorLoadingPackageTitle": "パッケージ情報の読み込みエラー",
81278127
"xpack.ingestManager.createPackageConfig.StepSelectConfig.errorLoadingSelectedAgentConfigTitle": "選択したエージェント構成の読み込みエラー",
8128-
"xpack.ingestManager.createPackageConfig.StepSelectConfig.filterAgentConfigsInputPlaceholder": "エージェント構成の検索",
81298128
"xpack.ingestManager.createPackageConfig.stepSelectPackage.errorLoadingConfigTitle": "エージェント構成情報の読み込みエラー",
81308129
"xpack.ingestManager.createPackageConfig.stepSelectPackage.errorLoadingPackagesTitle": "統合の読み込みエラー",
81318130
"xpack.ingestManager.createPackageConfig.stepSelectPackage.errorLoadingSelectedPackageTitle": "選択した統合の読み込みエラー",

x-pack/plugins/translations/translations/zh-CN.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8129,7 +8129,6 @@
81298129
"xpack.ingestManager.createPackageConfig.StepSelectConfig.errorLoadingAgentConfigsTitle": "加载代理配置时出错",
81308130
"xpack.ingestManager.createPackageConfig.StepSelectConfig.errorLoadingPackageTitle": "加载软件包信息时出错",
81318131
"xpack.ingestManager.createPackageConfig.StepSelectConfig.errorLoadingSelectedAgentConfigTitle": "加载选定代理配置时出错",
8132-
"xpack.ingestManager.createPackageConfig.StepSelectConfig.filterAgentConfigsInputPlaceholder": "搜索代理配置",
81338132
"xpack.ingestManager.createPackageConfig.stepSelectPackage.errorLoadingConfigTitle": "加载代理配置信息时出错",
81348133
"xpack.ingestManager.createPackageConfig.stepSelectPackage.errorLoadingPackagesTitle": "加载集成时出错",
81358134
"xpack.ingestManager.createPackageConfig.stepSelectPackage.errorLoadingSelectedPackageTitle": "加载选定集成时出错",

0 commit comments

Comments
 (0)