From 9db03e2b0c468a83f63e3bfd69bdbb650a71eb5a Mon Sep 17 00:00:00 2001 From: Jen Huang Date: Wed, 22 Jul 2020 18:43:03 -0700 Subject: [PATCH 1/6] Initial pass at using combo box instead of selectable for agent configs --- .../step_select_config.tsx | 210 +++++++++++------- .../list_page/components/create_config.tsx | 2 +- 2 files changed, 131 insertions(+), 81 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx index 91c80b7eee4c8..63274757313b2 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx @@ -4,16 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ import React, { useEffect, useState, Fragment } from 'react'; +import styled from 'styled-components'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiFlexGroup, EuiFlexItem, - EuiSelectable, + EuiComboBox, EuiSpacer, EuiTextColor, EuiPortal, EuiButtonEmpty, + EuiFormRow, + EuiLink, } from '@elastic/eui'; import { Error } from '../../../components'; import { AgentConfig, PackageInfo, GetAgentConfigsResponseItem } from '../../../types'; @@ -26,6 +29,22 @@ import { } from '../../../hooks'; import { CreateAgentConfigFlyout } from '../list_page/components'; +const AgentConfigWrapper = styled(EuiFormRow)` + .euiFormRow__label { + width: 100%; + } +`; + +const AgentConfigNameColumn = styled(EuiFlexItem)` + max-width: ${(2 / 9) * 100}%; + overflow: hidden; +`; + +const AgentConfigDescriptionColumn = styled(EuiFlexItem)` + max-width: ${(5 / 9) * 100}%; + overflow: hidden; +`; + export const StepSelectConfig: React.FunctionComponent<{ pkgkey: string; updatePackageInfo: (packageInfo: PackageInfo | undefined) => void; @@ -106,6 +125,38 @@ export const StepSelectConfig: React.FunctionComponent<{ } }, [selectedConfigId, agentConfig, updateAgentConfig, setIsLoadingSecondStep]); + const agentConfigOptions = packageInfoData + ? agentConfigs.map((agentConf) => { + const alreadyHasLimitedPackage = + (isLimitedPackage && + doesAgentConfigAlreadyIncludePackage(agentConf, packageInfoData.response.name)) || + false; + return { + label: agentConf.name, + key: agentConf.id, + disabled: alreadyHasLimitedPackage, + 'data-test-subj': 'agentConfigItem', + }; + }) + : []; + + const selectedConfigOption = agentConfigOptions.find((option) => option.key === selectedConfigId); + + // Try to select default agent config + useEffect(() => { + if (!selectedConfigId && agentConfigs.length && agentConfigOptions.length) { + const defaultAgentConfig = agentConfigs.find((config) => config.is_default); + if (defaultAgentConfig) { + const defaultAgentConfigOption = agentConfigOptions.find( + (option) => option.key === defaultAgentConfig.id + ); + if (defaultAgentConfigOption && !defaultAgentConfigOption.disabled) { + setSelectedConfigId(defaultAgentConfig.id); + } + } + } + }, [agentConfigs, agentConfigOptions, selectedConfigId]); + // Display package error if there is one if (packageInfoError) { return ( @@ -154,77 +205,92 @@ export const StepSelectConfig: React.FunctionComponent<{ ) : null} - { - const alreadyHasLimitedPackage = - (isLimitedPackage && - packageInfoData && - doesAgentConfigAlreadyIncludePackage(agentConf, packageInfoData.response.name)) || - false; - return { - label: agentConf.name, - key: agentConf.id, - checked: selectedConfigId === agentConf.id ? 'on' : undefined, - disabled: alreadyHasLimitedPackage, - 'data-test-subj': 'agentConfigItem', - }; - })} - renderOption={(option) => ( - - {option.label} + - - {agentConfigsById[option.key!].description} - + - - - +
+ setIsCreateAgentConfigFlyoutOpen(true)} + > + + +
- )} - listProps={{ - bordered: true, - }} - searchProps={{ - placeholder: i18n.translate( - 'xpack.ingestManager.createPackageConfig.StepSelectConfig.filterAgentConfigsInputPlaceholder', + } + helpText={ + selectedConfigId ? ( + + ) : null + } + > + { - const selectedOption = options.find((option) => option.checked === 'on'); - if (selectedOption) { - if (selectedOption.key !== selectedConfigId) { - setSelectedConfigId(selectedOption.key); + )} + singleSelection={{ asPlainText: true }} + fullWidth={true} + isLoading={isAgentConfigsLoading || isPackageInfoLoading} + options={agentConfigOptions} + renderOption={(option) => { + return ( + + + {option.label} + + + + {agentConfigsById[option.key!].description} + + + + + + + + + ); + }} + selectedOptions={selectedConfigOption ? [selectedConfigOption] : []} + onChange={(options) => { + const selectedOption = options[0] || undefined; + if (selectedOption) { + if (selectedOption.key !== selectedConfigId) { + setSelectedConfigId(selectedOption.key); + } + } else { + setSelectedConfigId(undefined); } - } else { - setSelectedConfigId(undefined); - } - }} - > - {(list, search) => ( - - {search} - - {list} - - )} -
+ }} + /> +
{/* Display selected agent config error if there is one */} {selectedConfigError ? ( @@ -240,22 +306,6 @@ export const StepSelectConfig: React.FunctionComponent<{ /> ) : null} - -
- setIsCreateAgentConfigFlyoutOpen(true)} - flush="left" - size="s" - > - - -
-
); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/list_page/components/create_config.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/list_page/components/create_config.tsx index 37fce340da6ea..4edfbe1f416c7 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/list_page/components/create_config.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/list_page/components/create_config.tsx @@ -156,7 +156,7 @@ export const CreateAgentConfigFlyout: React.FunctionComponent = ({ ); return ( - + onClose()} size="l" maxWidth={400} {...restOfProps}> {header} {body} {footer} From d368dc558d230adb4455b8b4f04d6c0764b46641 Mon Sep 17 00:00:00 2001 From: Jen Huang Date: Thu, 23 Jul 2020 15:20:16 -0700 Subject: [PATCH 2/6] Hide agent count messaging if fleet isn't set up --- .../step_select_config.tsx | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx index 63274757313b2..e98ddf5328f56 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx @@ -26,6 +26,7 @@ import { useGetAgentConfigs, sendGetOneAgentConfig, useCapabilities, + useFleetStatus, } from '../../../hooks'; import { CreateAgentConfigFlyout } from '../list_page/components'; @@ -36,12 +37,12 @@ const AgentConfigWrapper = styled(EuiFormRow)` `; const AgentConfigNameColumn = styled(EuiFlexItem)` - max-width: ${(2 / 9) * 100}%; + max-width: ${(props) => `${(props.grow / 9) * 100}%`}; overflow: hidden; `; const AgentConfigDescriptionColumn = styled(EuiFlexItem)` - max-width: ${(5 / 9) * 100}%; + max-width: ${(props) => `${(props.grow / 9) * 100}%`}; overflow: hidden; `; @@ -52,6 +53,8 @@ export const StepSelectConfig: React.FunctionComponent<{ updateAgentConfig: (config: AgentConfig | undefined) => void; setIsLoadingSecondStep: (isLoading: boolean) => void; }> = ({ pkgkey, updatePackageInfo, agentConfig, updateAgentConfig, setIsLoadingSecondStep }) => { + const { isReady: isFleetReady } = useFleetStatus(); + // Selected config state const [selectedConfigId, setSelectedConfigId] = useState( agentConfig ? agentConfig.id : undefined @@ -231,7 +234,7 @@ export const StepSelectConfig: React.FunctionComponent<{ } helpText={ - selectedConfigId ? ( + isFleetReady && selectedConfigId ? ( {option.label} - + {agentConfigsById[option.key!].description} - - - - - + {isFleetReady ? ( + + + + + + ) : null} ); }} From cce2f1b0adc139c59c0dc78f4af7a95cfbe584d6 Mon Sep 17 00:00:00 2001 From: Jen Huang Date: Thu, 23 Jul 2020 16:51:51 -0700 Subject: [PATCH 3/6] Fix types --- .../step_select_config.tsx | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx index e98ddf5328f56..186bebbc331cc 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React, { useEffect, useState, Fragment } from 'react'; +import React, { useEffect, useState } from 'react'; import styled from 'styled-components'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -11,10 +11,9 @@ import { EuiFlexGroup, EuiFlexItem, EuiComboBox, - EuiSpacer, + EuiComboBoxOptionOption, EuiTextColor, EuiPortal, - EuiButtonEmpty, EuiFormRow, EuiLink, } from '@elastic/eui'; @@ -37,12 +36,12 @@ const AgentConfigWrapper = styled(EuiFormRow)` `; const AgentConfigNameColumn = styled(EuiFlexItem)` - max-width: ${(props) => `${(props.grow / 9) * 100}%`}; + max-width: ${(props) => `${((props.grow as number) / 9) * 100}%`}; overflow: hidden; `; const AgentConfigDescriptionColumn = styled(EuiFlexItem)` - max-width: ${(props) => `${(props.grow / 9) * 100}%`}; + max-width: ${(props) => `${((props.grow as number) / 9) * 100}%`}; overflow: hidden; `; @@ -128,7 +127,7 @@ export const StepSelectConfig: React.FunctionComponent<{ } }, [selectedConfigId, agentConfig, updateAgentConfig, setIsLoadingSecondStep]); - const agentConfigOptions = packageInfoData + const agentConfigOptions: Array> = packageInfoData ? agentConfigs.map((agentConf) => { const alreadyHasLimitedPackage = (isLimitedPackage && @@ -136,14 +135,16 @@ export const StepSelectConfig: React.FunctionComponent<{ false; return { label: agentConf.name, - key: agentConf.id, + value: agentConf.id, disabled: alreadyHasLimitedPackage, 'data-test-subj': 'agentConfigItem', }; }) : []; - const selectedConfigOption = agentConfigOptions.find((option) => option.key === selectedConfigId); + const selectedConfigOption = agentConfigOptions.find( + (option) => option.value === selectedConfigId + ); // Try to select default agent config useEffect(() => { @@ -151,7 +152,7 @@ export const StepSelectConfig: React.FunctionComponent<{ const defaultAgentConfig = agentConfigs.find((config) => config.is_default); if (defaultAgentConfig) { const defaultAgentConfigOption = agentConfigOptions.find( - (option) => option.key === defaultAgentConfig.id + (option) => option.value === defaultAgentConfig.id ); if (defaultAgentConfigOption && !defaultAgentConfigOption.disabled) { setSelectedConfigId(defaultAgentConfig.id); @@ -221,7 +222,7 @@ export const StepSelectConfig: React.FunctionComponent<{
setIsCreateAgentConfigFlyoutOpen(true)} > { + renderOption={(option: EuiComboBoxOptionOption) => { return ( @@ -264,7 +266,7 @@ export const StepSelectConfig: React.FunctionComponent<{ - {agentConfigsById[option.key!].description} + {agentConfigsById[option.value!].description} {isFleetReady ? ( @@ -274,7 +276,7 @@ export const StepSelectConfig: React.FunctionComponent<{ id="xpack.ingestManager.createPackageConfig.StepSelectConfig.agentConfigAgentsCountText" defaultMessage="{count, plural, one {# agent} other {# agents}} enrolled" values={{ - count: agentConfigsById[option.key!].agents || 0, + count: agentConfigsById[option.value!].agents || 0, }} /> @@ -287,8 +289,8 @@ export const StepSelectConfig: React.FunctionComponent<{ onChange={(options) => { const selectedOption = options[0] || undefined; if (selectedOption) { - if (selectedOption.key !== selectedConfigId) { - setSelectedConfigId(selectedOption.key); + if (selectedOption.value !== selectedConfigId) { + setSelectedConfigId(selectedOption.value); } } else { setSelectedConfigId(undefined); From 746073c1506aa783b1387636a40700f0b1d3c027 Mon Sep 17 00:00:00 2001 From: Jen Huang Date: Fri, 24 Jul 2020 14:27:20 -0700 Subject: [PATCH 4/6] Fix i18n --- .../create_package_config_page/step_select_config.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx index 186bebbc331cc..3f931ee90a2ea 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx @@ -237,7 +237,7 @@ export const StepSelectConfig: React.FunctionComponent<{ helpText={ isFleetReady && selectedConfigId ? ( Date: Mon, 27 Jul 2020 10:33:38 -0700 Subject: [PATCH 5/6] Fix i18n again --- x-pack/plugins/translations/translations/ja-JP.json | 1 - x-pack/plugins/translations/translations/zh-CN.json | 1 - 2 files changed, 2 deletions(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index cf789d1e7c450..ed3c4464324b0 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -8108,7 +8108,6 @@ "xpack.ingestManager.createPackageConfig.StepSelectConfig.errorLoadingAgentConfigsTitle": "エージェント構成の読み込みエラー", "xpack.ingestManager.createPackageConfig.StepSelectConfig.errorLoadingPackageTitle": "パッケージ情報の読み込みエラー", "xpack.ingestManager.createPackageConfig.StepSelectConfig.errorLoadingSelectedAgentConfigTitle": "選択したエージェント構成の読み込みエラー", - "xpack.ingestManager.createPackageConfig.StepSelectConfig.filterAgentConfigsInputPlaceholder": "エージェント構成の検索", "xpack.ingestManager.createPackageConfig.stepSelectPackage.errorLoadingConfigTitle": "エージェント構成情報の読み込みエラー", "xpack.ingestManager.createPackageConfig.stepSelectPackage.errorLoadingPackagesTitle": "統合の読み込みエラー", "xpack.ingestManager.createPackageConfig.stepSelectPackage.errorLoadingSelectedPackageTitle": "選択した統合の読み込みエラー", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 5b81804faf715..95ed30df897af 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -8113,7 +8113,6 @@ "xpack.ingestManager.createPackageConfig.StepSelectConfig.errorLoadingAgentConfigsTitle": "加载代理配置时出错", "xpack.ingestManager.createPackageConfig.StepSelectConfig.errorLoadingPackageTitle": "加载软件包信息时出错", "xpack.ingestManager.createPackageConfig.StepSelectConfig.errorLoadingSelectedAgentConfigTitle": "加载选定代理配置时出错", - "xpack.ingestManager.createPackageConfig.StepSelectConfig.filterAgentConfigsInputPlaceholder": "搜索代理配置", "xpack.ingestManager.createPackageConfig.stepSelectPackage.errorLoadingConfigTitle": "加载代理配置信息时出错", "xpack.ingestManager.createPackageConfig.stepSelectPackage.errorLoadingPackagesTitle": "加载集成时出错", "xpack.ingestManager.createPackageConfig.stepSelectPackage.errorLoadingSelectedPackageTitle": "加载选定集成时出错", From 6fb3057d55e844710433ddbbe50eef0aea4523f9 Mon Sep 17 00:00:00 2001 From: Jen Huang Date: Mon, 27 Jul 2020 10:43:58 -0700 Subject: [PATCH 6/6] Add comment explaining styling --- .../create_package_config_page/step_select_config.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx index 3f931ee90a2ea..6f06530100d71 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_select_config.tsx @@ -35,11 +35,15 @@ const AgentConfigWrapper = styled(EuiFormRow)` } `; +// Custom styling for drop down list items due to: +// 1) the max-width and overflow properties is added to prevent long config +// names/descriptions from overflowing the flex items +// 2) max-width is built from the grow property on the flex items because the value +// changes based on if Fleet is enabled/setup or not const AgentConfigNameColumn = styled(EuiFlexItem)` max-width: ${(props) => `${((props.grow as number) / 9) * 100}%`}; overflow: hidden; `; - const AgentConfigDescriptionColumn = styled(EuiFlexItem)` max-width: ${(props) => `${((props.grow as number) / 9) * 100}%`}; overflow: hidden;