From d562ef71cf87ed3c8ed5030ea346d2b8d308fc4e Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Thu, 2 Sep 2021 19:57:32 -0400 Subject: [PATCH] [Upgrade Assistant] New Kibana deprecations page (#110101) --- .../translations/translations/ja-JP.json | 36 +-- .../translations/translations/zh-CN.json | 37 +-- .../es_deprecations/deprecations_list.test.ts | 2 +- .../deprecation_details_flyout.test.ts | 132 ++++++++ .../deprecations_list.test.ts | 125 ++++++++ .../error_handling.test.ts | 80 +++++ .../kibana_deprecations.helpers.ts | 91 +++++- .../kibana_deprecations.test.ts | 245 --------------- .../kibana_deprecations/mocked_responses.ts | 34 ++ .../public/application/app.tsx | 12 +- .../application/components/constants.tsx | 27 +- .../es_deprecations/es_deprecations.tsx | 41 +-- .../es_deprecations/es_deprecations_table.tsx | 6 +- .../deprecation_list_bar => }/index.ts | 5 +- .../_deprecation_details_flyout.scss | 4 + .../deprecation_details_flyout.tsx | 235 ++++++++++++++ .../kibana_deprecations/deprecation_item.tsx | 145 --------- .../kibana_deprecations/deprecation_list.tsx | 150 --------- .../components/kibana_deprecations/index.ts | 2 +- .../kibana_deprecation_errors.tsx | 73 ----- .../kibana_deprecations.tsx | 295 +++++++++++++----- .../kibana_deprecations_table.tsx | 251 +++++++++++++++ .../resolution_table_cell.tsx | 145 +++++++++ .../resolve_deprecation_modal.tsx | 64 ---- .../kibana_deprecations/steps_modal.tsx | 115 ------- .../no_deprecations/no_deprecations.tsx | 9 +- .../components/shared/deprecation_count.tsx | 53 ++++ .../deprecation_list_bar/count_summary.tsx | 41 --- .../deprecation_list_bar.tsx | 69 ---- .../shared/deprecation_pagination.tsx | 24 -- .../application/components/shared/health.tsx | 88 ------ .../application/components/shared/index.ts | 5 +- .../group_by_filter.test.tsx.snap | 24 -- .../__snapshots__/level_filter.test.tsx.snap | 19 -- .../search_bar/group_by_filter.test.tsx | 31 -- .../shared/search_bar/group_by_filter.tsx | 54 ---- .../components/shared/search_bar/index.ts | 8 - .../shared/search_bar/level_filter.test.tsx | 34 -- .../shared/search_bar/level_filter.tsx | 51 --- .../shared/search_bar/search_bar.tsx | 141 --------- .../public/application/components/types.ts | 8 - .../public/application/lib/breadcrumbs.ts | 2 +- .../accessibility/apps/upgrade_assistant.ts | 42 ++- .../upgrade_assistant/upgrade_assistant.ts | 2 +- x-pack/test/functional/config.js | 3 + .../page_objects/upgrade_assistant_page.ts | 17 + 46 files changed, 1434 insertions(+), 1643 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_list.test.ts create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts delete mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.test.ts create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/mocked_responses.ts rename x-pack/plugins/upgrade_assistant/public/application/components/{shared/deprecation_list_bar => }/index.ts (54%) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/_deprecation_details_flyout.scss create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolution_table_cell.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_count.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/count_summary.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/deprecation_list_bar.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_pagination.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/health.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/group_by_filter.test.tsx.snap delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.test.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/index.ts delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.test.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index c1205265bd10d..22d8d6d87db87 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25166,16 +25166,6 @@ "xpack.upgradeAssistant.breadcrumb.esDeprecationsLabel": "Elasticsearchの廃止予定", "xpack.upgradeAssistant.breadcrumb.kibanaDeprecationsLabel": "Kibanaの廃止予定", "xpack.upgradeAssistant.breadcrumb.overviewLabel": "アップグレードアシスタント", - "xpack.upgradeAssistant.checkupTab.changeFiltersShowMoreLabel": "より多く表示させるにはフィルターを変更します。", - "xpack.upgradeAssistant.checkupTab.controls.filterBar.criticalButtonLabel": "重大", - "xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIndexLabel": "インデックス別", - "xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIssueLabel": "問題別", - "xpack.upgradeAssistant.checkupTab.deprecations.criticalActionTooltip": "アップグレード前にこの問題を解決してください。", - "xpack.upgradeAssistant.checkupTab.deprecations.criticalLabel": "重大", - "xpack.upgradeAssistant.checkupTab.deprecations.warningActionTooltip": "アップグレード前にこの問題を解決することをお勧めしますが、必須ではありません。", - "xpack.upgradeAssistant.checkupTab.deprecations.warningLabel": "警告", - "xpack.upgradeAssistant.checkupTab.noDeprecationsLabel": "説明がありません", - "xpack.upgradeAssistant.checkupTab.numDeprecationsShownLabel": "{total} 件中 {numShown} 件を表示中", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.cancelButtonLabel": "キャンセル", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.closeButtonLabel": "閉じる", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.continueButtonLabel": "再インデックスを続ける", @@ -25212,16 +25202,6 @@ "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.destructiveCallout.calloutDetail": "続行する前に、インデックスをバックアップしてください。再インデックスを続行するには、各変更を承諾してください。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.destructiveCallout.calloutTitle": "このインデックスには元に戻すことのできない破壊的な変更が含まれています", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.documentationLinkLabel": "ドキュメント", - "xpack.upgradeAssistant.deprecationGroupItem.docLinkText": "ドキュメンテーションを表示", - "xpack.upgradeAssistant.deprecationGroupItem.fixButtonLabel": "修正する手順を表示", - "xpack.upgradeAssistant.deprecationGroupItem.resolveButtonLabel": "クイック解決", - "xpack.upgradeAssistant.deprecationGroupItemTitle": "'{domainId}'は廃止予定の機能を使用しています", - "xpack.upgradeAssistant.deprecationListBar.collapseAllButtonLabel": "すべて縮小", - "xpack.upgradeAssistant.deprecationListBar.expandAllButtonLabel": "すべて拡張", - "xpack.upgradeAssistant.deprecationListSearchBar.filterErrorMessageLabel": "フィルター無効:{searchTermError}", - "xpack.upgradeAssistant.deprecationListSearchBar.placeholderAriaLabel": "フィルター", - "xpack.upgradeAssistant.deprecationListSearchBar.placeholderLabel": "フィルター", - "xpack.upgradeAssistant.deprecationListSearchBar.reloadButtonLabel": "再読み込み", "xpack.upgradeAssistant.emptyPrompt.learnMoreDescription": "{nextMajor}への移行に関する詳細をご覧ください。", "xpack.upgradeAssistant.emptyPrompt.title": "{uaVersion} アップグレードアシスタント", "xpack.upgradeAssistant.emptyPrompt.upgradeAssistantDescription": "アップグレードアシスタントはクラスターの廃止予定の設定を特定し、アップグレード前に問題を解決できるようにします。Elastic {nextMajor}にアップグレードするときにここに戻って確認してください。", @@ -25245,25 +25225,11 @@ "xpack.upgradeAssistant.esDeprecationStats.loadingText": "Elasticsearchの廃止統計情報を読み込んでいます...", "xpack.upgradeAssistant.esDeprecationStats.noDeprecationsText": "警告なし。準備ができました。", "xpack.upgradeAssistant.esDeprecationStats.statsTitle": "Elasticsearch", - "xpack.upgradeAssistant.esDeprecationStats.warningDeprecationsTitle": "警告", - "xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorDescription": "エラーについては、Kibanaサーバーログを確認してください。", - "xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorTitle": "Kibana廃止予定を取得できませんでした", - "xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorDescription": "エラーについては、Kibanaサーバーログを確認してください。", - "xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorTitle": "一部のKibana廃止予定が正常に取得されませんでした", "xpack.upgradeAssistant.kibanaDeprecations.deprecationLabel": "Kibana", "xpack.upgradeAssistant.kibanaDeprecations.docLinkText": "ドキュメント", - "xpack.upgradeAssistant.kibanaDeprecations.errorMessage": "廃止予定の解決エラー", "xpack.upgradeAssistant.kibanaDeprecations.loadingText": "廃止予定を読み込んでいます...", - "xpack.upgradeAssistant.kibanaDeprecations.pageDescription": "アップグレード前に、ここで一覧の問題を確認し、必要な変更を行ってください。アップグレード前に、重大な問題を解決する必要があります。", "xpack.upgradeAssistant.kibanaDeprecations.pageTitle": "Kibana", - "xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.cancelButtonLabel": "キャンセル", - "xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.modalTitle": "'{domainId}'で廃止予定を解決しますか?", - "xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.resolveButtonLabel": "解決", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.closeButtonLabel": "閉じる", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.docLinkLabel": "ドキュメンテーションを表示", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.modalTitle": "'{domainId}'で廃止予定を解決", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.stepTitle": "ステップ{step}", - "xpack.upgradeAssistant.kibanaDeprecations.successMessage": "廃止予定が解決されました", + "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsLabel": "Kibanaには{criticalDeprecations}個の重大な廃止予定があります", "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsTitle": "重大", "xpack.upgradeAssistant.kibanaDeprecationStats.loadingErrorMessage": "Kibana廃止予定の取得中にエラーが発生しました。", "xpack.upgradeAssistant.kibanaDeprecationStats.loadingText": "Kibana廃止予定統計情報を読み込んでいます…", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index a14bc9542ca0d..41d986ef72400 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25595,16 +25595,6 @@ "xpack.upgradeAssistant.breadcrumb.esDeprecationsLabel": "Elasticsearch 弃用", "xpack.upgradeAssistant.breadcrumb.kibanaDeprecationsLabel": "Kibana 弃用", "xpack.upgradeAssistant.breadcrumb.overviewLabel": "升级助手", - "xpack.upgradeAssistant.checkupTab.changeFiltersShowMoreLabel": "更改筛选以显示更多内容。", - "xpack.upgradeAssistant.checkupTab.controls.filterBar.criticalButtonLabel": "紧急", - "xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIndexLabel": "按索引", - "xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIssueLabel": "按问题", - "xpack.upgradeAssistant.checkupTab.deprecations.criticalActionTooltip": "请解决此问题后再升级。", - "xpack.upgradeAssistant.checkupTab.deprecations.criticalLabel": "紧急", - "xpack.upgradeAssistant.checkupTab.deprecations.warningActionTooltip": "建议在升级之前先解决此问题,但这不是必需的。", - "xpack.upgradeAssistant.checkupTab.deprecations.warningLabel": "警告", - "xpack.upgradeAssistant.checkupTab.noDeprecationsLabel": "无弃用内容", - "xpack.upgradeAssistant.checkupTab.numDeprecationsShownLabel": "显示 {numShown} 个,共 {total} 个", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.cancelButtonLabel": "取消", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.closeButtonLabel": "关闭", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.continueButtonLabel": "继续重新索引", @@ -25641,16 +25631,6 @@ "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.destructiveCallout.calloutDetail": "继续前备份索引。要继续重新索引,请接受每个更改。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.destructiveCallout.calloutTitle": "此索引需要无法恢复的破坏性更改", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.documentationLinkLabel": "文档", - "xpack.upgradeAssistant.deprecationGroupItem.docLinkText": "查看文档", - "xpack.upgradeAssistant.deprecationGroupItem.fixButtonLabel": "显示修复步骤", - "xpack.upgradeAssistant.deprecationGroupItem.resolveButtonLabel": "快速解决", - "xpack.upgradeAssistant.deprecationGroupItemTitle": "“{domainId}”正在使用弃用的功能", - "xpack.upgradeAssistant.deprecationListBar.collapseAllButtonLabel": "折叠全部", - "xpack.upgradeAssistant.deprecationListBar.expandAllButtonLabel": "展开全部", - "xpack.upgradeAssistant.deprecationListSearchBar.filterErrorMessageLabel": "筛选无效:{searchTermError}", - "xpack.upgradeAssistant.deprecationListSearchBar.placeholderAriaLabel": "筛选", - "xpack.upgradeAssistant.deprecationListSearchBar.placeholderLabel": "筛选", - "xpack.upgradeAssistant.deprecationListSearchBar.reloadButtonLabel": "重新加载", "xpack.upgradeAssistant.emptyPrompt.learnMoreDescription": "详细了解如何迁移到 {nextMajor}。", "xpack.upgradeAssistant.emptyPrompt.title": "{uaVersion} 升级助手", "xpack.upgradeAssistant.emptyPrompt.upgradeAssistantDescription": "升级助手识别集群中弃用的设置,帮助您在升级前解决问题。需要升级到 Elastic {nextMajor} 时,回到这里查看。", @@ -25674,26 +25654,11 @@ "xpack.upgradeAssistant.esDeprecationStats.loadingText": "正在加载 Elasticsearch 弃用统计……", "xpack.upgradeAssistant.esDeprecationStats.noDeprecationsText": "无警告。已就绪!", "xpack.upgradeAssistant.esDeprecationStats.statsTitle": "Elasticsearch", - "xpack.upgradeAssistant.esDeprecationStats.warningDeprecationsTitle": "警告", - "xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorDescription": "请在 Kibana 服务器日志中查看错误。", - "xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorTitle": "无法检索 Kibana 弃用", - "xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorDescription": "请在 Kibana 服务器日志中查看错误。", - "xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorTitle": "未成功检索全部的 Kibana 弃用", "xpack.upgradeAssistant.kibanaDeprecations.deprecationLabel": "Kibana", "xpack.upgradeAssistant.kibanaDeprecations.docLinkText": "文档", - "xpack.upgradeAssistant.kibanaDeprecations.errorMessage": "解决弃用时出错", "xpack.upgradeAssistant.kibanaDeprecations.loadingText": "正在加载弃用……", - "xpack.upgradeAssistant.kibanaDeprecations.pageDescription": "在升级之前查看此处所列的问题并进行必要的更改。在升级之前必须解决紧急问题。", "xpack.upgradeAssistant.kibanaDeprecations.pageTitle": "Kibana", - "xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.cancelButtonLabel": "取消", - "xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.modalTitle": "在“{domainId}”中解决弃用?", - "xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.resolveButtonLabel": "解决", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.closeButtonLabel": "关闭", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.docLinkLabel": "查看文档", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.modalTitle": "在“{domainId}”中解决弃用", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.stepTitle": "步骤 {step}", - "xpack.upgradeAssistant.kibanaDeprecations.successMessage": "弃用已解决", - "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsLabel": "Kibana 有 {criticalDeprecations} 个紧急{criticalDeprecations, plural, other {弃用}}", + "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsLabel": "Kibana 具有 {criticalDeprecations} 个关键弃用", "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsTitle": "紧急", "xpack.upgradeAssistant.kibanaDeprecationStats.getWarningDeprecationsMessage": "Kibana 有 {warningDeprecations} 个警告{warningDeprecations, plural, other {弃用}}", "xpack.upgradeAssistant.kibanaDeprecationStats.loadingErrorMessage": "检索 Kibana 弃用时发生错误。", diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts index ffee297f6f574..316e1a65f0890 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts @@ -18,7 +18,7 @@ import { createEsDeprecationsMockResponse, } from './mocked_responses'; -describe('Deprecations table', () => { +describe('ES deprecations table', () => { let testBed: ElasticsearchTestBed; const { server, httpRequestsMockHelpers } = setupEnvironment(); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts new file mode 100644 index 0000000000000..c65f15fda2e3c --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts @@ -0,0 +1,132 @@ +/* + * 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 { act } from 'react-dom/test-utils'; +import { deprecationsServiceMock } from 'src/core/public/mocks'; + +import { setupEnvironment } from '../helpers'; +import { KibanaTestBed, setupKibanaPage } from './kibana_deprecations.helpers'; +import { kibanaDeprecationsMockResponse } from './mocked_responses'; + +describe('Kibana deprecation details flyout', () => { + let testBed: KibanaTestBed; + const { server } = setupEnvironment(); + const deprecationService = deprecationsServiceMock.createStartContract(); + + afterAll(() => { + server.restore(); + }); + + beforeEach(async () => { + await act(async () => { + deprecationService.getAllDeprecations = jest + .fn() + .mockReturnValue(kibanaDeprecationsMockResponse); + + testBed = await setupKibanaPage({ + services: { + core: { + deprecations: deprecationService, + }, + }, + }); + }); + + testBed.component.update(); + }); + + describe('Deprecation with manual steps', () => { + test('renders flyout with manual steps only', async () => { + const { find, exists, actions } = testBed; + const manualDeprecation = kibanaDeprecationsMockResponse[1]; + + await actions.table.clickDeprecationAt(1); + + expect(exists('kibanaDeprecationDetails')).toBe(true); + expect(find('kibanaDeprecationDetails.flyoutTitle').text()).toBe(manualDeprecation.title); + expect(find('manualStepsList').find('li').length).toEqual( + manualDeprecation.correctiveActions.manualSteps.length + ); + + // Quick resolve callout and button should not display + expect(exists('quickResolveCallout')).toBe(false); + expect(exists('resolveButton')).toBe(false); + }); + }); + + describe('Deprecation with automatic resolution', () => { + test('resolves deprecation successfully', async () => { + const { find, exists, actions } = testBed; + const quickResolveDeprecation = kibanaDeprecationsMockResponse[0]; + + await actions.table.clickDeprecationAt(0); + + expect(exists('kibanaDeprecationDetails')).toBe(true); + expect(find('kibanaDeprecationDetails.flyoutTitle').text()).toBe( + quickResolveDeprecation.title + ); + expect(find('manualStepsList').find('li').length).toEqual( + quickResolveDeprecation.correctiveActions.manualSteps.length + ); + + // Quick resolve callout and button should display + expect(exists('quickResolveCallout')).toBe(true); + expect(exists('resolveButton')).toBe(true); + + await actions.flyout.clickResolveButton(); + + // Flyout should close after button click + expect(exists('kibanaDeprecationDetails')).toBe(false); + + // Reopen the flyout + await actions.table.clickDeprecationAt(0); + + // Resolve information should not display and Quick resolve button should be disabled + expect(exists('resolveSection')).toBe(false); + expect(find('resolveButton').props().disabled).toBe(true); + expect(find('resolveButton').text()).toContain('Resolved'); + }); + + test('handles resolve failure', async () => { + const { find, exists, actions } = testBed; + const quickResolveDeprecation = kibanaDeprecationsMockResponse[0]; + + deprecationService.resolveDeprecation.mockReturnValue( + Promise.resolve({ + status: 'fail', + reason: 'resolve failed', + }) + ); + + await actions.table.clickDeprecationAt(0); + + expect(exists('kibanaDeprecationDetails')).toBe(true); + expect(find('kibanaDeprecationDetails.flyoutTitle').text()).toBe( + quickResolveDeprecation.title + ); + + // Quick resolve callout and button should display + expect(exists('quickResolveCallout')).toBe(true); + expect(exists('resolveButton')).toBe(true); + + await actions.flyout.clickResolveButton(); + + // Flyout should close after button click + expect(exists('kibanaDeprecationDetails')).toBe(false); + + // Reopen the flyout + await actions.table.clickDeprecationAt(0); + + // Verify error displays + expect(exists('quickResolveError')).toBe(true); + // Resolve information should display and Quick resolve button should be enabled + expect(exists('resolveSection')).toBe(true); + expect(find('resolveButton').props().disabled).toBe(false); + expect(find('resolveButton').text()).toContain('Try again'); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_list.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_list.test.ts new file mode 100644 index 0000000000000..c3e3581409947 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_list.test.ts @@ -0,0 +1,125 @@ +/* + * 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 { act } from 'react-dom/test-utils'; +import { deprecationsServiceMock } from 'src/core/public/mocks'; + +import { setupEnvironment } from '../helpers'; +import { KibanaTestBed, setupKibanaPage } from './kibana_deprecations.helpers'; +import { kibanaDeprecationsMockResponse } from './mocked_responses'; + +const criticalDeprecations = kibanaDeprecationsMockResponse.filter( + (deprecation) => deprecation.level === 'critical' +); +const warningDeprecations = kibanaDeprecationsMockResponse.filter( + (deprecation) => deprecation.level === 'warning' +); +const configDeprecations = kibanaDeprecationsMockResponse.filter( + (deprecation) => deprecation.deprecationType === 'config' +); + +describe('Kibana deprecations table', () => { + let testBed: KibanaTestBed; + const { server } = setupEnvironment(); + const deprecationService = deprecationsServiceMock.createStartContract(); + + afterAll(() => { + server.restore(); + }); + + beforeEach(async () => { + await act(async () => { + deprecationService.getAllDeprecations = jest + .fn() + .mockReturnValue(kibanaDeprecationsMockResponse); + + testBed = await setupKibanaPage({ + services: { + core: { + deprecations: deprecationService, + }, + }, + }); + }); + + testBed.component.update(); + }); + + test('renders deprecations', () => { + const { exists, table } = testBed; + + expect(exists('kibanaDeprecations')).toBe(true); + + const { tableCellsValues } = table.getMetaData('kibanaDeprecationsTable'); + + expect(tableCellsValues.length).toEqual(kibanaDeprecationsMockResponse.length); + }); + + it('refreshes deprecation data', async () => { + const { actions } = testBed; + + expect(deprecationService.getAllDeprecations).toHaveBeenCalledTimes(1); + + await actions.table.clickRefreshButton(); + + expect(deprecationService.getAllDeprecations).toHaveBeenCalledTimes(2); + }); + + it('shows critical and warning deprecations count', () => { + const { find } = testBed; + + expect(find('criticalDeprecationsCount').text()).toContain(criticalDeprecations.length); + expect(find('warningDeprecationsCount').text()).toContain(warningDeprecations.length); + }); + + describe('Search bar', () => { + it('filters by "critical" status', async () => { + const { actions, table } = testBed; + + // Show only critical deprecations + await actions.searchBar.clickCriticalFilterButton(); + const { rows: criticalRows } = table.getMetaData('kibanaDeprecationsTable'); + expect(criticalRows.length).toEqual(criticalDeprecations.length); + + // Show all deprecations + await actions.searchBar.clickCriticalFilterButton(); + const { rows: allRows } = table.getMetaData('kibanaDeprecationsTable'); + expect(allRows.length).toEqual(kibanaDeprecationsMockResponse.length); + }); + + it('filters by type', async () => { + const { table, actions } = testBed; + + await actions.searchBar.openTypeFilterDropdown(); + await actions.searchBar.filterByConfigType(); + + const { rows: configRows } = table.getMetaData('kibanaDeprecationsTable'); + + expect(configRows.length).toEqual(configDeprecations.length); + }); + }); + + describe('No deprecations', () => { + beforeEach(async () => { + await act(async () => { + testBed = await setupKibanaPage({ isReadOnlyMode: false }); + }); + + const { component } = testBed; + + component.update(); + }); + + test('renders prompt', () => { + const { exists, find } = testBed; + expect(exists('noDeprecationsPrompt')).toBe(true); + expect(find('noDeprecationsPrompt').text()).toContain( + 'Your Kibana configuration is up to date' + ); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts new file mode 100644 index 0000000000000..6de1fd339f3cc --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts @@ -0,0 +1,80 @@ +/* + * 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 { act } from 'react-dom/test-utils'; +import { deprecationsServiceMock } from 'src/core/public/mocks'; + +import { setupEnvironment } from '../helpers'; +import { KibanaTestBed, setupKibanaPage } from './kibana_deprecations.helpers'; +import { kibanaDeprecationsMockResponse } from './mocked_responses'; + +describe('Error handling', () => { + let testBed: KibanaTestBed; + const { server } = setupEnvironment(); + const deprecationService = deprecationsServiceMock.createStartContract(); + + afterAll(() => { + server.restore(); + }); + + test('handles plugin error', async () => { + await act(async () => { + deprecationService.getAllDeprecations = jest.fn().mockReturnValue([ + ...kibanaDeprecationsMockResponse, + { + domainId: 'failed_plugin_id', + title: 'Failed to fetch deprecations for "failed_plugin_id"', + message: `Failed to get deprecations info for plugin "failed_plugin_id".`, + level: 'fetch_error', + correctiveActions: { + manualSteps: ['Check Kibana server logs for error message.'], + }, + }, + ]); + + testBed = await setupKibanaPage({ + services: { + core: { + deprecations: deprecationService, + }, + }, + }); + }); + + const { component, exists, find } = testBed; + + component.update(); + + expect(exists('kibanaDeprecationErrors')).toBe(true); + expect(find('kibanaDeprecationErrors').text()).toContain( + 'Deprecation warnings may be incomplete' + ); + }); + + test('handles request error', async () => { + await act(async () => { + deprecationService.getAllDeprecations = jest + .fn() + .mockRejectedValue(new Error('Internal Server Error')); + + testBed = await setupKibanaPage({ + services: { + core: { + deprecations: deprecationService, + }, + }, + }); + }); + + const { component, exists, find } = testBed; + + component.update(); + + expect(exists('kibanaRequestError')).toBe(true); + expect(find('kibanaRequestError').text()).toContain('Could not retrieve Kibana deprecations'); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.helpers.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.helpers.ts index 860c9249b266a..345a06d3d80a0 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.helpers.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.helpers.ts @@ -4,9 +4,9 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -import { registerTestBed, TestBed, TestBedConfig } from '@kbn/test/jest'; -import { KibanaDeprecationsContent } from '../../../public/application/components/kibana_deprecations'; +import { act } from 'react-dom/test-utils'; +import { registerTestBed, TestBed, TestBedConfig, findTestSubject } from '@kbn/test/jest'; +import { KibanaDeprecations } from '../../../public/application/components'; import { WithAppDependencies } from '../helpers'; const testBedConfig: TestBedConfig = { @@ -22,17 +22,92 @@ export type KibanaTestBed = TestBed & { }; const createActions = (testBed: TestBed) => { + const { component, find, table } = testBed; + /** * User Actions */ + const tableActions = { + clickRefreshButton: async () => { + await act(async () => { + find('refreshButton').simulate('click'); + }); + + component.update(); + }, + + clickDeprecationAt: async (index: number) => { + const { rows } = table.getMetaData('kibanaDeprecationsTable'); + + const deprecationDetailsLink = findTestSubject( + rows[index].reactWrapper, + 'deprecationDetailsLink' + ); + + await act(async () => { + deprecationDetailsLink.simulate('click'); + }); + component.update(); + }, + }; + + const searchBarActions = { + openTypeFilterDropdown: async () => { + await act(async () => { + // EUI doesn't support data-test-subj's on the filter buttons, so we must access via CSS selector + find('kibanaDeprecations') + .find('.euiSearchBar__filtersHolder') + .find('.euiPopover') + .find('.euiFilterButton') + .at(0) + .simulate('click'); + }); + + component.update(); + }, + + clickCriticalFilterButton: async () => { + await act(async () => { + // EUI doesn't support data-test-subj's on the filter buttons, so we must access via CSS selector + find('kibanaDeprecations') + .find('.euiSearchBar__filtersHolder') + .find('.euiFilterButton') + .at(0) + .simulate('click'); + }); + + component.update(); + }, + + filterByConfigType: async () => { + // We need to read the document "body" as the filter dropdown options are added there and not inside + // the component DOM tree. The "Config" option is expected to be the first item. + const configTypeFilterButton: HTMLButtonElement | null = document.body.querySelector( + '.euiFilterSelect__items .euiFilterSelectItem' + ); + + await act(async () => { + configTypeFilterButton!.click(); + }); + + component.update(); + }, + }; + + const flyoutActions = { + clickResolveButton: async () => { + await act(async () => { + find('resolveButton').simulate('click'); + }); - const clickExpandAll = () => { - const { find } = testBed; - find('expandAll').simulate('click'); + component.update(); + }, }; return { - clickExpandAll, + table: tableActions, + flyout: flyoutActions, + searchBar: searchBarActions, }; }; @@ -40,7 +115,7 @@ export const setupKibanaPage = async ( overrides?: Record ): Promise => { const initTestBed = registerTestBed( - WithAppDependencies(KibanaDeprecationsContent, overrides), + WithAppDependencies(KibanaDeprecations, overrides), testBedConfig ); const testBed = await initTestBed(); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.test.ts deleted file mode 100644 index 7ac2b28ada5e0..0000000000000 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.test.ts +++ /dev/null @@ -1,245 +0,0 @@ -/* - * 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 type { DomainDeprecationDetails } from 'kibana/public'; -import { act } from 'react-dom/test-utils'; -import { deprecationsServiceMock } from 'src/core/public/mocks'; - -import { setupEnvironment } from '../helpers'; -import { KibanaTestBed, setupKibanaPage } from './kibana_deprecations.helpers'; - -describe('Kibana deprecations', () => { - let testBed: KibanaTestBed; - const { server } = setupEnvironment(); - - afterAll(() => { - server.restore(); - }); - - describe('With deprecations', () => { - const kibanaDeprecationsMockResponse: DomainDeprecationDetails[] = [ - { - title: 'mock-deprecation-title', - correctiveActions: { - manualSteps: ['Step 1', 'Step 2', 'Step 3'], - api: { - method: 'POST', - path: '/test', - }, - }, - domainId: 'test_domain', - level: 'critical', - message: 'Test deprecation message', - }, - ]; - - beforeEach(async () => { - await act(async () => { - const deprecationService = deprecationsServiceMock.createStartContract(); - deprecationService.getAllDeprecations = jest - .fn() - .mockReturnValue(kibanaDeprecationsMockResponse); - - testBed = await setupKibanaPage({ - services: { - core: { - deprecations: deprecationService, - }, - }, - }); - }); - - testBed.component.update(); - }); - - test('renders deprecations', () => { - const { exists, find } = testBed; - expect(exists('kibanaDeprecationsContent')).toBe(true); - expect(find('kibanaDeprecationItem').length).toEqual(1); - }); - - describe('manual steps modal', () => { - test('renders modal with a list of steps to fix a deprecation', async () => { - const { component, actions, exists, find } = testBed; - const deprecation = kibanaDeprecationsMockResponse[0]; - - expect(exists('kibanaDeprecationsContent')).toBe(true); - - // Open all deprecations - actions.clickExpandAll(); - - const accordionTestSubj = `${deprecation.domainId}Deprecation`; - - await act(async () => { - find(`${accordionTestSubj}.stepsButton`).simulate('click'); - }); - - component.update(); - - // We need to read the document "body" as the modal is added there and not inside - // the component DOM tree. - let modal = document.body.querySelector('[data-test-subj="stepsModal"]'); - - expect(modal).not.toBeNull(); - expect(modal!.textContent).toContain(`Resolve deprecation in '${deprecation.domainId}'`); - - const steps: NodeListOf | null = modal!.querySelectorAll( - '[data-test-subj="fixDeprecationSteps"] .euiStep' - ); - - expect(steps).not.toBe(null); - expect(steps.length).toEqual(deprecation!.correctiveActions!.manualSteps!.length); - - await act(async () => { - const closeButton: HTMLButtonElement | null = modal!.querySelector( - '[data-test-subj="closeButton"]' - ); - - closeButton!.click(); - }); - - component.update(); - - // Confirm modal closed and no longer appears in the DOM - modal = document.body.querySelector('[data-test-subj="stepsModal"]'); - expect(modal).toBe(null); - }); - }); - - describe('resolve modal', () => { - test('renders confirmation modal to resolve a deprecation', async () => { - const { component, actions, exists, find } = testBed; - const deprecation = kibanaDeprecationsMockResponse[0]; - - expect(exists('kibanaDeprecationsContent')).toBe(true); - - // Open all deprecations - actions.clickExpandAll(); - - const accordionTestSubj = `${deprecation.domainId}Deprecation`; - - await act(async () => { - find(`${accordionTestSubj}.resolveButton`).simulate('click'); - }); - - component.update(); - - // We need to read the document "body" as the modal is added there and not inside - // the component DOM tree. - let modal = document.body.querySelector('[data-test-subj="resolveModal"]'); - - expect(modal).not.toBe(null); - expect(modal!.textContent).toContain(`Resolve deprecation in '${deprecation.domainId}'`); - - const confirmButton: HTMLButtonElement | null = modal!.querySelector( - '[data-test-subj="confirmModalConfirmButton"]' - ); - - await act(async () => { - confirmButton!.click(); - }); - - component.update(); - - // Confirm modal should close and no longer appears in the DOM - modal = document.body.querySelector('[data-test-subj="resolveModal"]'); - expect(modal).toBe(null); - }); - }); - }); - - describe('No deprecations', () => { - beforeEach(async () => { - await act(async () => { - testBed = await setupKibanaPage({ isReadOnlyMode: false }); - }); - - const { component } = testBed; - - component.update(); - }); - - test('renders prompt', () => { - const { exists, find } = testBed; - expect(exists('noDeprecationsPrompt')).toBe(true); - expect(find('noDeprecationsPrompt').text()).toContain( - 'Your Kibana configuration is up to date' - ); - }); - }); - - describe('Error handling', () => { - test('handles request error', async () => { - await act(async () => { - const deprecationService = deprecationsServiceMock.createStartContract(); - deprecationService.getAllDeprecations = jest - .fn() - .mockRejectedValue(new Error('Internal Server Error')); - - testBed = await setupKibanaPage({ - services: { - core: { - deprecations: deprecationService, - }, - }, - }); - }); - - const { component, exists, find } = testBed; - - component.update(); - - expect(exists('kibanaRequestError')).toBe(true); - expect(find('kibanaRequestError').text()).toContain('Could not retrieve Kibana deprecations'); - }); - - test('handles deprecation service error', async () => { - const domainId = 'test'; - const kibanaDeprecationsMockResponse: DomainDeprecationDetails[] = [ - { - domainId, - title: `Failed to fetch deprecations for ${domainId}`, - message: `Failed to get deprecations info for plugin "${domainId}".`, - level: 'fetch_error', - correctiveActions: { - manualSteps: ['Check Kibana server logs for error message.'], - }, - }, - ]; - - await act(async () => { - const deprecationService = deprecationsServiceMock.createStartContract(); - deprecationService.getAllDeprecations = jest - .fn() - .mockReturnValue(kibanaDeprecationsMockResponse); - - testBed = await setupKibanaPage({ - services: { - core: { - deprecations: deprecationService, - }, - }, - }); - }); - - const { component, exists, find, actions } = testBed; - component.update(); - - // Verify top-level callout renders - expect(exists('kibanaPluginError')).toBe(true); - expect(find('kibanaPluginError').text()).toContain( - 'Not all Kibana deprecations were retrieved successfully' - ); - - // Open all deprecations - actions.clickExpandAll(); - - // Verify callout also displays for deprecation with error - expect(exists(`${domainId}Error`)).toBe(true); - }); - }); -}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/mocked_responses.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/mocked_responses.ts new file mode 100644 index 0000000000000..261fe719bf5bf --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/mocked_responses.ts @@ -0,0 +1,34 @@ +/* + * 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 type { DomainDeprecationDetails } from 'kibana/public'; + +export const kibanaDeprecationsMockResponse: DomainDeprecationDetails[] = [ + { + correctiveActions: { + manualSteps: ['Step 1', 'Step 2', 'Step 3'], + api: { + method: 'POST', + path: '/test', + }, + }, + domainId: 'test_domain_1', + level: 'critical', + title: 'Test deprecation title 1', + message: 'Test deprecation message 1', + deprecationType: 'config', + }, + { + correctiveActions: { + manualSteps: ['Step 1', 'Step 2', 'Step 3'], + }, + domainId: 'test_domain_2', + level: 'warning', + title: 'Test deprecation title 1', + message: 'Test deprecation message 2', + deprecationType: 'feature', + }, +]; diff --git a/x-pack/plugins/upgrade_assistant/public/application/app.tsx b/x-pack/plugins/upgrade_assistant/public/application/app.tsx index cc921bdaefc15..0d32d1b661b84 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/app.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/app.tsx @@ -8,16 +8,12 @@ import React from 'react'; import { Router, Switch, Route, Redirect } from 'react-router-dom'; import { ScopedHistory } from 'src/core/public'; -import { GlobalFlyout } from '../shared_imports'; -import { APP_WRAPPER_CLASS } from '../shared_imports'; -import { AppContextProvider, useAppContext } from './app_context'; -import { ComingSoonPrompt } from './components/coming_soon_prompt'; -import { EsDeprecations } from './components/es_deprecations'; -import { KibanaDeprecationsContent } from './components/kibana_deprecations'; -import { Overview } from './components/overview'; import { RedirectAppLinks } from '../../../../../src/plugins/kibana_react/public'; +import { APP_WRAPPER_CLASS, GlobalFlyout } from '../shared_imports'; import { AppDependencies } from '../types'; +import { AppContextProvider, useAppContext } from './app_context'; +import { EsDeprecations, ComingSoonPrompt, KibanaDeprecations, Overview } from './components'; const { GlobalFlyoutProvider } = GlobalFlyout; @@ -33,7 +29,7 @@ const App: React.FunctionComponent = () => { - + ); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/constants.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/constants.tsx index c7f974fab6a89..34850e6c97543 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/constants.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/constants.tsx @@ -5,30 +5,8 @@ * 2.0. */ -import { IconColor } from '@elastic/eui'; -import { invert } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { DeprecationInfo } from '../../../common/types'; - -export const LEVEL_MAP: { [level: string]: number } = { - warning: 0, - critical: 1, -}; - -interface ReverseLevelMap { - [idx: number]: DeprecationInfo['level']; -} - -export const REVERSE_LEVEL_MAP: ReverseLevelMap = invert(LEVEL_MAP) as ReverseLevelMap; - -export const COLOR_MAP: { [level: string]: IconColor } = { - warning: 'default', - critical: 'danger', -}; - -export const DEPRECATIONS_PER_PAGE = 25; - export const DEPRECATION_TYPE_MAP = { cluster_settings: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.clusterDeprecationTypeLabel', @@ -49,3 +27,8 @@ export const DEPRECATION_TYPE_MAP = { defaultMessage: 'Machine Learning', }), }; + +export const PAGINATION_CONFIG = { + initialPageSize: 50, + pageSizeOptions: [50, 100, 200], +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx index 52722a52be6d3..b823740433f84 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx @@ -8,14 +8,7 @@ import React, { useEffect, useMemo } from 'react'; import { withRouter, RouteComponentProps } from 'react-router-dom'; -import { - EuiPageHeader, - EuiSpacer, - EuiPageContent, - EuiFlexGroup, - EuiFlexItem, - EuiHealth, -} from '@elastic/eui'; +import { EuiPageHeader, EuiSpacer, EuiPageContent } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { EnrichedDeprecationInfo } from '../../../../common/types'; @@ -23,7 +16,7 @@ import { SectionLoading } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; import { EsDeprecationsTable } from './es_deprecations_table'; import { EsDeprecationErrors } from './es_deprecation_errors'; -import { NoDeprecationsPrompt } from '../shared'; +import { NoDeprecationsPrompt, DeprecationCount } from '../shared'; const getDeprecationCountByLevel = (deprecations: EnrichedDeprecationInfo[]) => { const criticalDeprecations: EnrichedDeprecationInfo[] = []; @@ -54,20 +47,6 @@ const i18nTexts = { isLoading: i18n.translate('xpack.upgradeAssistant.esDeprecations.loadingText', { defaultMessage: 'Loading deprecations…', }), - getCriticalStatusLabel: (count: number) => - i18n.translate('xpack.upgradeAssistant.esDeprecations.criticalStatusLabel', { - defaultMessage: 'Critical: {count}', - values: { - count, - }, - }), - getWarningStatusLabel: (count: number) => - i18n.translate('xpack.upgradeAssistant.esDeprecations.warningStatusLabel', { - defaultMessage: 'Warning: {count}', - values: { - count, - }, - }), }; export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { @@ -132,18 +111,10 @@ export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { return (
- - - - {i18nTexts.getCriticalStatusLabel(deprecationsCountByLevel.criticalDeprecations)} - - - - - {i18nTexts.getWarningStatusLabel(deprecationsCountByLevel.warningDeprecations)} - - - + diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx index 30866e9299f34..f1b693fa48f57 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx @@ -33,7 +33,7 @@ import { ReindexTableRow, } from './deprecation_types'; import { DeprecationTableColumns } from '../types'; -import { DEPRECATION_TYPE_MAP } from '../constants'; +import { DEPRECATION_TYPE_MAP, PAGINATION_CONFIG } from '../constants'; const i18nTexts = { refreshButtonLabel: i18n.translate( @@ -99,7 +99,7 @@ const cellToLabelMap = { }; const cellTypes = Object.keys(cellToLabelMap) as DeprecationTableColumns[]; -const pageSizeOptions = [50, 100, 200]; +const pageSizeOptions = PAGINATION_CONFIG.pageSizeOptions; const renderTableRowCells = (deprecation: EnrichedDeprecationInfo) => { switch (deprecation.correctiveAction?.type) { @@ -151,7 +151,7 @@ export const EsDeprecationsTable: React.FunctionComponent = ({ sortField: 'isCritical', }); - const [itemsPerPage, setItemsPerPage] = useState(pageSizeOptions[0]); + const [itemsPerPage, setItemsPerPage] = useState(PAGINATION_CONFIG.initialPageSize); const [currentPageIndex, setCurrentPageIndex] = useState(0); const [searchQuery, setSearchQuery] = useState(EuiSearchBar.Query.MATCH_ALL); const [searchError, setSearchError] = useState<{ message: string } | undefined>(undefined); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/index.ts similarity index 54% rename from x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/index.ts rename to x-pack/plugins/upgrade_assistant/public/application/components/index.ts index cbc04fd86bfbd..8924fa2d355a1 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/index.ts @@ -5,4 +5,7 @@ * 2.0. */ -export { DeprecationListBar } from './deprecation_list_bar'; +export { KibanaDeprecations } from './kibana_deprecations'; +export { EsDeprecations } from './es_deprecations'; +export { ComingSoonPrompt } from './coming_soon_prompt'; +export { Overview } from './overview'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/_deprecation_details_flyout.scss b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/_deprecation_details_flyout.scss new file mode 100644 index 0000000000000..c877ea4b48821 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/_deprecation_details_flyout.scss @@ -0,0 +1,4 @@ +// Used to add spacing between the list of manual deprecation steps +.upgResolveStep { + margin-bottom: $euiSizeL; +} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx new file mode 100644 index 0000000000000..d9d7b50c87f0c --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx @@ -0,0 +1,235 @@ +/* + * 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 React from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { + EuiButtonEmpty, + EuiButton, + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlyoutHeader, + EuiFlexGroup, + EuiFlexItem, + EuiTitle, + EuiText, + EuiCallOut, + EuiLink, + EuiSpacer, +} from '@elastic/eui'; + +import type { DeprecationResolutionState, KibanaDeprecationDetails } from './kibana_deprecations'; + +import './_deprecation_details_flyout.scss'; + +export interface DeprecationDetailsFlyoutProps { + deprecation: KibanaDeprecationDetails; + closeFlyout: () => void; + resolveDeprecation: (deprecationDetails: KibanaDeprecationDetails) => Promise; + deprecationResolutionState?: DeprecationResolutionState; +} + +const i18nTexts = { + learnMoreLinkLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.learnMoreLinkLabel', + { + defaultMessage: 'Learn more about this deprecation', + } + ), + closeButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.closeButtonLabel', + { + defaultMessage: 'Close', + } + ), + quickResolveButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveButtonLabel', + { + defaultMessage: 'Quick resolve', + } + ), + retryQuickResolveButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.retryQuickResolveButtonLabel', + { + defaultMessage: 'Try again', + } + ), + resolvedButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.resolvedButtonLabel', + { + defaultMessage: 'Resolved', + } + ), + quickResolveInProgressButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveInProgressButtonLabel', + { + defaultMessage: 'Resolution in progress…', + } + ), + quickResolveCalloutTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveCalloutTitle', + { + defaultMessage: 'Quick resolve action available', + } + ), + quickResolveErrorTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveErrorTitle', + { + defaultMessage: 'Error resolving deprecation', + } + ), + quickResolveCalloutDescription: ( + + {i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveText', { + defaultMessage: 'Quick resolve', + })} + + ), + }} + /> + ), + manualFixTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.manualFixTitle', + { + defaultMessage: 'Fix manually', + } + ), +}; + +const getQuickResolveButtonLabel = (deprecationResolutionState?: DeprecationResolutionState) => { + if (deprecationResolutionState?.resolveDeprecationStatus === 'in_progress') { + return i18nTexts.quickResolveInProgressButtonLabel; + } + + if (deprecationResolutionState?.resolveDeprecationStatus === 'ok') { + return i18nTexts.resolvedButtonLabel; + } + + if (deprecationResolutionState?.resolveDeprecationError) { + return i18nTexts.retryQuickResolveButtonLabel; + } + + return i18nTexts.quickResolveButtonLabel; +}; + +export const DeprecationDetailsFlyout = ({ + deprecation, + closeFlyout, + resolveDeprecation, + deprecationResolutionState, +}: DeprecationDetailsFlyoutProps) => { + const { documentationUrl, message, correctiveActions, title } = deprecation; + + return ( + <> + + +

{title}

+
+
+ + {deprecationResolutionState?.resolveDeprecationStatus === 'fail' && ( + <> + + {deprecationResolutionState.resolveDeprecationError} + + + + )} + + +

{message}

+ + {documentationUrl && ( +

+ + {i18nTexts.learnMoreLinkLabel} + +

+ )} +
+ + + + {/* Hide resolution steps if already resolved */} + {deprecationResolutionState?.resolveDeprecationStatus !== 'ok' && ( +
+ {correctiveActions.api && ( + <> + +

{i18nTexts.quickResolveCalloutDescription}

+
+ + + + )} + + +

{i18nTexts.manualFixTitle}

+
+ + + + +
    + {correctiveActions.manualSteps.map((step, stepIndex) => ( +
  1. + {step} +
  2. + ))} +
+
+
+ )} +
+ + + + + + {i18nTexts.closeButtonLabel} + + + + {/* Only show the "Quick resolve" button if deprecation supports it */} + {correctiveActions.api && ( + + resolveDeprecation(deprecation)} + isLoading={Boolean( + deprecationResolutionState?.resolveDeprecationStatus === 'in_progress' + )} + disabled={Boolean(deprecationResolutionState?.resolveDeprecationStatus === 'ok')} + > + {getQuickResolveButtonLabel(deprecationResolutionState)} + + + )} + + + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx deleted file mode 100644 index 5bcc49590c55e..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx +++ /dev/null @@ -1,145 +0,0 @@ -/* - * 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 React, { FunctionComponent } from 'react'; -import { - EuiAccordion, - EuiButton, - EuiFlexGroup, - EuiFlexItem, - EuiButtonEmpty, - EuiText, - EuiCallOut, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import type { DomainDeprecationDetails } from 'kibana/public'; -import { DeprecationHealth } from '../shared'; -import { LEVEL_MAP } from '../constants'; -import { StepsModalContent } from './steps_modal'; - -const i18nTexts = { - getDeprecationTitle: (domainId: string) => { - return i18n.translate('xpack.upgradeAssistant.deprecationGroupItemTitle', { - defaultMessage: "'{domainId}' is using a deprecated feature", - values: { - domainId, - }, - }); - }, - docLinkText: i18n.translate('xpack.upgradeAssistant.deprecationGroupItem.docLinkText', { - defaultMessage: 'View documentation', - }), - manualFixButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.deprecationGroupItem.fixButtonLabel', - { - defaultMessage: 'Show steps to fix', - } - ), - resolveButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.deprecationGroupItem.resolveButtonLabel', - { - defaultMessage: 'Quick resolve', - } - ), -}; - -export interface Props { - deprecation: DomainDeprecationDetails; - index: number; - forceExpand: boolean; - showStepsModal: (modalContent: StepsModalContent) => void; - showResolveModal: (deprecation: DomainDeprecationDetails) => void; -} - -export const KibanaDeprecationAccordion: FunctionComponent = ({ - deprecation, - forceExpand, - index, - showStepsModal, - showResolveModal, -}) => { - const { domainId, level, message, documentationUrl, correctiveActions } = deprecation; - - return ( - } - > - - - - {level === 'fetch_error' ? ( - - ) : ( - <> -

{message}

- - {(documentationUrl || correctiveActions?.manualSteps) && ( - - {correctiveActions?.api && ( - - showResolveModal(deprecation)} - > - {i18nTexts.resolveButtonLabel} - - - )} - - {correctiveActions?.manualSteps && ( - - - showStepsModal({ - domainId, - steps: correctiveActions.manualSteps!, - documentationUrl, - }) - } - > - {i18nTexts.manualFixButtonLabel} - - - )} - - {documentationUrl && ( - - - {i18nTexts.docLinkText} - - - )} - - )} - - )} -
-
-
-
- ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx deleted file mode 100644 index fb61efc373acf..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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 React, { FunctionComponent, useState, useEffect } from 'react'; -import { groupBy } from 'lodash'; -import { EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; - -import type { DomainDeprecationDetails } from 'kibana/public'; - -import { LevelFilterOption } from '../types'; -import { SearchBar, DeprecationListBar, DeprecationPagination } from '../shared'; -import { DEPRECATIONS_PER_PAGE } from '../constants'; -import { KibanaDeprecationAccordion } from './deprecation_item'; -import { StepsModalContent } from './steps_modal'; -import { KibanaDeprecationErrors } from './kibana_deprecation_errors'; - -interface Props { - deprecations: DomainDeprecationDetails[]; - showStepsModal: (newStepsModalContent: StepsModalContent) => void; - showResolveModal: (deprecation: DomainDeprecationDetails) => void; - reloadDeprecations: () => Promise; - isLoading: boolean; -} - -const getFilteredDeprecations = ( - deprecations: DomainDeprecationDetails[], - level: LevelFilterOption, - search: string -) => { - return deprecations - .filter((deprecation) => { - return level === 'all' || deprecation.level === level; - }) - .filter((filteredDep) => { - if (search.length > 0) { - try { - // 'i' is used for case-insensitive matching - const searchReg = new RegExp(search, 'i'); - return searchReg.test(filteredDep.message); - } catch (e) { - // ignore any regexp errors - return true; - } - } - return true; - }); -}; - -export const KibanaDeprecationList: FunctionComponent = ({ - deprecations, - showStepsModal, - showResolveModal, - reloadDeprecations, - isLoading, -}) => { - const [currentFilter, setCurrentFilter] = useState('all'); - const [search, setSearch] = useState(''); - const [expandState, setExpandState] = useState({ - forceExpand: false, - expandNumber: 0, - }); - const [currentPage, setCurrentPage] = useState(0); - - const setExpandAll = (expandAll: boolean) => { - setExpandState({ forceExpand: expandAll, expandNumber: expandState.expandNumber + 1 }); - }; - - const levelGroups = groupBy(deprecations, 'level'); - const levelToDeprecationCountMap = Object.keys(levelGroups).reduce((counts, level) => { - counts[level] = levelGroups[level].length; - return counts; - }, {} as { [level: string]: number }); - - const filteredDeprecations = getFilteredDeprecations(deprecations, currentFilter, search); - - const deprecationsWithErrors = deprecations.filter((dep) => dep.level === 'fetch_error'); - - useEffect(() => { - const pageCount = Math.ceil(filteredDeprecations.length / DEPRECATIONS_PER_PAGE); - if (currentPage >= pageCount) { - setCurrentPage(0); - } - }, [filteredDeprecations, currentPage]); - - return ( - <> - - - {deprecationsWithErrors.length > 0 && ( - <> - - - - )} - - - - - - <> - {filteredDeprecations - .slice(currentPage * DEPRECATIONS_PER_PAGE, (currentPage + 1) * DEPRECATIONS_PER_PAGE) - .map((deprecation, index) => [ -
- - -
, - ])} - - {/* Only show pagination if we have more than DEPRECATIONS_PER_PAGE */} - {filteredDeprecations.length > DEPRECATIONS_PER_PAGE && ( - <> - - - - - )} - - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/index.ts index 84d2b88757188..6a1375f57cd43 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { KibanaDeprecationsContent } from './kibana_deprecations'; +export { KibanaDeprecations } from './kibana_deprecations'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx deleted file mode 100644 index 79ada21941b56..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 React from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiPageContent, EuiEmptyPrompt } from '@elastic/eui'; - -interface Props { - errorType: 'pluginError' | 'requestError'; -} - -const i18nTexts = { - pluginError: { - title: i18n.translate('xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorTitle', { - defaultMessage: 'Not all Kibana deprecations were retrieved successfully', - }), - description: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorDescription', - { - defaultMessage: 'Check the Kibana server logs for errors.', - } - ), - }, - loadingError: { - title: i18n.translate('xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorTitle', { - defaultMessage: 'Could not retrieve Kibana deprecations', - }), - description: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorDescription', - { - defaultMessage: 'Check the Kibana server logs for errors.', - } - ), - }, -}; - -export const KibanaDeprecationErrors: React.FunctionComponent = ({ errorType }) => { - if (errorType === 'pluginError') { - return ( - - {i18nTexts.pluginError.title}} - body={

{i18nTexts.pluginError.description}

} - /> -
- ); - } - - return ( - - {i18nTexts.loadingError.title}} - body={

{i18nTexts.loadingError.description}

} - /> -
- ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index 90f8936d0e38d..a6d7e4fdb674a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -5,30 +5,44 @@ * 2.0. */ -import React, { useEffect, useState, useCallback } from 'react'; +import React, { useEffect, useState, useCallback, useMemo } from 'react'; +import uuid from 'uuid'; import { withRouter, RouteComponentProps } from 'react-router-dom'; - -import { EuiButtonEmpty, EuiPageContent, EuiPageHeader, EuiSpacer } from '@elastic/eui'; +import { EuiPageContent, EuiPageHeader, EuiSpacer, EuiCallOut, EuiEmptyPrompt } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import type { DomainDeprecationDetails } from 'kibana/public'; -import { SectionLoading } from '../../../shared_imports'; +import { SectionLoading, GlobalFlyout } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; -import { NoDeprecationsPrompt } from '../shared'; -import { KibanaDeprecationList } from './deprecation_list'; -import { StepsModal, StepsModalContent } from './steps_modal'; -import { KibanaDeprecationErrors } from './kibana_deprecation_errors'; -import { ResolveDeprecationModal } from './resolve_deprecation_modal'; -import { LEVEL_MAP } from '../constants'; +import { NoDeprecationsPrompt, DeprecationCount } from '../shared'; +import { KibanaDeprecationsTable } from './kibana_deprecations_table'; +import { + DeprecationDetailsFlyout, + DeprecationDetailsFlyoutProps, +} from './deprecation_details_flyout'; + +const { useGlobalFlyout } = GlobalFlyout; const i18nTexts = { pageTitle: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.pageTitle', { - defaultMessage: 'Kibana', - }), - pageDescription: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.pageDescription', { - defaultMessage: - 'Review the issues listed here and make the necessary changes before upgrading. Critical issues must be resolved before you upgrade.', + defaultMessage: 'Kibana deprecation warnings', }), + pageDescription: ( + + {i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.quickResolveText', { + defaultMessage: 'Quick Resolve', + })} + + ), + }} + /> + ), docLinkText: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.docLinkText', { defaultMessage: 'Documentation', }), @@ -38,47 +52,114 @@ const i18nTexts = { isLoading: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.loadingText', { defaultMessage: 'Loading deprecations…', }), - successMessage: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.successMessage', { - defaultMessage: 'Deprecation resolved', - }), - errorMessage: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.errorMessage', { - defaultMessage: 'Error resolving deprecation', + kibanaDeprecationErrorTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.kibanaDeprecationErrorTitle', + { + defaultMessage: 'Deprecation warnings may be incomplete', + } + ), + getKibanaDeprecationErrorDescription: (pluginIds: string[]) => + i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.kibanaDeprecationErrorDescription', { + defaultMessage: + 'Failed to get deprecation warnings for {pluginCount, plural, one {this plugin} other {these plugins}}: {pluginIds}. Check the Kibana server logs for more details.', + values: { + pluginCount: pluginIds.length, + pluginIds: pluginIds.join(', '), + }, + }), + requestErrorTitle: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.requestErrorTitle', { + defaultMessage: 'Could not retrieve Kibana deprecations', }), + requestErrorDescription: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecationErrors.requestErrorDescription', + { + defaultMessage: 'Check the Kibana server logs for errors.', + } + ), }; -const sortByLevelDesc = (a: DomainDeprecationDetails, b: DomainDeprecationDetails) => { - return -1 * (LEVEL_MAP[a.level] - LEVEL_MAP[b.level]); +export interface DeprecationResolutionState { + id: string; + resolveDeprecationStatus: 'ok' | 'fail' | 'in_progress'; + resolveDeprecationError?: string; +} + +export interface KibanaDeprecationDetails extends DomainDeprecationDetails { + id: string; + filterType: DomainDeprecationDetails['deprecationType'] | 'uncategorized'; +} + +const getDeprecationCountByLevel = (deprecations: KibanaDeprecationDetails[]) => { + const criticalDeprecations: KibanaDeprecationDetails[] = []; + const warningDeprecations: KibanaDeprecationDetails[] = []; + + deprecations.forEach((deprecation) => { + if (deprecation.level === 'critical') { + criticalDeprecations.push(deprecation); + return; + } + warningDeprecations.push(deprecation); + }); + + return { + criticalDeprecations: criticalDeprecations.length, + warningDeprecations: warningDeprecations.length, + }; }; -export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponentProps) => { +export const KibanaDeprecations = withRouter(({ history }: RouteComponentProps) => { const [kibanaDeprecations, setKibanaDeprecations] = useState< - DomainDeprecationDetails[] | undefined + KibanaDeprecationDetails[] | undefined >(undefined); + const [kibanaDeprecationErrors, setKibanaDeprecationErrors] = useState([]); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(undefined); - const [stepsModalContent, setStepsModalContent] = useState( + const [flyoutContent, setFlyoutContent] = useState( undefined ); - const [resolveModalContent, setResolveModalContent] = useState< - undefined | DomainDeprecationDetails + const [deprecationResolutionState, setDeprecationResolutionState] = useState< + DeprecationResolutionState | undefined >(undefined); - const [isResolvingDeprecation, setIsResolvingDeprecation] = useState(false); const { services: { - core: { deprecations, docLinks, notifications }, + core: { deprecations }, breadcrumbs, api, }, } = useAppContext(); + const { + addContent: addContentToGlobalFlyout, + removeContent: removeContentFromGlobalFlyout, + } = useGlobalFlyout(); + const getAllDeprecations = useCallback(async () => { setIsLoading(true); try { - const response = await deprecations.getAllDeprecations(); - const sortedDeprecations = response.sort(sortByLevelDesc); - setKibanaDeprecations(sortedDeprecations); + const allDeprecations = await deprecations.getAllDeprecations(); + + const filteredDeprecations: KibanaDeprecationDetails[] = []; + const deprecationErrors: string[] = []; + + allDeprecations.forEach((deprecation) => { + // Keep track of any deprecations that failed to fetch to show warning in UI + if (deprecation.level === 'fetch_error') { + deprecationErrors.push(deprecation.domainId); + return; + } + + // Only show deprecations in the table that fetched successfully + filteredDeprecations.push({ + ...deprecation, + id: uuid.v4(), // Associate an unique ID with each deprecation to track resolution state + filterType: deprecation.deprecationType ?? 'uncategorized', // deprecationType is currently optional, in order to correctly handle sort/filter, we default any undefined types to "uncategorized" + }); + }); + + setKibanaDeprecations(filteredDeprecations); + setKibanaDeprecationErrors(deprecationErrors); } catch (e) { setError(e); } @@ -86,35 +167,68 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent setIsLoading(false); }, [deprecations]); - const toggleStepsModal = (newStepsModalContent?: StepsModalContent) => { - setStepsModalContent(newStepsModalContent); - }; + const deprecationsCountByLevel: { + warningDeprecations: number; + criticalDeprecations: number; + } = useMemo(() => getDeprecationCountByLevel(kibanaDeprecations || []), [kibanaDeprecations]); - const toggleResolveModal = (newResolveModalContent?: DomainDeprecationDetails) => { - setResolveModalContent(newResolveModalContent); + const toggleFlyout = (newFlyoutContent?: KibanaDeprecationDetails) => { + setFlyoutContent(newFlyoutContent); }; - const resolveDeprecation = async (deprecationDetails: DomainDeprecationDetails) => { - setIsResolvingDeprecation(true); + const closeFlyout = useCallback(() => { + toggleFlyout(); + removeContentFromGlobalFlyout('deprecationDetails'); + }, [removeContentFromGlobalFlyout]); - const response = await deprecations.resolveDeprecation(deprecationDetails); + const resolveDeprecation = useCallback( + async (deprecationDetails: KibanaDeprecationDetails) => { + setDeprecationResolutionState({ + id: deprecationDetails.id, + resolveDeprecationStatus: 'in_progress', + }); - setIsResolvingDeprecation(false); - toggleResolveModal(); + const response = await deprecations.resolveDeprecation(deprecationDetails); - // Handle error case - if (response.status === 'fail') { - notifications.toasts.addError(new Error(response.reason), { - title: i18nTexts.errorMessage, + setDeprecationResolutionState({ + id: deprecationDetails.id, + resolveDeprecationStatus: response.status, + resolveDeprecationError: response.status === 'fail' ? response.reason : undefined, }); - return; - } + closeFlyout(); + }, + [closeFlyout, deprecations] + ); - notifications.toasts.addSuccess(i18nTexts.successMessage); - // Refetch deprecations - getAllDeprecations(); - }; + useEffect(() => { + if (flyoutContent) { + addContentToGlobalFlyout({ + id: 'deprecationDetails', + Component: DeprecationDetailsFlyout, + props: { + deprecation: flyoutContent, + closeFlyout, + resolveDeprecation, + deprecationResolutionState: + deprecationResolutionState && flyoutContent.id === deprecationResolutionState.id + ? deprecationResolutionState + : undefined, + }, + flyoutProps: { + onClose: closeFlyout, + 'data-test-subj': 'kibanaDeprecationDetails', + 'aria-labelledby': 'kibanaDeprecationDetailsFlyoutTitle', + }, + }); + } + }, [ + addContentToGlobalFlyout, + closeFlyout, + deprecationResolutionState, + flyoutContent, + resolveDeprecation, + ]); useEffect(() => { async function sendTelemetryData() { @@ -151,51 +265,64 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent {i18nTexts.isLoading} ); - } else if (kibanaDeprecations?.length) { + } + + if (kibanaDeprecations?.length) { return ( -
+
- {i18nTexts.docLinkText} - , - ]} - /> + > + + - + {kibanaDeprecationErrors.length > 0 && ( + <> + +

{i18nTexts.getKibanaDeprecationErrorDescription(kibanaDeprecationErrors)}

+
- {stepsModalContent && ( - toggleStepsModal()} modalContent={stepsModalContent} /> + + )} - {resolveModalContent && ( - toggleResolveModal()} - resolveDeprecation={resolveDeprecation} - isResolvingDeprecation={isResolvingDeprecation} - deprecation={resolveModalContent} - /> - )} +
); - } else if (error) { - return ; + } + + if (error) { + return ( + + {i18nTexts.requestErrorTitle}} + body={

{i18nTexts.requestErrorDescription}

} + /> +
+ ); } return null; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx new file mode 100644 index 0000000000000..9117bcdbcaee5 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx @@ -0,0 +1,251 @@ +/* + * 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 React from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiInMemoryTable, + EuiBasicTableColumn, + EuiButton, + EuiLink, + EuiBadge, + Search, +} from '@elastic/eui'; + +import { PAGINATION_CONFIG } from '../constants'; +import type { DeprecationResolutionState, KibanaDeprecationDetails } from './kibana_deprecations'; +import { ResolutionTableCell } from './resolution_table_cell'; + +const i18nTexts = { + refreshButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.refreshButtonLabel', + { + defaultMessage: 'Refresh', + } + ), + statusColumnTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.statusColumnTitle', + { + defaultMessage: 'Status', + } + ), + issueColumnTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.issueColumnTitle', + { + defaultMessage: 'Issue', + } + ), + typeColumnTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.typeColumnTitle', + { + defaultMessage: 'Type', + } + ), + resolutionColumnTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.resolutionColumnTitle', + { + defaultMessage: 'Resolution', + } + ), + configDeprecationTypeCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.configDeprecationTypeCellLabel', + { + defaultMessage: 'Config', + } + ), + featureDeprecationTypeCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.featureDeprecationTypeCellLabel', + { + defaultMessage: 'Feature', + } + ), + unknownDeprecationTypeCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.unknownDeprecationTypeCellLabel', + { + defaultMessage: 'Uncategorized', + } + ), + typeFilterLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.typeFilterLabel', + { + defaultMessage: 'Type', + } + ), + criticalFilterLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.criticalFilterLabel', + { + defaultMessage: 'Critical', + } + ), + criticalBadgeLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.criticalBadgeLabel', + { + defaultMessage: 'critical', + } + ), + searchPlaceholderLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.searchPlaceholderLabel', + { + defaultMessage: 'Filter', + } + ), +}; + +interface Props { + deprecations?: KibanaDeprecationDetails[]; + reload: () => void; + toggleFlyout: (newFlyoutContent?: KibanaDeprecationDetails) => void; + deprecationResolutionState?: DeprecationResolutionState; +} + +export const KibanaDeprecationsTable: React.FunctionComponent = ({ + deprecations, + reload, + toggleFlyout, + deprecationResolutionState, +}) => { + const columns: Array> = [ + { + field: 'level', + name: i18nTexts.statusColumnTitle, + width: '5%', + truncateText: true, + sortable: true, + render: (level: KibanaDeprecationDetails['level']) => { + if (level === 'critical') { + return {i18nTexts.criticalBadgeLabel}; + } + + return <>{''}; + }, + }, + { + field: 'title', + width: '40%', + name: i18nTexts.issueColumnTitle, + truncateText: true, + sortable: true, + render: (title: KibanaDeprecationDetails['title'], deprecation: KibanaDeprecationDetails) => { + return ( + toggleFlyout(deprecation)} + data-test-subj="deprecationDetailsLink" + > + {title} + + ); + }, + }, + { + field: 'filterType', + name: i18nTexts.typeColumnTitle, + width: '20%', + truncateText: true, + sortable: true, + render: (filterType: KibanaDeprecationDetails['filterType']) => { + switch (filterType) { + case 'config': + return i18nTexts.configDeprecationTypeCellLabel; + case 'feature': + return i18nTexts.featureDeprecationTypeCellLabel; + case 'uncategorized': + default: + return i18nTexts.unknownDeprecationTypeCellLabel; + } + }, + }, + { + field: 'correctiveActions', + name: i18nTexts.resolutionColumnTitle, + width: '30%', + truncateText: true, + sortable: true, + render: ( + correctiveActions: KibanaDeprecationDetails['correctiveActions'], + deprecation: KibanaDeprecationDetails + ) => { + return ( + + ); + }, + }, + ]; + + const sorting = { + sort: { + field: 'level', + direction: 'asc', + }, + } as const; + + const searchConfig: Search = { + filters: [ + { + type: 'field_value_toggle', + name: i18nTexts.criticalFilterLabel, + field: 'level', + value: 'critical', + }, + { + type: 'field_value_selection', + field: 'filterType', + name: i18nTexts.typeFilterLabel, + multiSelect: false, + options: [ + { + value: 'config', + name: i18nTexts.configDeprecationTypeCellLabel, + }, + { + value: 'feature', + name: i18nTexts.featureDeprecationTypeCellLabel, + }, + { + value: 'uncategorized', + name: i18nTexts.unknownDeprecationTypeCellLabel, + }, + ], + }, + ], + box: { + incremental: true, + placeholder: i18nTexts.searchPlaceholderLabel, + }, + toolsRight: [ + + {i18nTexts.refreshButtonLabel} + , + ], + }; + + return ( + ({ + 'data-test-subj': 'row', + })} + cellProps={(deprecation, field) => ({ + 'data-test-subj': `${((field?.name as string) || 'table').toLowerCase()}Cell`, + })} + data-test-subj="kibanaDeprecationsTable" + tableLayout="auto" + /> + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolution_table_cell.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolution_table_cell.tsx new file mode 100644 index 0000000000000..aef52fe07a183 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolution_table_cell.tsx @@ -0,0 +1,145 @@ +/* + * 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 React from 'react'; + +import { + EuiFlexItem, + EuiText, + EuiFlexGroup, + EuiIcon, + EuiLoadingSpinner, + EuiToolTip, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import type { DeprecationResolutionState } from './kibana_deprecations'; + +const i18nTexts = { + manualCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.manualCellLabel', + { + defaultMessage: 'Manual', + } + ), + manualCellTooltipLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.manualCellTooltipLabel', + { + defaultMessage: 'Resolve this deprecation manually.', + } + ), + automatedCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.automatedCellLabel', + { + defaultMessage: 'Automated', + } + ), + automationInProgressCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.automationInProgressCellLabel', + { + defaultMessage: 'Resolution in progress…', + } + ), + automationCompleteCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.automationCompleteCellLabel', + { + defaultMessage: 'Resolved', + } + ), + automationFailedCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.automationFailedCellLabel', + { + defaultMessage: 'Resolution failed', + } + ), + automatedCellTooltipLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.automatedCellTooltipLabel', + { + defaultMessage: 'This is an automated resolution.', + } + ), +}; + +interface Props { + deprecationId: string; + isAutomated: boolean; + deprecationResolutionState?: DeprecationResolutionState; +} + +export const ResolutionTableCell: React.FunctionComponent = ({ + deprecationId, + isAutomated, + deprecationResolutionState, +}) => { + if (isAutomated) { + if (deprecationResolutionState?.id === deprecationId) { + const { resolveDeprecationStatus } = deprecationResolutionState; + + switch (resolveDeprecationStatus) { + case 'in_progress': + return ( + + + + + + {i18nTexts.automationInProgressCellLabel} + + + ); + case 'fail': + return ( + + + + + + {i18nTexts.automationFailedCellLabel} + + + ); + case 'ok': + default: + return ( + + + + + + {i18nTexts.automationCompleteCellLabel} + + + ); + } + } + + return ( + + + + + + + {i18nTexts.automatedCellLabel} + + + + ); + } + + return ( + + + {i18nTexts.manualCellLabel} + + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx deleted file mode 100644 index f94512fac5630..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 React, { FunctionComponent } from 'react'; -import { i18n } from '@kbn/i18n'; - -import { EuiConfirmModal } from '@elastic/eui'; -import type { DomainDeprecationDetails } from 'kibana/public'; - -interface Props { - closeModal: () => void; - deprecation: DomainDeprecationDetails; - isResolvingDeprecation: boolean; - resolveDeprecation: (deprecationDetails: DomainDeprecationDetails) => Promise; -} - -const i18nTexts = { - getModalTitle: (domainId: string) => - i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.modalTitle', - { - defaultMessage: "Resolve deprecation in '{domainId}'?", - values: { - domainId, - }, - } - ), - cancelButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.cancelButtonLabel', - { - defaultMessage: 'Cancel', - } - ), - resolveButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.resolveButtonLabel', - { - defaultMessage: 'Resolve', - } - ), -}; - -export const ResolveDeprecationModal: FunctionComponent = ({ - closeModal, - deprecation, - isResolvingDeprecation, - resolveDeprecation, -}) => { - return ( - resolveDeprecation(deprecation)} - cancelButtonText={i18nTexts.cancelButtonLabel} - confirmButtonText={i18nTexts.resolveButtonLabel} - defaultFocusedButton="confirm" - isLoading={isResolvingDeprecation} - /> - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx deleted file mode 100644 index 98027d4f46aac..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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 React, { FunctionComponent } from 'react'; -import { i18n } from '@kbn/i18n'; - -import { - EuiText, - EuiSteps, - EuiButton, - EuiModal, - EuiModalBody, - EuiModalFooter, - EuiModalHeader, - EuiModalHeaderTitle, - EuiTitle, - EuiButtonEmpty, - EuiFlexGroup, - EuiFlexItem, -} from '@elastic/eui'; - -export interface StepsModalContent { - domainId: string; - steps: string[]; - documentationUrl?: string; -} - -interface Props { - closeModal: () => void; - modalContent: StepsModalContent; -} - -const i18nTexts = { - getModalTitle: (domainId: string) => - i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.stepsModal.modalTitle', { - defaultMessage: "Resolve deprecation in '{domainId}'", - values: { - domainId, - }, - }), - getStepTitle: (step: number) => - i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.stepsModal.stepTitle', { - defaultMessage: 'Step {step}', - values: { - step, - }, - }), - docLinkLabel: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.stepsModal.docLinkLabel', - { - defaultMessage: 'View documentation', - } - ), - closeButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.stepsModal.closeButtonLabel', - { - defaultMessage: 'Close', - } - ), -}; - -export const StepsModal: FunctionComponent = ({ closeModal, modalContent }) => { - const { domainId, steps, documentationUrl } = modalContent; - - return ( - - - - -

{i18nTexts.getModalTitle(domainId)}

-
-
-
- - - { - return { - title: i18nTexts.getStepTitle(index + 1), - children: ( - -

{step}

-
- ), - }; - })} - /> -
- - - - {documentationUrl && ( - - - {i18nTexts.docLinkLabel} - - - )} - - - - {i18nTexts.closeButtonLabel} - - - - -
- ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx index 2f034d461a24f..bed92d3b92ccf 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx @@ -11,12 +11,9 @@ import { EuiFlexGroup, EuiFlexItem, EuiText, EuiIcon, EuiSpacer } from '@elastic import { i18n } from '@kbn/i18n'; const i18nTexts = { - noDeprecationsText: i18n.translate( - 'xpack.upgradeAssistant.esDeprecationStats.noDeprecationsText', - { - defaultMessage: 'No warnings. Good to go!', - } - ), + noDeprecationsText: i18n.translate('xpack.upgradeAssistant.noDeprecationsText', { + defaultMessage: 'No warnings. Good to go!', + }), }; export const NoDeprecations: FunctionComponent = () => { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_count.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_count.tsx new file mode 100644 index 0000000000000..3312508a87073 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_count.tsx @@ -0,0 +1,53 @@ +/* + * 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 React, { FunctionComponent } from 'react'; + +import { EuiFlexGroup, EuiFlexItem, EuiHealth } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +const i18nTexts = { + getCriticalStatusLabel: (count: number) => + i18n.translate('xpack.upgradeAssistant.deprecationCount.criticalStatusLabel', { + defaultMessage: 'Critical: {count}', + values: { + count, + }, + }), + getWarningStatusLabel: (count: number) => + i18n.translate('xpack.upgradeAssistant.deprecationCount.warningStatusLabel', { + defaultMessage: 'Warning: {count}', + values: { + count, + }, + }), +}; + +interface Props { + totalCriticalDeprecations: number; + totalWarningDeprecations: number; +} + +export const DeprecationCount: FunctionComponent = ({ + totalCriticalDeprecations, + totalWarningDeprecations, +}) => { + return ( + + + + {i18nTexts.getCriticalStatusLabel(totalCriticalDeprecations)} + + + + + {i18nTexts.getWarningStatusLabel(totalWarningDeprecations)} + + + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/count_summary.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/count_summary.tsx deleted file mode 100644 index 709ef7224870e..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/count_summary.tsx +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 React, { FunctionComponent } from 'react'; - -import { EuiText } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; - -export const DeprecationCountSummary: FunctionComponent<{ - allDeprecationsCount: number; - filteredDeprecationsCount: number; -}> = ({ filteredDeprecationsCount, allDeprecationsCount }) => ( - - {allDeprecationsCount > 0 ? ( - - ) : ( - - )} - {filteredDeprecationsCount !== allDeprecationsCount && ( - <> - {'. '} - - - )} - -); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/deprecation_list_bar.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/deprecation_list_bar.tsx deleted file mode 100644 index 6cb5ae3675c44..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/deprecation_list_bar.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 React, { FunctionComponent } from 'react'; -import { i18n } from '@kbn/i18n'; - -import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { DeprecationCountSummary } from './count_summary'; - -const i18nTexts = { - expandAllButton: i18n.translate( - 'xpack.upgradeAssistant.deprecationListBar.expandAllButtonLabel', - { - defaultMessage: 'Expand all', - } - ), - collapseAllButton: i18n.translate( - 'xpack.upgradeAssistant.deprecationListBar.collapseAllButtonLabel', - { - defaultMessage: 'Collapse all', - } - ), -}; - -export const DeprecationListBar: FunctionComponent<{ - allDeprecationsCount: number; - filteredDeprecationsCount: number; - setExpandAll: (shouldExpandAll: boolean) => void; -}> = ({ allDeprecationsCount, filteredDeprecationsCount, setExpandAll }) => { - return ( - - - - - - - - - setExpandAll(true)} - data-test-subj="expandAll" - > - {i18nTexts.expandAllButton} - - - - setExpandAll(false)} - data-test-subj="collapseAll" - > - {i18nTexts.collapseAllButton} - - - - - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_pagination.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_pagination.tsx deleted file mode 100644 index ae2c0ba1c4877..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_pagination.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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 React, { FunctionComponent } from 'react'; - -import { EuiFlexGroup, EuiFlexItem, EuiPagination } from '@elastic/eui'; - -export const DeprecationPagination: FunctionComponent<{ - pageCount: number; - activePage: number; - setPage: (page: number) => void; -}> = ({ pageCount, activePage, setPage }) => { - return ( - - - - - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/health.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/health.tsx deleted file mode 100644 index 9bf35668ac88a..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/health.tsx +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 { countBy } from 'lodash'; -import React, { FunctionComponent } from 'react'; - -import { EuiBadge, EuiToolTip } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { DeprecationInfo } from '../../../../common/types'; -import { COLOR_MAP, REVERSE_LEVEL_MAP } from '../constants'; - -const LocalizedLevels: { [level: string]: string } = { - warning: i18n.translate('xpack.upgradeAssistant.checkupTab.deprecations.warningLabel', { - defaultMessage: 'Warning', - }), - critical: i18n.translate('xpack.upgradeAssistant.checkupTab.deprecations.criticalLabel', { - defaultMessage: 'Critical', - }), -}; - -export const LocalizedActions: { [level: string]: string } = { - warning: i18n.translate('xpack.upgradeAssistant.checkupTab.deprecations.warningActionTooltip', { - defaultMessage: 'Resolving this issue before upgrading is advised, but not required.', - }), - critical: i18n.translate('xpack.upgradeAssistant.checkupTab.deprecations.criticalActionTooltip', { - defaultMessage: 'Resolve this issue before upgrading.', - }), -}; - -interface DeprecationHealthProps { - deprecationLevels: number[]; - single?: boolean; -} - -const SingleHealth: FunctionComponent<{ level: DeprecationInfo['level']; label: string }> = ({ - level, - label, -}) => ( - - - {label} - -   - -); - -/** - * Displays a summary health for a list of deprecations that shows the number and level of severity - * deprecations in the list. - */ -export const DeprecationHealth: FunctionComponent = ({ - deprecationLevels, - single = false, -}) => { - if (deprecationLevels.length === 0) { - return ; - } - - if (single) { - const highest = Math.max(...deprecationLevels); - const highestLevel = REVERSE_LEVEL_MAP[highest]; - - return ; - } - - const countByLevel = countBy(deprecationLevels); - - return ( - - {Object.keys(countByLevel) - .map((k) => parseInt(k, 10)) - .sort() - .map((level) => [level, REVERSE_LEVEL_MAP[level]]) - .map(([numLevel, stringLevel]) => ( - - ))} - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts index c79d8247a93f1..89bce0813b92f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts @@ -6,7 +6,4 @@ */ export { NoDeprecationsPrompt } from './no_deprecations'; -export { DeprecationHealth } from './health'; -export { SearchBar } from './search_bar'; -export { DeprecationPagination } from './deprecation_pagination'; -export { DeprecationListBar } from './deprecation_list_bar'; +export { DeprecationCount } from './deprecation_count'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/group_by_filter.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/group_by_filter.test.tsx.snap deleted file mode 100644 index 5a8619e1e687b..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/group_by_filter.test.tsx.snap +++ /dev/null @@ -1,24 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`GroupByFilter renders 1`] = ` - - - - By issue - - - By index - - - -`; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap deleted file mode 100644 index 551e212f23dd7..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap +++ /dev/null @@ -1,19 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DeprecationLevelFilter renders 1`] = ` - - - - Critical - - - -`; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.test.tsx deleted file mode 100644 index fa863e4935c09..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.test.tsx +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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 { mount, shallow } from 'enzyme'; -import React from 'react'; - -import { GroupByOption } from '../../types'; -import { GroupByFilter } from './group_by_filter'; - -const defaultProps = { - availableGroupByOptions: [GroupByOption.message, GroupByOption.index], - currentGroupBy: GroupByOption.message, - onGroupByChange: jest.fn(), -}; - -describe('GroupByFilter', () => { - test('renders', () => { - expect(shallow()).toMatchSnapshot(); - }); - - test('clicking button calls onGroupByChange', () => { - const wrapper = mount(); - wrapper.find('button.euiFilterButton-hasActiveFilters').simulate('click'); - expect(defaultProps.onGroupByChange).toHaveBeenCalledTimes(1); - expect(defaultProps.onGroupByChange.mock.calls[0][0]).toEqual(GroupByOption.message); - }); -}); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.tsx deleted file mode 100644 index c37ae47793b95..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.tsx +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 React from 'react'; - -import { EuiFilterButton, EuiFilterGroup, EuiFlexItem } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { GroupByOption } from '../../types'; - -const LocalizedOptions: { [option: string]: string } = { - message: i18n.translate('xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIssueLabel', { - defaultMessage: 'By issue', - }), - index: i18n.translate('xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIndexLabel', { - defaultMessage: 'By index', - }), -}; - -interface GroupByFilterProps { - availableGroupByOptions: GroupByOption[]; - currentGroupBy: GroupByOption; - onGroupByChange: (groupBy: GroupByOption) => void; -} - -export const GroupByFilter: React.FunctionComponent = ({ - availableGroupByOptions, - currentGroupBy, - onGroupByChange, -}) => { - if (availableGroupByOptions.length <= 1) { - return null; - } - - return ( - - - {availableGroupByOptions.map((option) => ( - - {LocalizedOptions[option]} - - ))} - - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/index.ts deleted file mode 100644 index 31ad78cf572fe..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* - * 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. - */ - -export { SearchBar } from './search_bar'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.test.tsx deleted file mode 100644 index c778e56e8df11..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.test.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 { mount, shallow } from 'enzyme'; -import React from 'react'; -import { LevelFilterOption } from '../../types'; - -import { DeprecationLevelFilter } from './level_filter'; - -const defaultProps = { - levelsCount: { - warning: 4, - critical: 1, - }, - currentFilter: 'all' as LevelFilterOption, - onFilterChange: jest.fn(), -}; - -describe('DeprecationLevelFilter', () => { - test('renders', () => { - expect(shallow()).toMatchSnapshot(); - }); - - test('clicking button calls onFilterChange', () => { - const wrapper = mount(); - wrapper.find('button[data-test-subj="criticalLevelFilter"]').simulate('click'); - expect(defaultProps.onFilterChange).toHaveBeenCalledTimes(1); - expect(defaultProps.onFilterChange.mock.calls[0][0]).toEqual('critical'); - }); -}); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx deleted file mode 100644 index 59bfaa595b0a6..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 React from 'react'; - -import { EuiFilterButton, EuiFilterGroup, EuiFlexItem } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { LevelFilterOption } from '../../types'; - -const LocalizedOptions: { [option: string]: string } = { - critical: i18n.translate( - 'xpack.upgradeAssistant.checkupTab.controls.filterBar.criticalButtonLabel', - { defaultMessage: 'Critical' } - ), -}; -interface DeprecationLevelProps { - levelsCount: { - [key: string]: number; - }; - currentFilter: LevelFilterOption; - onFilterChange(level: LevelFilterOption): void; -} - -export const DeprecationLevelFilter: React.FunctionComponent = ({ - levelsCount, - currentFilter, - onFilterChange, -}) => { - return ( - - - { - onFilterChange(currentFilter !== 'critical' ? 'critical' : 'all'); - }} - hasActiveFilters={currentFilter === 'critical'} - numFilters={levelsCount.critical || undefined} - data-test-subj="criticalLevelFilter" - > - {LocalizedOptions.critical} - - - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx deleted file mode 100644 index 7c805398a6b47..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx +++ /dev/null @@ -1,141 +0,0 @@ -/* - * 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 React, { FunctionComponent, useState } from 'react'; -import { i18n } from '@kbn/i18n'; -import { - EuiButton, - EuiFieldSearch, - EuiFlexGroup, - EuiFlexItem, - EuiCallOut, - EuiSpacer, -} from '@elastic/eui'; - -import type { DomainDeprecationDetails } from 'kibana/public'; -import { DeprecationInfo } from '../../../../../common/types'; -import { validateRegExpString } from '../../../lib/utils'; -import { GroupByOption, LevelFilterOption } from '../../types'; -import { DeprecationLevelFilter } from './level_filter'; -import { GroupByFilter } from './group_by_filter'; - -interface SearchBarProps { - allDeprecations?: DeprecationInfo[] | DomainDeprecationDetails; - isLoading: boolean; - loadData: () => void; - currentFilter: LevelFilterOption; - onFilterChange: (filter: LevelFilterOption) => void; - onSearchChange: (filter: string) => void; - totalDeprecationsCount: number; - levelToDeprecationCountMap: { - [key: string]: number; - }; - groupByFilterProps?: { - availableGroupByOptions: GroupByOption[]; - currentGroupBy: GroupByOption; - onGroupByChange: (groupBy: GroupByOption) => void; - }; -} - -const i18nTexts = { - searchAriaLabel: i18n.translate( - 'xpack.upgradeAssistant.deprecationListSearchBar.placeholderAriaLabel', - { defaultMessage: 'Filter' } - ), - searchPlaceholderLabel: i18n.translate( - 'xpack.upgradeAssistant.deprecationListSearchBar.placeholderLabel', - { - defaultMessage: 'Filter', - } - ), - reloadButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.deprecationListSearchBar.reloadButtonLabel', - { - defaultMessage: 'Reload', - } - ), - getInvalidSearchMessage: (searchTermError: string) => - i18n.translate('xpack.upgradeAssistant.deprecationListSearchBar.filterErrorMessageLabel', { - defaultMessage: 'Filter invalid: {searchTermError}', - values: { searchTermError }, - }), -}; - -export const SearchBar: FunctionComponent = ({ - totalDeprecationsCount, - levelToDeprecationCountMap, - isLoading, - loadData, - currentFilter, - onFilterChange, - onSearchChange, - groupByFilterProps, -}) => { - const [searchTermError, setSearchTermError] = useState(null); - const filterInvalid = Boolean(searchTermError); - return ( - <> - - - - - { - const string = e.target.value; - const errorMessage = validateRegExpString(string); - if (errorMessage) { - // Emit an empty search term to listeners if search term is invalid. - onSearchChange(''); - setSearchTermError(errorMessage); - } else { - onSearchChange(e.target.value); - if (searchTermError) { - setSearchTermError(null); - } - } - }} - /> - - - {/* These two components provide their own EuiFlexItem wrappers */} - - {groupByFilterProps && } - - - - - {i18nTexts.reloadButtonLabel} - - - - - {filterInvalid && ( - <> - - - - - )} - - - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/types.ts b/x-pack/plugins/upgrade_assistant/public/application/components/types.ts index b46bb583244f0..81495c45420bf 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/types.ts @@ -13,14 +13,6 @@ export enum LoadingState { Error, } -export type LevelFilterOption = 'all' | 'critical'; - -export enum GroupByOption { - message = 'message', - index = 'index', - node = 'node', -} - export type DeprecationTableColumns = | 'type' | 'index' diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts index f36dc2096ddc7..1beb759442f9f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts @@ -21,7 +21,7 @@ const i18nTexts = { kibanaDeprecations: i18n.translate( 'xpack.upgradeAssistant.breadcrumb.kibanaDeprecationsLabel', { - defaultMessage: 'Kibana deprecations', + defaultMessage: 'Kibana deprecation warnings', } ), }, diff --git a/x-pack/test/accessibility/apps/upgrade_assistant.ts b/x-pack/test/accessibility/apps/upgrade_assistant.ts index 47bade2e706d1..01fc11954ef76 100644 --- a/x-pack/test/accessibility/apps/upgrade_assistant.ts +++ b/x-pack/test/accessibility/apps/upgrade_assistant.ts @@ -75,22 +75,38 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await a11y.testAppSnapshot(); }); - it('Kibana deprecations page', async () => { - await PageObjects.common.navigateToUrl( - 'management', - 'stack/upgrade_assistant/kibana_deprecations', - { - ensureCurrentUrl: false, - shouldLoginIfPrompted: false, - shouldUseHashForSubUrl: false, - } - ); + describe('Kibana deprecations page', () => { + beforeEach(async () => { + await PageObjects.common.navigateToUrl( + 'management', + 'stack/upgrade_assistant/kibana_deprecations', + { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, + } + ); - await retry.waitFor('Kibana deprecations to be visible', async () => { - return testSubjects.exists('kibanaDeprecationsContent'); + await retry.waitFor('Kibana deprecations to be visible', async () => { + return testSubjects.exists('kibanaDeprecations'); + }); }); - await a11y.testAppSnapshot(); + it('Deprecations table', async () => { + await a11y.testAppSnapshot(); + }); + + it('Deprecation details flyout', async () => { + await PageObjects.upgradeAssistant.clickKibanaDeprecation( + 'xpack.securitySolution has a deprecated setting' // This deprecation was added to the test runner config so should be guaranteed + ); + + await retry.waitFor('Kibana deprecation details flyout to be visible', async () => { + return testSubjects.exists('kibanaDeprecationDetails'); + }); + + await a11y.testAppSnapshot(); + }); }); }); } diff --git a/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts b/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts index 3bd6af70e7847..6ab46cb3be93d 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts @@ -105,7 +105,7 @@ export default function upgradeAssistantFunctionalTests({ await PageObjects.upgradeAssistant.clickKibanaDeprecationsPanel(); await retry.waitFor('Kibana deprecations table to be visible', async () => { - return testSubjects.exists('kibanaDeprecationsContent'); + return testSubjects.exists('kibanaDeprecations'); }); }); }); diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index 0b202d3eb1b54..8825c5796496f 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -86,6 +86,9 @@ export default async function ({ readConfigFile }) { '--xpack.encryptedSavedObjects.encryptionKey="DkdXazszSCYexXqz4YktBGHCRkV6hyNK"', '--xpack.discoverEnhanced.actions.exploreDataInContextMenu.enabled=true', '--savedObjects.maxImportPayloadBytes=10485760', // for OSS test management/_import_objects + '--xpack.observability.unsafe.cases.enabled=true', + '--xpack.siem.enabled=true', // Used to trigger Kibana deprecation warning in UA (renamed config) + '--xpack.observability.unsafe.alertingExperience.enabled=true', // NOTE: Can be removed once enabled by default ], }, uiSettings: { diff --git a/x-pack/test/functional/page_objects/upgrade_assistant_page.ts b/x-pack/test/functional/page_objects/upgrade_assistant_page.ts index 32332620ffc59..406800d775417 100644 --- a/x-pack/test/functional/page_objects/upgrade_assistant_page.ts +++ b/x-pack/test/functional/page_objects/upgrade_assistant_page.ts @@ -40,4 +40,21 @@ export class UpgradeAssistantPageObject extends FtrService { await this.testSubjects.click('kibanaStatsPanel'); }); } + + async clickKibanaDeprecation(selectedIssue: string) { + const table = await this.testSubjects.find('kibanaDeprecationsTable'); + const rows = await table.findAllByTestSubject('row'); + + const selectedRow = rows.find(async (row) => { + const issue = await (await row.findByTestSubject('issueCell')).getVisibleText(); + return issue === selectedIssue; + }); + + if (selectedRow) { + const issueLink = await selectedRow.findByTestSubject('deprecationDetailsLink'); + await issueLink.click(); + } else { + this.log.debug('Unable to find selected deprecation row'); + } + } }