diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.scss b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.scss index 026e63b2b4caa..8e196936e4073 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.scss +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.scss @@ -8,6 +8,7 @@ $heightHeader: $euiSizeL * 2; .componentTemplates { border: $euiBorderThin; + border-radius: $euiBorderRadius; border-top: none; height: 100%; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.scss b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.scss index 041fc1c8bf9a4..aeccc6a513fe2 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.scss +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.scss @@ -7,30 +7,31 @@ &__selection { border: $euiBorderThin; + border-radius: $euiBorderRadius; - padding: 0 $euiSize $euiSize; - color: $euiColorDarkShade; + padding: 0 $euiSize $euiSize; + color: $euiColorDarkShade; - &--is-empty { - align-items: center; - justify-content: center; - } + &--is-empty { + align-items: center; + justify-content: center; + } - &__header { - background-color: $euiColorLightestShade; - border-bottom: $euiBorderThin; - color: $euiColorInk; - height: $euiSizeXXL; // [1] - line-height: $euiSizeXXL; // [1] - font-size: $euiSizeM; - margin-bottom: $euiSizeS; - margin-left: $euiSize * -1; - margin-right: $euiSize * -1; - padding-left: $euiSize; + &__header { + background-color: $euiColorLightestShade; + border-bottom: $euiBorderThin; + color: $euiColorInk; + height: $euiSizeXXL; // [1] + line-height: $euiSizeXXL; // [1] + font-size: $euiSizeM; + margin-bottom: $euiSizeS; + margin-left: $euiSize * -1; + margin-right: $euiSize * -1; + padding-left: $euiSize; - &__count { - font-weight: 600; - } + &__count { + font-weight: 600; + } } &__content { diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.tsx index ccdfaad78fb6b..ff871b8b79247 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.tsx @@ -200,12 +200,19 @@ export const ComponentTemplatesSelector = ({ ) : ( -
- -
+ +

+ +
+ +

+
)} diff --git a/x-pack/plugins/index_management/public/application/components/index_templates/shared_imports.ts b/x-pack/plugins/index_management/public/application/components/index_templates/shared_imports.ts new file mode 100644 index 0000000000000..cc43b8b48b0c7 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/index_templates/shared_imports.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +export { + useForm, + Form, + getUseField, + FormDataProvider, +} from '../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib'; + +export { CheckBoxField } from '../../../../../../../src/plugins/es_ui_shared/static/forms/components'; diff --git a/x-pack/plugins/index_management/public/application/components/index_templates/simulate_template/index.ts b/x-pack/plugins/index_management/public/application/components/index_templates/simulate_template/index.ts index fb10096ed81d4..de231baf11c50 100644 --- a/x-pack/plugins/index_management/public/application/components/index_templates/simulate_template/index.ts +++ b/x-pack/plugins/index_management/public/application/components/index_templates/simulate_template/index.ts @@ -10,4 +10,4 @@ export { Props as SimulateTemplateProps, } from './simulate_template_flyout'; -export { SimulateTemplate } from './simulate_template'; +export { SimulateTemplate, Filters as SimulateTemplateFilters } from './simulate_template'; diff --git a/x-pack/plugins/index_management/public/application/components/index_templates/simulate_template/simulate_template.tsx b/x-pack/plugins/index_management/public/application/components/index_templates/simulate_template/simulate_template.tsx index b362b37d54c49..c2ba4eea56ad8 100644 --- a/x-pack/plugins/index_management/public/application/components/index_templates/simulate_template/simulate_template.tsx +++ b/x-pack/plugins/index_management/public/application/components/index_templates/simulate_template/simulate_template.tsx @@ -5,7 +5,8 @@ */ import React, { useState, useCallback, useEffect } from 'react'; import uuid from 'uuid'; -import { EuiCodeBlock } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiCodeBlock, EuiCallOut } from '@elastic/eui'; import { serializers } from '../../../../shared_imports'; import { TemplateDeserialized } from '../../../../../common'; @@ -14,12 +15,18 @@ import { simulateIndexTemplate } from '../../../services'; const { stripEmptyFields } = serializers; +export interface Filters { + mappings: boolean; + settings: boolean; + aliases: boolean; +} + interface Props { template: { [key: string]: any }; - minHeightCodeBlock?: string; + filters?: Filters; } -export const SimulateTemplate = React.memo(({ template, minHeightCodeBlock }: Props) => { +export const SimulateTemplate = React.memo(({ template, filters }: Props) => { const [templatePreview, setTemplatePreview] = useState('{}'); const updatePreview = useCallback(async () => { @@ -34,26 +41,60 @@ export const SimulateTemplate = React.memo(({ template, minHeightCodeBlock }: Pr indexTemplate.index_patterns = [uuid.v4()]; const { data, error } = await simulateIndexTemplate(indexTemplate); + let filteredTemplate = data; if (data) { // "Overlapping" info is only useful when simulating against an index // which we don't do here. delete data.overlapping; + + if (data.template && data.template.mappings === undefined) { + // Adding some extra logic to return an empty object for "mappings" as ES does not + // return one in that case (empty objects _are_ returned for "settings" and "aliases") + // Issue: https://github.com/elastic/elasticsearch/issues/60968 + data.template.mappings = {}; + } + + if (filters) { + filteredTemplate = Object.entries(filters).reduce( + (acc, [key, value]) => { + if (!value) { + delete acc[key]; + } + return acc; + }, + { ...data.template } as any + ); + } } - setTemplatePreview(JSON.stringify(data ?? error, null, 2)); - }, [template]); + setTemplatePreview(JSON.stringify(filteredTemplate ?? error, null, 2)); + }, [template, filters]); useEffect(() => { updatePreview(); }, [updatePreview]); - return templatePreview === '{}' ? null : ( - + const isEmpty = templatePreview === '{}'; + const hasFilters = Boolean(filters); + + if (isEmpty && hasFilters) { + return ( + + } + iconType="pin" + size="s" + /> + ); + } + + return isEmpty ? null : ( + {templatePreview} ); diff --git a/x-pack/plugins/index_management/public/application/components/index_templates/simulate_template/simulate_template_flyout.tsx b/x-pack/plugins/index_management/public/application/components/index_templates/simulate_template/simulate_template_flyout.tsx index 63bfe78546041..f818f49d8aa59 100644 --- a/x-pack/plugins/index_management/public/application/components/index_templates/simulate_template/simulate_template_flyout.tsx +++ b/x-pack/plugins/index_management/public/application/components/index_templates/simulate_template/simulate_template_flyout.tsx @@ -5,6 +5,7 @@ */ import React, { useState, useCallback, useEffect, useRef } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; import { EuiFlyoutHeader, EuiTitle, @@ -19,11 +20,16 @@ import { EuiSpacer, } from '@elastic/eui'; -import { SimulateTemplate } from './simulate_template'; +import { useForm, Form, getUseField, CheckBoxField, FormDataProvider } from '../shared_imports'; +import { SimulateTemplate, Filters } from './simulate_template'; + +const CheckBox = getUseField({ component: CheckBoxField }); export interface Props { onClose(): void; getTemplate: () => { [key: string]: any }; + filters: Filters; + onFiltersChange: (filters: Filters) => void; } export const defaultFlyoutProps = { @@ -31,16 +37,39 @@ export const defaultFlyoutProps = { 'aria-labelledby': 'simulateTemplateFlyoutTitle', }; -export const SimulateTemplateFlyoutContent = ({ onClose, getTemplate }: Props) => { +const i18nTexts = { + filters: { + label: i18n.translate('xpack.idxMgmt.simulateTemplate.filters.label', { + defaultMessage: 'Include:', + }), + mappings: i18n.translate('xpack.idxMgmt.simulateTemplate.filters.mappings', { + defaultMessage: 'Mappings', + }), + indexSettings: i18n.translate('xpack.idxMgmt.simulateTemplate.filters.indexSettings', { + defaultMessage: 'Index settings', + }), + aliases: i18n.translate('xpack.idxMgmt.simulateTemplate.filters.aliases', { + defaultMessage: 'Aliases', + }), + }, +}; + +export const SimulateTemplateFlyoutContent = ({ + onClose, + getTemplate, + filters, + onFiltersChange, +}: Props) => { const isMounted = useRef(false); - const [heightCodeBlock, setHeightCodeBlock] = useState(0); const [template, setTemplate] = useState<{ [key: string]: any }>({}); + const { form } = useForm({ defaultValue: filters }); + const { subscribe } = form; useEffect(() => { - setHeightCodeBlock( - document.getElementsByClassName('euiFlyoutBody__overflow')[0].clientHeight - 96 - ); - }, []); + subscribe((formState) => { + onFiltersChange(formState.data.format()); + }); + }, [subscribe, onFiltersChange]); const updatePreview = useCallback(async () => { const indexTemplate = await getTemplate(); @@ -71,8 +100,8 @@ export const SimulateTemplateFlyoutContent = ({ onClose, getTemplate }: Props) =

@@ -80,7 +109,28 @@ export const SimulateTemplateFlyoutContent = ({ onClose, getTemplate }: Props) = - +
+ + {i18nTexts.filters.label} + + + + + + + + + + + + + + + {(formData) => { + return ; + }} + +
diff --git a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_components.tsx b/x-pack/plugins/index_management/public/application/components/template_form/steps/step_components.tsx index ae831f4acf7ee..a4f64f7881a28 100644 --- a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_components.tsx +++ b/x-pack/plugins/index_management/public/application/components/template_form/steps/step_components.tsx @@ -34,7 +34,7 @@ const i18nTexts = { description: ( ), }; diff --git a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_review.tsx b/x-pack/plugins/index_management/public/application/components/template_form/steps/step_review.tsx index 1b4f19dda99f7..3bdcf1f35733e 100644 --- a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_review.tsx +++ b/x-pack/plugins/index_management/public/application/components/template_form/steps/step_review.tsx @@ -66,7 +66,7 @@ const PreviewTab = ({ template }: { template: { [key: string]: any } }) => {

diff --git a/x-pack/plugins/index_management/public/application/components/template_form/template_form.tsx b/x-pack/plugins/index_management/public/application/components/template_form/template_form.tsx index fb0ba0b68fa6c..151b31b527228 100644 --- a/x-pack/plugins/index_management/public/application/components/template_form/template_form.tsx +++ b/x-pack/plugins/index_management/public/application/components/template_form/template_form.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, { useState, useCallback } from 'react'; +import React, { useState, useCallback, useRef } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiSpacer, EuiButton } from '@elastic/eui'; @@ -15,6 +15,7 @@ import { SimulateTemplateFlyoutContent, SimulateTemplateProps, simulateTemplateFlyoutProps, + SimulateTemplateFilters, } from '../index_templates'; import { StepLogisticsContainer, StepComponentContainer, StepReviewContainer } from './steps'; import { @@ -98,6 +99,11 @@ export const TemplateForm = ({ }: Props) => { const [wizardContent, setWizardContent] = useState | null>(null); const { addContent: addContentToGlobalFlyout, closeFlyout } = useGlobalFlyout(); + const simulateTemplateFilters = useRef({ + mappings: true, + settings: true, + aliases: true, + }); const indexTemplate = defaultValue ?? { name: '', @@ -234,6 +240,10 @@ export const TemplateForm = ({ return template; }, [buildTemplateObject, indexTemplate, wizardContent]); + const onSimulateTemplateFiltersChange = useCallback((filters: SimulateTemplateFilters) => { + simulateTemplateFilters.current = filters; + }, []); + const showPreviewFlyout = () => { addContentToGlobalFlyout({ id: 'simulateTemplate', @@ -241,6 +251,8 @@ export const TemplateForm = ({ props: { getTemplate: getSimulateTemplate, onClose: closeFlyout, + filters: simulateTemplateFilters.current, + onFiltersChange: onSimulateTemplateFiltersChange, }, flyoutProps: simulateTemplateFlyoutProps, }); diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_preview.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_preview.tsx index ec52bcbab3b0b..49b78f3f56c25 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_preview.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_preview.tsx @@ -21,7 +21,7 @@ export const TabPreview = ({ templateDetails }: Props) => {

diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 3daa936f5be58..2cb4c89cac52c 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -7281,7 +7281,6 @@ "xpack.idxMgmt.componentTemplatesSelector.filters.mappingsLabel": "マッピング", "xpack.idxMgmt.componentTemplatesSelector.loadingComponentsDescription": "コンポーネントテンプレートを読み込んでいます...", "xpack.idxMgmt.componentTemplatesSelector.loadingComponentsErrorMessage": "コンポーネントの読み込みエラー", - "xpack.idxMgmt.componentTemplatesSelector.noComponentSelectedLabel": "コンポーネントテンプレートが選択されていません。", "xpack.idxMgmt.componentTemplatesSelector.removeItemIconLabel": "削除", "xpack.idxMgmt.componentTemplatesSelector.searchBox.placeholder": "コンポーネントテンプレートを検索", "xpack.idxMgmt.componentTemplatesSelector.searchResult.emptyPrompt.clearSearchButtonLabel": "検索のクリア", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index f396d950f7526..19320c12d240f 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7283,7 +7283,6 @@ "xpack.idxMgmt.componentTemplatesSelector.filters.mappingsLabel": "映射", "xpack.idxMgmt.componentTemplatesSelector.loadingComponentsDescription": "正在加载组件模板……", "xpack.idxMgmt.componentTemplatesSelector.loadingComponentsErrorMessage": "加载组件时出错", - "xpack.idxMgmt.componentTemplatesSelector.noComponentSelectedLabel": "未选择任何组件模板。", "xpack.idxMgmt.componentTemplatesSelector.removeItemIconLabel": "移除", "xpack.idxMgmt.componentTemplatesSelector.searchBox.placeholder": "搜索组件模板", "xpack.idxMgmt.componentTemplatesSelector.searchResult.emptyPrompt.clearSearchButtonLabel": "清除搜索",