From 1cf806f83a0c9e0c6f3f5bf9411e1eb20156ac6a Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 30 Jan 2025 11:25:39 +0100 Subject: [PATCH] [8.x] Add a warning callout when deleting managed assets (#207329) (#208491) # Backport This will backport the following commits from `main` to `8.x`: - [Add a warning callout when deleting managed assets (#207329)](https://github.com/elastic/kibana/pull/207329) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 1 + package.json | 1 + .../delete_managed_assets_callout/README.mdx | 15 +++++++ .../delete_managed_assets_callout/index.ts | 11 +++++ .../kibana.jsonc | 7 ++++ .../package.json | 6 +++ .../src/callout.stories.tsx | 25 +++++++++++ .../src/callout.tsx | 41 ++++++++++++++++++ .../tsconfig.json | 21 ++++++++++ tsconfig.base.json | 2 + .../home/index_templates_tab.test.ts | 4 +- .../components/template_delete_modal.tsx | 32 ++++++++++++-- .../template_details_content.tsx | 11 +++-- .../template_table/template_table.tsx | 9 ++-- .../api/templates/register_delete_route.ts | 1 + .../shared/index_management/tsconfig.json | 1 + .../sections/pipelines_list/delete_modal.tsx | 40 ++++++++++++++---- .../pipelines_list/details_flyout.tsx | 5 ++- .../sections/pipelines_list/main.tsx | 2 +- .../sections/pipelines_list/table.tsx | 6 +-- .../shared/ingest_pipelines/tsconfig.json | 3 +- .../index_templates_tab/index.ts | 1 + .../index_template_list.ts | 42 +++++++++++++++++++ .../apps/ingest_pipelines/ingest_pipelines.ts | 18 ++++++++ .../page_objects/index_management_page.ts | 1 + yarn.lock | 4 ++ 26 files changed, 284 insertions(+), 26 deletions(-) create mode 100644 src/platform/packages/shared/kbn-management/delete_managed_assets_callout/README.mdx create mode 100644 src/platform/packages/shared/kbn-management/delete_managed_assets_callout/index.ts create mode 100644 src/platform/packages/shared/kbn-management/delete_managed_assets_callout/kibana.jsonc create mode 100644 src/platform/packages/shared/kbn-management/delete_managed_assets_callout/package.json create mode 100644 src/platform/packages/shared/kbn-management/delete_managed_assets_callout/src/callout.stories.tsx create mode 100644 src/platform/packages/shared/kbn-management/delete_managed_assets_callout/src/callout.tsx create mode 100644 src/platform/packages/shared/kbn-management/delete_managed_assets_callout/tsconfig.json create mode 100644 x-pack/test/functional/apps/index_management/index_templates_tab/index_template_list.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index cffe9930c5787..1bcb048ce8a9b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -385,6 +385,7 @@ src/platform/packages/private/default-nav/analytics @elastic/kibana-data-discove src/platform/packages/private/default-nav/devtools @elastic/kibana-management src/platform/packages/private/default-nav/management @elastic/kibana-management src/platform/packages/private/default-nav/ml @elastic/ml-ui +src/platform/packages/shared/kbn-management/delete_managed_assets_callout @elastic/kibana-management packages/kbn-dependency-usage @elastic/kibana-security packages/kbn-dev-cli-errors @elastic/kibana-operations packages/kbn-dev-cli-runner @elastic/kibana-operations diff --git a/package.json b/package.json index 34604b3436320..c13f35729196a 100644 --- a/package.json +++ b/package.json @@ -451,6 +451,7 @@ "@kbn/default-nav-devtools": "link:src/platform/packages/private/default-nav/devtools", "@kbn/default-nav-management": "link:src/platform/packages/private/default-nav/management", "@kbn/default-nav-ml": "link:src/platform/packages/private/default-nav/ml", + "@kbn/delete-managed-asset-callout": "link:src/platform/packages/shared/kbn-management/delete_managed_assets_callout", "@kbn/dev-tools-plugin": "link:src/platform/plugins/shared/dev_tools", "@kbn/developer-examples-plugin": "link:examples/developer_examples", "@kbn/discover-contextual-components": "link:src/platform/packages/shared/kbn-discover-contextual-components", diff --git a/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/README.mdx b/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/README.mdx new file mode 100644 index 0000000000000..b4549716f06af --- /dev/null +++ b/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/README.mdx @@ -0,0 +1,15 @@ +--- +id: kbn-management/components/DeleteManagedAssetsCallout +slug: /kbn-management/components/delete_managed_assets_callout +title: Delete Managed Assets Callout +description: A callout component that displays a warning message for when a user is about to delete a managed asset. +tags: ['management', 'component'] +date: 2025-01-20 +--- + +This component is used to display a warning callout when a user is about to delete a managed asset. + + +```typescript + +``` \ No newline at end of file diff --git a/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/index.ts b/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/index.ts new file mode 100644 index 0000000000000..01e2eb8291a93 --- /dev/null +++ b/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export type { DeleteManagedAssetsCalloutProps } from './src/callout'; +export { DeleteManagedAssetsCallout } from './src/callout'; diff --git a/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/kibana.jsonc b/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/kibana.jsonc new file mode 100644 index 0000000000000..4c144e78304f3 --- /dev/null +++ b/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/delete-managed-asset-callout", + "owner": "@elastic/kibana-management", + "group": "platform", + "visibility": "shared" +} diff --git a/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/package.json b/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/package.json new file mode 100644 index 0000000000000..ae188a2d6e949 --- /dev/null +++ b/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/delete-managed-asset-callout", + "private": true, + "version": "1.0.0", + "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0" +} \ No newline at end of file diff --git a/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/src/callout.stories.tsx b/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/src/callout.stories.tsx new file mode 100644 index 0000000000000..1f36808a65050 --- /dev/null +++ b/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/src/callout.stories.tsx @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import React from 'react'; + +import { DeleteManagedAssetsCallout as Component } from './callout'; + +export default { + title: 'Developer/Delete Managed Assets Callout', + description: '', +}; + +export const DeleteManagedAssetsCallout = () => { + return ; +}; + +export const ErrorDeleteManagedAssetsCallout = () => { + return ; +}; diff --git a/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/src/callout.tsx b/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/src/callout.tsx new file mode 100644 index 0000000000000..9b178461edfb8 --- /dev/null +++ b/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/src/callout.tsx @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import type { EuiCallOutProps } from '@elastic/eui'; +import { EuiCallOut } from '@elastic/eui'; + +export interface DeleteManagedAssetsCalloutProps extends EuiCallOutProps { + assetName: string; + overrideBody?: string; +} + +export const DeleteManagedAssetsCallout = ({ + assetName, + overrideBody, + ...overrideCalloutProps +}: DeleteManagedAssetsCalloutProps) => { + return ( + +

+ {overrideBody ?? + i18n.translate('management.deleteManagedAssetsCallout.body', { + defaultMessage: `Elasticsearch automatically re-creates any missing managed {assetName}. If you delete managed {assetName}, the deletion appears as successful, but the {assetName} are immediately re-created and reappear.`, + values: { assetName }, + })} +

+
+ ); +}; diff --git a/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/tsconfig.json b/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/tsconfig.json new file mode 100644 index 0000000000000..519a99e9fb9a2 --- /dev/null +++ b/src/platform/packages/shared/kbn-management/delete_managed_assets_callout/tsconfig.json @@ -0,0 +1,21 @@ +{ + "extends": "../../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx" + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/i18n", + ] +} diff --git a/tsconfig.base.json b/tsconfig.base.json index 793665e7bc2d9..76751ff9a9083 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -764,6 +764,8 @@ "@kbn/default-nav-management/*": ["src/platform/packages/private/default-nav/management/*"], "@kbn/default-nav-ml": ["src/platform/packages/private/default-nav/ml"], "@kbn/default-nav-ml/*": ["src/platform/packages/private/default-nav/ml/*"], + "@kbn/delete-managed-asset-callout": ["src/platform/packages/shared/kbn-management/delete_managed_assets_callout"], + "@kbn/delete-managed-asset-callout/*": ["src/platform/packages/shared/kbn-management/delete_managed_assets_callout/*"], "@kbn/dependency-usage": ["packages/kbn-dependency-usage"], "@kbn/dependency-usage/*": ["packages/kbn-dependency-usage/*"], "@kbn/dev-cli-errors": ["packages/kbn-dev-cli-errors"], diff --git a/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/home/index_templates_tab.test.ts b/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/home/index_templates_tab.test.ts index ea536becfccac..3d4b60a04d965 100644 --- a/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/home/index_templates_tab.test.ts +++ b/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/home/index_templates_tab.test.ts @@ -455,7 +455,7 @@ describe('Index Templates tab', () => { `${API_BASE_PATH}/delete_index_templates`, expect.objectContaining({ body: JSON.stringify({ - templates: [{ name: templates[0].name, isLegacy }], + templates: [{ name: templates[0].name, isLegacy, type: 'default' }], }), }) ); @@ -518,7 +518,7 @@ describe('Index Templates tab', () => { `${API_BASE_PATH}/delete_index_templates`, expect.objectContaining({ body: JSON.stringify({ - templates: [{ name: templates[0].name, isLegacy: false }], + templates: [{ name: templates[0].name, isLegacy: false, type: 'default' }], }), }) ); diff --git a/x-pack/platform/plugins/shared/index_management/public/application/components/template_delete_modal.tsx b/x-pack/platform/plugins/shared/index_management/public/application/components/template_delete_modal.tsx index 0462891834276..ded2ff915d9d9 100644 --- a/x-pack/platform/plugins/shared/index_management/public/application/components/template_delete_modal.tsx +++ b/x-pack/platform/plugins/shared/index_management/public/application/components/template_delete_modal.tsx @@ -6,10 +6,11 @@ */ import React, { Fragment, useState } from 'react'; -import { EuiConfirmModal, EuiCallOut, EuiCheckbox, EuiBadge } from '@elastic/eui'; +import { EuiConfirmModal, EuiCallOut, EuiCheckbox, EuiBadge, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; +import { DeleteManagedAssetsCallout } from '@kbn/delete-managed-asset-callout'; import { deleteTemplates } from '../services/api'; import { notificationService } from '../services/notification'; @@ -17,7 +18,7 @@ export const TemplateDeleteModal = ({ templatesToDelete, callback, }: { - templatesToDelete: Array<{ name: string; isLegacy?: boolean }>; + templatesToDelete: Array<{ name: string; isLegacy?: boolean; type?: string }>; callback: (data?: { hasDeletedTemplates: boolean }) => void; }) => { const [isDeleteConfirmed, setIsDeleteConfirmed] = useState(false); @@ -25,6 +26,9 @@ export const TemplateDeleteModal = ({ const numTemplatesToDelete = templatesToDelete.length; const hasSystemTemplate = Boolean(templatesToDelete.find(({ name }) => name.startsWith('.'))); + const managedTemplatesToDelete = templatesToDelete.filter( + ({ type }) => type === 'managed' + ).length; const handleDeleteTemplates = () => { deleteTemplates(templatesToDelete).then(({ data: { templatesDeleted, errors }, error }) => { @@ -109,6 +113,17 @@ export const TemplateDeleteModal = ({ confirmButtonDisabled={hasSystemTemplate ? !isDeleteConfirmed : false} > + {managedTemplatesToDelete > 0 && ( + <> + + + + + )}

    - {templatesToDelete.map(({ name }) => ( + {templatesToDelete.map(({ name, type }) => (
  • {name} + {type === 'managed' && ( + <> + {' '} + + + + + )} {name.startsWith('.') ? ( {' '} diff --git a/x-pack/platform/plugins/shared/index_management/public/application/sections/home/template_list/template_details/template_details_content.tsx b/x-pack/platform/plugins/shared/index_management/public/application/sections/home/template_list/template_details/template_details_content.tsx index 5ba051bcaafce..09a397047960c 100644 --- a/x-pack/platform/plugins/shared/index_management/public/application/sections/home/template_list/template_details/template_details_content.tsx +++ b/x-pack/platform/plugins/shared/index_management/public/application/sections/home/template_list/template_details/template_details_content.tsx @@ -89,7 +89,7 @@ const tabToUiMetricMap: { [key: string]: string } = { }; export interface Props { - template: { name: string; isLegacy?: boolean }; + template: { name: string; isLegacy?: boolean; type?: string }; onClose: () => void; editTemplate: (name: string, isLegacy?: boolean) => void; cloneTemplate: (name: string, isLegacy?: boolean) => void; @@ -106,8 +106,9 @@ export const TemplateDetailsContent = ({ const { uiMetricService } = useServices(); const { error, data: templateDetails, isLoading } = useLoadIndexTemplate(templateName, isLegacy); const isCloudManaged = templateDetails?._kbnMeta.type === 'cloudManaged'; + const templateType = templateDetails?._kbnMeta.type; const [templateToDelete, setTemplateToDelete] = useState< - Array<{ name: string; isLegacy?: boolean }> + Array<{ name: string; isLegacy?: boolean; type?: string }> >([]); const [activeTab, setActiveTab] = useState(SUMMARY_TAB_ID); const [isPopoverOpen, setIsPopOverOpen] = useState(false); @@ -306,7 +307,11 @@ export const TemplateDetailsContent = ({ defaultMessage: 'Delete', }), icon: 'trash', - onClick: () => setTemplateToDelete([{ name: templateName, isLegacy }]), + onClick: () => + setTemplateToDelete([ + { name: templateName, isLegacy, type: templateType }, + ]), + 'data-test-subj': 'deleteIndexTemplateButton', disabled: isCloudManaged, }, ], diff --git a/x-pack/platform/plugins/shared/index_management/public/application/sections/home/template_list/template_table/template_table.tsx b/x-pack/platform/plugins/shared/index_management/public/application/sections/home/template_list/template_table/template_table.tsx index 679aa56194186..a4f8262cefb50 100644 --- a/x-pack/platform/plugins/shared/index_management/public/application/sections/home/template_list/template_table/template_table.tsx +++ b/x-pack/platform/plugins/shared/index_management/public/application/sections/home/template_list/template_table/template_table.tsx @@ -42,7 +42,7 @@ export const TemplateTable: React.FunctionComponent = ({ const { uiMetricService } = useServices(); const [selection, setSelection] = useState([]); const [templatesToDelete, setTemplatesToDelete] = useState< - Array<{ name: string; isLegacy?: boolean }> + Array<{ name: string; isLegacy?: boolean; type?: string }> >([]); const columns: Array> = [ @@ -182,8 +182,8 @@ export const TemplateTable: React.FunctionComponent = ({ icon: 'trash', color: 'danger', type: 'icon', - onClick: ({ name, _kbnMeta: { isLegacy } }: TemplateListItem) => { - setTemplatesToDelete([{ name, isLegacy }]); + onClick: ({ name, _kbnMeta: { isLegacy, type } }: TemplateListItem) => { + setTemplatesToDelete([{ name, isLegacy, type }]); }, isPrimary: true, enabled: ({ _kbnMeta: { type } }: TemplateListItem) => type !== 'cloudManaged', @@ -233,9 +233,10 @@ export const TemplateTable: React.FunctionComponent = ({ data-test-subj="deleteTemplatesButton" onClick={() => setTemplatesToDelete( - selection.map(({ name, _kbnMeta: { isLegacy } }: TemplateListItem) => ({ + selection.map(({ name, _kbnMeta: { isLegacy, type } }: TemplateListItem) => ({ name, isLegacy, + type, })) ) } diff --git a/x-pack/platform/plugins/shared/index_management/server/routes/api/templates/register_delete_route.ts b/x-pack/platform/plugins/shared/index_management/server/routes/api/templates/register_delete_route.ts index 7982aeb564475..66371ddbc6787 100644 --- a/x-pack/platform/plugins/shared/index_management/server/routes/api/templates/register_delete_route.ts +++ b/x-pack/platform/plugins/shared/index_management/server/routes/api/templates/register_delete_route.ts @@ -17,6 +17,7 @@ const bodySchema = schema.object({ schema.object({ name: schema.string(), isLegacy: schema.maybe(schema.boolean()), + type: schema.maybe(schema.string()), }) ), }); diff --git a/x-pack/platform/plugins/shared/index_management/tsconfig.json b/x-pack/platform/plugins/shared/index_management/tsconfig.json index 411aa3faaa846..a1498ac9e6184 100644 --- a/x-pack/platform/plugins/shared/index_management/tsconfig.json +++ b/x-pack/platform/plugins/shared/index_management/tsconfig.json @@ -56,6 +56,7 @@ "@kbn/unsaved-changes-prompt", "@kbn/shared-ux-table-persist", "@kbn/core-application-browser", + "@kbn/delete-managed-asset-callout", "@kbn/inference-endpoint-ui-common", ], "exclude": ["target/**/*"] diff --git a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/delete_modal.tsx b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/delete_modal.tsx index 4d4b8cae50bff..d1f3ad81bc615 100644 --- a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/delete_modal.tsx +++ b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/delete_modal.tsx @@ -6,26 +6,31 @@ */ import React from 'react'; -import { EuiConfirmModal } from '@elastic/eui'; +import { EuiConfirmModal, EuiSpacer, EuiBadge } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; +import { DeleteManagedAssetsCallout } from '@kbn/delete-managed-asset-callout'; +import { Pipeline } from '../../../../common/types'; import { useKibana } from '../../../shared_imports'; export const PipelineDeleteModal = ({ pipelinesToDelete, callback, }: { - pipelinesToDelete: string[]; + pipelinesToDelete: Pipeline[]; callback: (data?: { hasDeletedPipelines: boolean }) => void; }) => { const { services } = useKibana(); const numPipelinesToDelete = pipelinesToDelete.length; + const managedPipelinesToDelete = pipelinesToDelete.filter(({ isManaged }) => isManaged).length; const handleDeletePipelines = () => { + const pipelineNames = pipelinesToDelete.map(({ name }) => name); + services.api - .deletePipelines(pipelinesToDelete) + .deletePipelines(pipelineNames) .then(({ data: { itemsDeleted, errors }, error }) => { const hasDeletedPipelines = itemsDeleted && itemsDeleted.length; @@ -36,7 +41,7 @@ export const PipelineDeleteModal = ({ 'xpack.ingestPipelines.deleteModal.successDeleteSingleNotificationMessageText', { defaultMessage: "Deleted pipeline ''{pipelineName}''", - values: { pipelineName: pipelinesToDelete[0] }, + values: { pipelineName: pipelineNames[0] }, } ) : i18n.translate( @@ -66,7 +71,7 @@ export const PipelineDeleteModal = ({ ) : i18n.translate('xpack.ingestPipelines.deleteModal.errorNotificationMessageText', { defaultMessage: "Error deleting pipeline ''{name}''", - values: { name: (errors && errors[0].name) || pipelinesToDelete[0] }, + values: { name: (errors && errors[0].name) || pipelineNames[0] }, }); services.notifications.toasts.addDanger(errorMessage); } @@ -105,6 +110,18 @@ export const PipelineDeleteModal = ({ } > <> + {managedPipelinesToDelete > 0 && ( + <> + + + + + )} +

      - {pipelinesToDelete.map((name) => ( -
    • {name}
    • + {pipelinesToDelete.map(({ name, isManaged }) => ( +
    • + {name}{' '} + {isManaged && ( + + {i18n.translate('xpack.ingestPipelines.deleteModal.managedPipelineLabel', { + defaultMessage: 'Managed', + })} + + )} +
    • ))}
    diff --git a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx index fb266b16211cb..edb0ec7bd7d45 100644 --- a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx +++ b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx @@ -39,7 +39,7 @@ export interface Props { pipeline: Pipeline; onEditClick: (pipelineName: string) => void; onCloneClick: (pipelineName: string) => void; - onDeleteClick: (pipelineName: string[]) => void; + onDeleteClick: (pipelineName: Pipeline[]) => void; onClose: () => void; } @@ -80,9 +80,10 @@ export const PipelineDetailsFlyout: FunctionComponent = ({ defaultMessage: 'Delete', }), icon: , + 'data-test-subj': 'deletePipelineButton', onClick: () => { setShowPopover(false); - onDeleteClick([pipeline.name]); + onDeleteClick([pipeline]); }, }, ]; diff --git a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/main.tsx b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/main.tsx index 55456ee54e8c9..0a12cbabb7ed1 100644 --- a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/main.tsx +++ b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/main.tsx @@ -57,7 +57,7 @@ export const PipelinesList: React.FunctionComponent = ({ const [showFlyout, setShowFlyout] = useState(false); const [showPopover, setShowPopover] = useState(false); - const [pipelinesToDelete, setPipelinesToDelete] = useState([]); + const [pipelinesToDelete, setPipelinesToDelete] = useState([]); const { data, isLoading, error, resendRequest } = services.api.useLoadPipelines(); diff --git a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/table.tsx b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/table.tsx index 73a06a946947c..6e82f1ecadbeb 100644 --- a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/table.tsx +++ b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/pipelines_list/table.tsx @@ -40,7 +40,7 @@ export interface Props { isLoading: boolean; onEditPipelineClick: (pipelineName: string) => void; onClonePipelineClick: (pipelineName: string) => void; - onDeletePipelineClick: (pipelineName: string[]) => void; + onDeletePipelineClick: (pipelineName: Pipeline[]) => void; } export const deprecatedPipelineBadge = { @@ -246,7 +246,7 @@ export const PipelineTable: FunctionComponent = ({ selection.length > 0 ? ( onDeletePipelineClick(selection.map((pipeline) => pipeline.name))} + onClick={() => onDeletePipelineClick(selection)} color="danger" > = ({ type: 'icon', icon: 'trash', color: 'danger', - onClick: ({ name }) => onDeletePipelineClick([name]), + onClick: (pipeline) => onDeletePipelineClick([pipeline]), }, ], }, diff --git a/x-pack/platform/plugins/shared/ingest_pipelines/tsconfig.json b/x-pack/platform/plugins/shared/ingest_pipelines/tsconfig.json index b2bfeccf6733a..bd438295eb78d 100644 --- a/x-pack/platform/plugins/shared/ingest_pipelines/tsconfig.json +++ b/x-pack/platform/plugins/shared/ingest_pipelines/tsconfig.json @@ -38,7 +38,8 @@ "@kbn/core-http-browser-mocks", "@kbn/shared-ux-table-persist", "@kbn/core-http-browser", - "@kbn/core-plugins-server" + "@kbn/core-plugins-server", + "@kbn/delete-managed-asset-callout" ], "exclude": [ "target/**/*", diff --git a/x-pack/test/functional/apps/index_management/index_templates_tab/index.ts b/x-pack/test/functional/apps/index_management/index_templates_tab/index.ts index f415bced4a418..215f1068ca2a3 100644 --- a/x-pack/test/functional/apps/index_management/index_templates_tab/index.ts +++ b/x-pack/test/functional/apps/index_management/index_templates_tab/index.ts @@ -10,5 +10,6 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext) => { describe('Index Management: index templates tab', function () { loadTestFile(require.resolve('./index_template_tab')); + loadTestFile(require.resolve('./index_template_list')); }); }; diff --git a/x-pack/test/functional/apps/index_management/index_templates_tab/index_template_list.ts b/x-pack/test/functional/apps/index_management/index_templates_tab/index_template_list.ts new file mode 100644 index 0000000000000..6a8e900746271 --- /dev/null +++ b/x-pack/test/functional/apps/index_management/index_templates_tab/index_template_list.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default ({ getPageObjects, getService }: FtrProviderContext) => { + const pageObjects = getPageObjects(['common', 'indexManagement', 'header']); + const log = getService('log'); + const security = getService('security'); + const testSubjects = getService('testSubjects'); + + describe('Index template tab -> templates list', function () { + before(async () => { + await log.debug('Navigating to the index templates tab'); + await security.testUser.setRoles(['index_management_user']); + await pageObjects.common.navigateToApp('indexManagement'); + + // Navigate to the templates tab + await pageObjects.indexManagement.changeTabs('templatesTab'); + await pageObjects.header.waitUntilLoadingHasFinished(); + }); + + it('shows warning callout when deleting a managed index template', async () => { + // Open the flyout for any managed index template + await pageObjects.indexManagement.clickIndexTemplateNameLink('ilm-history-7'); + + // Open the manage context menu + await testSubjects.click('manageTemplateButton'); + // Click the delete button + await testSubjects.click('deleteIndexTemplateButton'); + + // Check if the callout is displayed + const calloutExists = await testSubjects.exists('deleteManagedAssetsCallout'); + expect(calloutExists).to.be(true); + }); + }); +}; diff --git a/x-pack/test/functional/apps/ingest_pipelines/ingest_pipelines.ts b/x-pack/test/functional/apps/ingest_pipelines/ingest_pipelines.ts index b4a6bfe60e010..fa66399c09c79 100644 --- a/x-pack/test/functional/apps/ingest_pipelines/ingest_pipelines.ts +++ b/x-pack/test/functional/apps/ingest_pipelines/ingest_pipelines.ts @@ -77,6 +77,24 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(url).not.to.contain(`pipeline=${pipelinesList[0]}`); }); + it('shows warning callout when deleting a managed pipeline', async () => { + // Filter results by managed pipelines + await testSubjects.click('filtersDropdown'); + await testSubjects.click('managedFilter'); + + // Open the flyout for the first pipeline + await pageObjects.ingestPipelines.clickPipelineLink(0); + + // Open the manage context menu + await testSubjects.click('managePipelineButton'); + // Click the delete button + await testSubjects.click('deletePipelineButton'); + + // Check if the callout is displayed + const calloutExists = await testSubjects.exists('deleteManagedAssetsCallout'); + expect(calloutExists).to.be(true); + }); + it('sets query params for search and filters when changed', async () => { // Set the search input with a test search await testSubjects.setValue('pipelineTableSearch', 'test'); diff --git a/x-pack/test/functional/page_objects/index_management_page.ts b/x-pack/test/functional/page_objects/index_management_page.ts index d406749068474..49fee4383930b 100644 --- a/x-pack/test/functional/page_objects/index_management_page.ts +++ b/x-pack/test/functional/page_objects/index_management_page.ts @@ -168,6 +168,7 @@ export function IndexManagementPageProvider({ getService }: FtrProviderContext) async clickNextButton() { await testSubjects.click('nextButton'); }, + indexDetailsPage: { async openIndexDetailsPage(indexOfRow: number) { const indexList = await testSubjects.findAll('indexTableIndexNameLink'); diff --git a/yarn.lock b/yarn.lock index 699c0a03e3203..0573d748ea25d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5373,6 +5373,10 @@ version "0.0.0" uid "" +"@kbn/delete-managed-asset-callout@link:src/platform/packages/shared/kbn-management/delete_managed_assets_callout": + version "0.0.0" + uid "" + "@kbn/dependency-usage@link:packages/kbn-dependency-usage": version "0.0.0" uid ""