diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipeline_form.helpers.ts b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipeline_form.helpers.ts index 25603db59f16a..16d56be207268 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipeline_form.helpers.ts +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipeline_form.helpers.ts @@ -78,6 +78,7 @@ export type PipelineFormTestSubjects = | 'showRequestLink' | 'apiRequestFlyout' | 'apiRequestFlyout.apiRequestFlyoutTitle' + | 'deprecatedPipelineCallout' | 'testPipelineFlyout' | 'testPipelineFlyout.title' | 'documentationLink'; diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_edit.helpers.ts b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_edit.helpers.ts index 02a2c0f890182..20a6e141b35bf 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_edit.helpers.ts +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_edit.helpers.ts @@ -19,6 +19,7 @@ export type PipelinesEditTestBed = TestBed & { export const PIPELINE_TO_EDIT = { name: 'my_pipeline', description: 'pipeline description', + deprecated: true, processors: [ { set: { diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_edit.test.tsx b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_edit.test.tsx index eff4a815ac265..8848f97928dd3 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_edit.test.tsx +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_edit.test.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import { omit } from 'lodash'; import { act } from 'react-dom/test-utils'; import { setupEnvironment, pageHelpers } from './helpers'; @@ -47,6 +48,12 @@ describe('', () => { expect(nameInput.props().disabled).toEqual(true); }); + it('should show deprecated callout', () => { + const { exists } = testBed; + + expect(exists('deprecatedPipelineCallout')).toBe(true); + }); + describe('form submission', () => { it('should send the correct payload with changed values', async () => { const UPDATED_DESCRIPTION = 'updated pipeline description'; @@ -62,7 +69,7 @@ describe('', () => { `${API_BASE_PATH}/${name}`, expect.objectContaining({ body: JSON.stringify({ - ...pipelineDefinition, + ...omit(pipelineDefinition, 'deprecated'), description: UPDATED_DESCRIPTION, }), }) diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_list.test.ts b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_list.test.ts index 521dfd4368206..286da05449cc1 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_list.test.ts +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_list.test.ts @@ -11,6 +11,7 @@ import { API_BASE_PATH } from '../../common/constants'; import { setupEnvironment, pageHelpers } from './helpers'; import { PipelineListTestBed } from './helpers/pipelines_list.helpers'; +import { Pipeline } from '../../common/types'; const { setup } = pageHelpers.pipelinesList; @@ -39,7 +40,14 @@ describe('', () => { processors: [], }; - const pipelines = [pipeline1, pipeline2]; + const pipeline3 = { + name: 'test_pipeline3', + description: 'test_pipeline3 description', + processors: [], + deprecated: true, + }; + + const pipelines = [pipeline1, pipeline2, pipeline3]; httpRequestsMockHelpers.setLoadPipelinesResponse(pipelines); @@ -66,6 +74,30 @@ describe('', () => { }); }); + test('deprecated pipelines are hidden by default', async () => { + const { table, component } = testBed; + const { tableCellsValues } = table.getMetaData('pipelinesTable'); + + // Table should shouldnt show any deprecated pipelines by default + const pipelinesWithoutDeprecated = pipelines.filter( + (pipeline: Pipeline) => !pipeline?.deprecated + ); + expect(tableCellsValues.length).toEqual(pipelinesWithoutDeprecated.length); + + // Enable filtering by deprecated pipelines + const searchInput = component.find('.euiFieldSearch').first(); + (searchInput.instance() as unknown as HTMLInputElement).value = 'is:deprecated'; + searchInput.simulate('keyup', { key: 'Enter', keyCode: 13, which: 13 }); + component.update(); + + // Table should now show only deprecated pipelines + const { tableCellsValues: tableCellValuesUpdated } = table.getMetaData('pipelinesTable'); + const pipelinesWithDeprecated = pipelines.filter( + (pipeline: Pipeline) => pipeline?.deprecated + ); + expect(tableCellValuesUpdated.length).toEqual(pipelinesWithDeprecated.length); + }); + test('should reload the pipeline data', async () => { const { actions } = testBed; diff --git a/x-pack/plugins/ingest_pipelines/common/types.ts b/x-pack/plugins/ingest_pipelines/common/types.ts index 69c4b6c52b4b8..c526facdedab8 100644 --- a/x-pack/plugins/ingest_pipelines/common/types.ts +++ b/x-pack/plugins/ingest_pipelines/common/types.ts @@ -25,6 +25,7 @@ export interface Pipeline { _meta?: { [key: string]: any }; on_failure?: Processor[]; isManaged?: boolean; + deprecated?: boolean; } export interface PipelinesByName { diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx index 1bab1918c0e9c..fbac7f1106bea 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx @@ -47,6 +47,25 @@ const ManagedPipelineCallout = () => ( ); +const DeprecatedPipelineCallout = () => ( + + } + > + + +); + export const PipelinesEdit: React.FunctionComponent> = ({ match: { params: { name }, @@ -167,6 +186,12 @@ export const PipelinesEdit: React.FunctionComponent )} + {pipeline?.deprecated && ( + <> + + + + )} = ({

{pipeline.name}

+ {pipeline.deprecated ? ( + + {' '} + + + {deprecatedPipelineBadge.badge} + + + + ) : null} {pipeline.isManaged ? ( {' '} diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx index 58603950f12ea..2acbd21632f2a 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { FunctionComponent, useState } from 'react'; +import React, { FunctionComponent, useState, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { @@ -17,6 +17,11 @@ import { EuiPopover, EuiContextMenu, EuiBadge, + EuiToolTip, + EuiFilterGroup, + EuiSelectable, + EuiFilterButton, + EuiSelectableOption, } from '@elastic/eui'; import { reactRouterNavigate } from '@kbn/kibana-react-plugin/public'; @@ -31,6 +36,27 @@ export interface Props { onDeletePipelineClick: (pipelineName: string[]) => void; } +export const deprecatedPipelineBadge = { + badge: i18n.translate('xpack.ingestPipelines.list.table.deprecatedBadgeLabel', { + defaultMessage: 'Deprecated', + }), + badgeTooltip: i18n.translate('xpack.ingestPipelines.list.table.deprecatedBadgeTooltip', { + defaultMessage: + 'This pipeline is no longer supported and might be removed in a future release. Instead, use one of the other pipelines available or create a new one.', + }), +}; + +const deprecatedFilterLabel = i18n.translate( + 'xpack.ingestPipelines.list.table.deprecatedFilterLabel', + { + defaultMessage: 'Deprecated', + } +); + +const managedFilterLabel = i18n.translate('xpack.ingestPipelines.list.table.managedFilterLabel', { + defaultMessage: 'Managed', +}); + export const PipelineTable: FunctionComponent = ({ pipelines, onReloadClick, @@ -38,6 +64,10 @@ export const PipelineTable: FunctionComponent = ({ onClonePipelineClick, onDeletePipelineClick, }) => { + const [filterOptions, setFilterOptions] = useState([ + { key: 'managed', label: managedFilterLabel }, + { key: 'deprecated', label: deprecatedFilterLabel, checked: 'off' }, + ]); const { history } = useKibana().services; const [selection, setSelection] = useState([]); const [showPopover, setShowPopover] = useState(false); @@ -65,6 +95,43 @@ export const PipelineTable: FunctionComponent = ({ }, ]; + const filteredPipelines = useMemo(() => { + return (pipelines || []).filter((pipeline) => { + const deprecatedFilter = filterOptions.find(({ key }) => key === 'deprecated')?.checked; + const managedFilter = filterOptions.find(({ key }) => key === 'managed')?.checked; + return !( + (deprecatedFilter === 'off' && pipeline.deprecated) || + (deprecatedFilter === 'on' && !pipeline.deprecated) || + (managedFilter === 'off' && pipeline.isManaged) || + (managedFilter === 'on' && !pipeline.isManaged) + ); + }); + }, [pipelines, filterOptions]); + + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const onButtonClick = () => { + setIsPopoverOpen(!isPopoverOpen); + }; + const closePopover = () => { + setIsPopoverOpen(false); + }; + + const button = ( + item.checked !== 'off').length} + hasActiveFilters={!!filterOptions.find((item) => item.checked === 'on')} + numActiveFilters={filterOptions.filter((item) => item.checked === 'on').length} + > + {i18n.translate('xpack.ingestPipelines.list.table.filtersButtonLabel', { + defaultMessage: 'Filters', + })} + + ); + const tableProps: EuiInMemoryTableProps = { itemId: 'name', isSelectable: true, @@ -111,6 +178,7 @@ export const PipelineTable: FunctionComponent = ({ })} , setShowPopover(false)} button={ @@ -147,11 +215,34 @@ export const PipelineTable: FunctionComponent = ({ }, filters: [ { - type: 'is', - field: 'isManaged', - name: i18n.translate('xpack.ingestPipelines.list.table.isManagedFilterLabel', { - defaultMessage: 'Managed', - }), + type: 'custom_component', + component: () => { + return ( + + + + {(list) =>
{list}
} +
+
+
+ ); + }, }, ], }, @@ -175,6 +266,16 @@ export const PipelineTable: FunctionComponent = ({ })} > {name} + {pipeline.deprecated && ( + <> +   + + + {deprecatedPipelineBadge.badge} + + + + )} {pipeline.isManaged && ( <>   @@ -236,7 +337,7 @@ export const PipelineTable: FunctionComponent = ({ ], }, ], - items: pipelines ?? [], + items: filteredPipelines, }; return ; diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 25f13a5258245..eb7bb5b84b480 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -21022,7 +21022,6 @@ "xpack.ingestPipelines.list.table.emptyPromptDescription": "Utilisez des pipelines pour retirer ou transformer des champs, extraire des valeurs à partir de texte et enrichir vos données avant l’indexation.", "xpack.ingestPipelines.list.table.emptyPromptDocumentionLink": "En savoir plus", "xpack.ingestPipelines.list.table.emptyPromptTitle": "Commencer en créant un pipeline", - "xpack.ingestPipelines.list.table.isManagedFilterLabel": "Géré", "xpack.ingestPipelines.list.table.managedBadgeLabel": "Géré", "xpack.ingestPipelines.list.table.nameColumnTitle": "Nom", "xpack.ingestPipelines.list.table.reloadButtonLabel": "Recharger", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 9306b03845635..3c7b0b6ec0866 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -21036,7 +21036,6 @@ "xpack.ingestPipelines.list.table.emptyPromptDescription": "パイプラインを使用すると、フィールドの削除または変換、テキストからの値の抽出、インデックス前のデータの強化を行うことができます。", "xpack.ingestPipelines.list.table.emptyPromptDocumentionLink": "詳細", "xpack.ingestPipelines.list.table.emptyPromptTitle": "パイプラインを作成して開始", - "xpack.ingestPipelines.list.table.isManagedFilterLabel": "管理中", "xpack.ingestPipelines.list.table.managedBadgeLabel": "管理中", "xpack.ingestPipelines.list.table.nameColumnTitle": "名前", "xpack.ingestPipelines.list.table.reloadButtonLabel": "再読み込み", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index a4da556606f23..0418b0828a0f1 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -21129,7 +21129,6 @@ "xpack.ingestPipelines.list.table.emptyPromptDescription": "在建立索引之前,请使用管道删除或转换字段,从文本中提取值,并扩充您的数据。", "xpack.ingestPipelines.list.table.emptyPromptDocumentionLink": "了解详情", "xpack.ingestPipelines.list.table.emptyPromptTitle": "首先创建管道", - "xpack.ingestPipelines.list.table.isManagedFilterLabel": "托管", "xpack.ingestPipelines.list.table.managedBadgeLabel": "托管", "xpack.ingestPipelines.list.table.nameColumnTitle": "名称", "xpack.ingestPipelines.list.table.reloadButtonLabel": "重新加载",