From fd86e7f9df5e39ebc6d137eb9989df97d78e1806 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 20 Feb 2025 11:54:42 +0100 Subject: [PATCH 1/3] Add cta for migrating system indices in the flyout --- .../migrate_system_indices/flyout.tsx | 67 ++++++++++--- .../migrate_system_indices/migrate_button.tsx | 99 +++++++++++++++++++ .../migrate_system_indices.tsx | 77 ++------------- .../use_migrate_system_indices.ts | 42 +++++--- 4 files changed, 187 insertions(+), 98 deletions(-) create mode 100644 x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_button.tsx diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx index 918f99955e54c..2525695e80ca7 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx @@ -26,6 +26,7 @@ import { EuiDescriptionList, EuiScreenReaderOnly, EuiBasicTableColumn, + EuiCallOut, } from '@elastic/eui'; import { @@ -33,10 +34,15 @@ import { SystemIndicesMigrationFeature, MIGRATION_STATUS, } from '../../../../../common/types'; +import { MigrateSystemIndicesButton } from './migrate_button'; export interface SystemIndicesFlyoutProps { closeFlyout: () => void; data: SystemIndicesMigrationStatus; + beginSystemIndicesMigration: () => void; + isInitialRequest: boolean; + isLoading: boolean; + migrationStatus?: MIGRATION_STATUS; } const i18nTexts = { @@ -98,6 +104,12 @@ const i18nTexts = { defaultMessage: 'Unknown error', } ), + migrationNotNeeded: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.migrationNotNeeded', + { + defaultMessage: 'Systems indices migration not needed', + } + ), }; const getFailedIndices = (feature: SystemIndicesMigrationFeature) => { @@ -166,7 +178,14 @@ const renderMigrationStatus = (status: MIGRATION_STATUS) => { return null; }; -export const SystemIndicesFlyout = ({ closeFlyout, data }: SystemIndicesFlyoutProps) => { +export const SystemIndicesFlyout = ({ + closeFlyout, + data, + beginSystemIndicesMigration, + isInitialRequest, + isLoading, + migrationStatus, +}: SystemIndicesFlyoutProps) => { const [expandedRows, setExpandedRows] = useState>({}); const toggleRow = (feature: SystemIndicesMigrationFeature) => { @@ -235,19 +254,27 @@ export const SystemIndicesFlyout = ({ closeFlyout, data }: SystemIndicesFlyoutPr - -

{i18nTexts.flyoutDescription}

-
- - - data-test-subj="featuresTable" - itemId="feature_name" - items={data.features} - columns={columns} - itemIdToExpandedRowMap={expandedRows} - pagination={true} - sorting={true} - /> + {migrationStatus === 'NO_MIGRATION_NEEDED' && ( + + )} + + {migrationStatus !== 'NO_MIGRATION_NEEDED' && ( + <> + +

{i18nTexts.flyoutDescription}

+
+ + + data-test-subj="featuresTable" + itemId="feature_name" + items={data.features} + columns={columns} + itemIdToExpandedRowMap={expandedRows} + pagination={true} + sorting={true} + /> + + )}
@@ -256,6 +283,18 @@ export const SystemIndicesFlyout = ({ closeFlyout, data }: SystemIndicesFlyoutPr {i18nTexts.closeButtonLabel} + + {migrationStatus !== 'NO_MIGRATION_NEEDED' && ( + + + + )} diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_button.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_button.tsx new file mode 100644 index 0000000000000..edf06c92e6991 --- /dev/null +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_button.tsx @@ -0,0 +1,99 @@ +/* + * 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, { useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiButton, EuiConfirmModal, EuiButtonProps } from '@elastic/eui'; + +const i18nTexts = { + inProgressButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.inProgressButtonLabel', + { + defaultMessage: 'Migration in progress', + } + ), + startButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.startButtonLabel', + { + defaultMessage: 'Migrate indices', + } + ), + modalTitle: i18n.translate('xpack.upgradeAssistant.overview.systemIndices.confirmModal.title', { + defaultMessage: 'Migrate Indices', + }), + modalButtonCancel: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.confirmModal.cancelButton.label', + { + defaultMessage: 'Cancel', + } + ), + modalButtonConfirm: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.confirmModal.confirmButton.label', + { + defaultMessage: 'Confirm', + } + ), + modalButtonDescription: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.confirmModal.description', + { + defaultMessage: 'Migrating system indices may lead to downtime while they are reindexed.', + } + ), +}; + +interface MigrateButtonProps { + buttonProps?: EuiButtonProps; + beginSystemIndicesMigration: () => void; + isInitialRequest: boolean; + isLoading: boolean; + isMigrating: boolean; +} + +export const MigrateSystemIndicesButton = ({ + buttonProps, + beginSystemIndicesMigration, + isInitialRequest, + isLoading, + isMigrating, +}: MigrateButtonProps) => { + const [isModalVisible, setIsModalVisible] = useState(false); + + const isButtonDisabled = isInitialRequest && isLoading; + + const handleConfirmMigration = () => { + beginSystemIndicesMigration(); + setIsModalVisible(false); + }; + + return ( + <> + setIsModalVisible(true)} + data-test-subj="startSystemIndicesMigrationButton" + > + {isMigrating ? i18nTexts.inProgressButtonLabel : i18nTexts.startButtonLabel} + + + {isModalVisible && ( + setIsModalVisible(false)} + onConfirm={handleConfirmMigration} + cancelButtonText={i18nTexts.modalButtonCancel} + confirmButtonText={i18nTexts.modalButtonConfirm} + defaultFocusedButton="confirm" + data-test-subj="migrationConfirmModal" + > + {i18nTexts.modalButtonDescription} + + )} + + ); +}; diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx index 6a236a7230bdd..9d54e3585c176 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { FunctionComponent, useEffect, useState } from 'react'; +import React, { FunctionComponent, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; @@ -20,7 +20,6 @@ import { EuiFlexItem, EuiCode, EuiLink, - EuiConfirmModal, } from '@elastic/eui'; import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; @@ -28,6 +27,7 @@ import { DocLinksStart } from '@kbn/core/public'; import type { SystemIndicesMigrationFeature } from '../../../../../common/types'; import type { OverviewStepProps } from '../../types'; import { useMigrateSystemIndices } from './use_migrate_system_indices'; +import { MigrateSystemIndicesButton } from './migrate_button'; interface Props { setIsComplete: OverviewStepProps['setIsComplete']; @@ -100,18 +100,6 @@ const i18nTexts = { /> ); }, - startButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.overview.systemIndices.startButtonLabel', - { - defaultMessage: 'Migrate indices', - } - ), - inProgressButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.overview.systemIndices.inProgressButtonLabel', - { - defaultMessage: 'Migration in progress', - } - ), noMigrationNeeded: i18n.translate( 'xpack.upgradeAssistant.overview.systemIndices.noMigrationNeeded', { @@ -159,55 +147,10 @@ const i18nTexts = { }, }; -const ConfirmModal: React.FC<{ - onCancel: () => void; - onConfirm: () => void; -}> = ({ onCancel, onConfirm }) => ( - - {i18n.translate('xpack.upgradeAssistant.overview.systemIndices.confirmModal.description', { - defaultMessage: 'Migrating system indices may lead to downtime while they are reindexed.', - })} - -); - const MigrateSystemIndicesStep: FunctionComponent = ({ setIsComplete }) => { const { beginSystemIndicesMigration, startMigrationStatus, migrationStatus, setShowFlyout } = useMigrateSystemIndices(); - const [isModalVisible, setIsModalVisible] = useState(false); - - const openMigrationModal = () => { - setIsModalVisible(true); - }; - const onCancel = () => { - setIsModalVisible(false); - }; - - const confirmMigrationAction = () => { - beginSystemIndicesMigration(); - setIsModalVisible(false); - }; - useEffect(() => { setIsComplete(migrationStatus.data?.migration_status === 'NO_MIGRATION_NEEDED'); // Depending upon setIsComplete would create an infinite loop. @@ -287,18 +230,14 @@ const MigrateSystemIndicesStep: FunctionComponent = ({ setIsComplete }) = )} - {isModalVisible && } - - - {isMigrating ? i18nTexts.inProgressButtonLabel : i18nTexts.startButtonLabel} - + { removeContentFromGlobalFlyout(FLYOUT_ID); }, [removeContentFromGlobalFlyout]); + const beginSystemIndicesMigration = useCallback(async () => { + const { error: startMigrationError } = await api.migrateSystemIndices(); + + setStartMigrationStatus({ + statusType: startMigrationError ? 'error' : 'started', + error: startMigrationError ?? undefined, + }); + + if (!startMigrationError) { + resendRequest(); + } + }, [api, resendRequest]); + useEffect(() => { if (showFlyout) { addContentToGlobalFlyout({ @@ -57,26 +70,25 @@ export const useMigrateSystemIndices = () => { props: { data: data!, closeFlyout, + beginSystemIndicesMigration, + isInitialRequest, + isLoading, + migrationStatus: data?.migration_status, }, flyoutProps: { onClose: closeFlyout, }, }); } - }, [addContentToGlobalFlyout, data, showFlyout, closeFlyout]); - - const beginSystemIndicesMigration = useCallback(async () => { - const { error: startMigrationError } = await api.migrateSystemIndices(); - - setStartMigrationStatus({ - statusType: startMigrationError ? 'error' : 'started', - error: startMigrationError ?? undefined, - }); - - if (!startMigrationError) { - resendRequest(); - } - }, [api, resendRequest]); + }, [ + addContentToGlobalFlyout, + data, + showFlyout, + closeFlyout, + beginSystemIndicesMigration, + isLoading, + isInitialRequest, + ]); return { setShowFlyout, From 756a20cde45bb7962481c7f952ad11a4815eea73 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 20 Feb 2025 11:54:53 +0100 Subject: [PATCH 2/3] commit with @elastic email From 9f9255f9d95d7f8b5fce882321d66129c261a290 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 20 Feb 2025 12:57:36 +0100 Subject: [PATCH 3/3] Add tests --- .../migrate_system_indices/flyout.test.ts | 54 +++++++++++++++++++ .../migrate_system_indices/flyout.tsx | 7 ++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/flyout.test.ts b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/flyout.test.ts index 4139d5010ff57..7de6e7439145d 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/flyout.test.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/flyout.test.ts @@ -40,6 +40,60 @@ describe('Overview - Migrate system indices - Flyout', () => { expect(tableCellsValues).toMatchSnapshot(); }); + test('can trigger the migration', async () => { + const { exists, find, component } = testBed; + + // Expect the migration button to be present + expect(exists('startSystemIndicesMigrationButton')).toBe(true); + + await act(async () => { + find('startSystemIndicesMigrationButton').simulate('click'); + }); + component.update(); + + expect(exists('migrationConfirmModal')).toBe(true); + + const modal = document.body.querySelector('[data-test-subj="migrationConfirmModal"]'); + const confirmButton: HTMLButtonElement | null = modal!.querySelector( + '[data-test-subj="confirmModalConfirmButton"]' + ); + + await act(async () => { + confirmButton!.click(); + }); + component.update(); + + expect(exists('migrationConfirmModal')).toBe(false); + }); + + test('disables migrate button when migrating', async () => { + httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ + migration_status: 'IN_PROGRESS', + }); + + testBed = await setupOverviewPage(httpSetup); + + const { find, component } = testBed; + + component.update(); + + expect(find('startSystemIndicesMigrationButton').props().disabled).toBe(true); + }); + + test('hides the start migration button when finished', async () => { + httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ + migration_status: 'NO_MIGRATION_NEEDED', + }); + + testBed = await setupOverviewPage(httpSetup); + + const { exists, component } = testBed; + + component.update(); + + expect(exists('startSystemIndicesMigrationButton')).toBe(false); + }); + test('shows migration errors inline within the table row', async () => { httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus(systemIndicesMigrationErrorStatus); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx index 2525695e80ca7..0bce47acfa2d2 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx @@ -255,7 +255,12 @@ export const SystemIndicesFlyout = ({ {migrationStatus === 'NO_MIGRATION_NEEDED' && ( - + )} {migrationStatus !== 'NO_MIGRATION_NEEDED' && (