From d67681d519ca4f89c651c315315c8edc212768df Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 10 Dec 2024 13:41:18 -0700 Subject: [PATCH] [dashboard] remove legacy embeddable client migrations (#203669) Part of https://github.com/elastic/kibana/issues/203250 --- .../public/dashboard_api/get_dashboard_api.ts | 1 - .../dashboard/public/dashboard_api/types.ts | 1 - .../dashboard_api/unsaved_changes_manager.ts | 9 ---- .../dashboard_app/_dashboard_app_strings.ts | 9 ---- .../top_nav/use_dashboard_menu_items.tsx | 6 +-- .../internal_dashboard_top_nav.tsx | 17 +----- src/plugins/dashboard/public/mocks.tsx | 1 - .../lib/load_dashboard_state.ts | 47 ++++++++-------- .../lib/migrate_dashboard_input.test.ts | 54 ------------------- .../lib/migrate_dashboard_input.ts | 54 ------------------- .../types.ts | 1 - .../translations/translations/fr-FR.json | 2 - .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 14 files changed, 25 insertions(+), 181 deletions(-) delete mode 100644 src/plugins/dashboard/public/services/dashboard_content_management_service/lib/migrate_dashboard_input.test.ts delete mode 100644 src/plugins/dashboard/public/services/dashboard_content_management_service/lib/migrate_dashboard_input.ts diff --git a/src/plugins/dashboard/public/dashboard_api/get_dashboard_api.ts b/src/plugins/dashboard/public/dashboard_api/get_dashboard_api.ts index 02c29968e526d..2e2e6352f829a 100644 --- a/src/plugins/dashboard/public/dashboard_api/get_dashboard_api.ts +++ b/src/plugins/dashboard/public/dashboard_api/get_dashboard_api.ts @@ -100,7 +100,6 @@ export function getDashboardApi({ timeRestore$: unifiedSearchManager.internalApi.timeRestore$, }); const unsavedChangesManager = initializeUnsavedChangesManager({ - anyMigrationRun: savedObjectResult?.anyMigrationRun ?? false, creationOptions, controlGroupApi$, lastSavedState: omit(savedObjectResult?.dashboardInput, 'controlGroupInput') ?? { diff --git a/src/plugins/dashboard/public/dashboard_api/types.ts b/src/plugins/dashboard/public/dashboard_api/types.ts index 2cfe5aa615f3b..7a1fc5fed7e13 100644 --- a/src/plugins/dashboard/public/dashboard_api/types.ts +++ b/src/plugins/dashboard/public/dashboard_api/types.ts @@ -155,7 +155,6 @@ export type DashboardApi = CanExpandPanels & getSettings: () => DashboardStateFromSettingsFlyout; getDashboardPanelFromId: (id: string) => Promise; hasOverlays$: PublishingSubject; - hasRunMigrations$: PublishingSubject; hasUnsavedChanges$: PublishingSubject; highlightPanel: (panelRef: HTMLDivElement) => void; highlightPanelId$: PublishingSubject; diff --git a/src/plugins/dashboard/public/dashboard_api/unsaved_changes_manager.ts b/src/plugins/dashboard/public/dashboard_api/unsaved_changes_manager.ts index b5d2117fde98e..46ae02de87fc2 100644 --- a/src/plugins/dashboard/public/dashboard_api/unsaved_changes_manager.ts +++ b/src/plugins/dashboard/public/dashboard_api/unsaved_changes_manager.ts @@ -23,7 +23,6 @@ import { import { initializeViewModeManager } from './view_mode_manager'; export function initializeUnsavedChangesManager({ - anyMigrationRun, creationOptions, controlGroupApi$, lastSavedState, @@ -33,7 +32,6 @@ export function initializeUnsavedChangesManager({ viewModeManager, unifiedSearchManager, }: { - anyMigrationRun: boolean; creationOptions?: DashboardCreationOptions; controlGroupApi$: PublishingSubject; lastSavedState: DashboardState; @@ -43,7 +41,6 @@ export function initializeUnsavedChangesManager({ viewModeManager: ReturnType; unifiedSearchManager: ReturnType; }) { - const hasRunMigrations$ = new BehaviorSubject(anyMigrationRun); const hasUnsavedChanges$ = new BehaviorSubject(false); const lastSavedState$ = new BehaviorSubject(lastSavedState); const saveNotification$ = new Subject(); @@ -113,7 +110,6 @@ export function initializeUnsavedChangesManager({ unifiedSearchManager.internalApi.reset(lastSavedState$.value); await controlGroupApi$.value?.asyncResetUnsavedChanges(); }, - hasRunMigrations$, hasUnsavedChanges$, saveNotification$, }, @@ -125,11 +121,6 @@ export function initializeUnsavedChangesManager({ getLastSavedState: () => lastSavedState$.value, onSave: (savedState: DashboardState) => { lastSavedState$.next(savedState); - - // if we set the last saved input, it means we have saved this Dashboard - therefore clientside migrations have - // been serialized into the SO. - hasRunMigrations$.next(false); - saveNotification$.next(); }, }, diff --git a/src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts b/src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts index 9c6526ce3403e..072da4d2fab30 100644 --- a/src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts +++ b/src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts @@ -67,15 +67,6 @@ export const unsavedChangesBadgeStrings = { defaultMessage: ' You have unsaved changes in this dashboard. To remove this label, save the dashboard.', }), - getHasRunMigrationsText: () => - i18n.translate('dashboard.hasRunMigrationsBadge', { - defaultMessage: 'Save recommended', - }), - getHasRunMigrationsToolTipContent: () => - i18n.translate('dashboard.hasRunMigrationsBadgeToolTipContent', { - defaultMessage: - 'One or more panels on this dashboard have been updated to a new version. Save the dashboard so it loads faster next time.', - }), }; export const getCreateVisualizationButtonTitle = () => diff --git a/src/plugins/dashboard/public/dashboard_app/top_nav/use_dashboard_menu_items.tsx b/src/plugins/dashboard/public/dashboard_app/top_nav/use_dashboard_menu_items.tsx index 0a96d3d978968..07e29db545e7f 100644 --- a/src/plugins/dashboard/public/dashboard_app/top_nav/use_dashboard_menu_items.tsx +++ b/src/plugins/dashboard/public/dashboard_app/top_nav/use_dashboard_menu_items.tsx @@ -43,11 +43,10 @@ export const useDashboardMenuItems = ({ const dashboardApi = useDashboardApi(); - const [dashboardTitle, hasOverlays, hasRunMigrations, hasUnsavedChanges, lastSavedId, viewMode] = + const [dashboardTitle, hasOverlays, hasUnsavedChanges, lastSavedId, viewMode] = useBatchedPublishingSubjects( dashboardApi.panelTitle, dashboardApi.hasOverlays$, - dashboardApi.hasRunMigrations$, dashboardApi.hasUnsavedChanges$, dashboardApi.savedObjectId, dashboardApi.viewMode @@ -161,7 +160,7 @@ export const useDashboardMenuItems = ({ emphasize: true, isLoading: isSaveInProgress, testId: 'dashboardQuickSaveMenuItem', - disableButton: disableTopNav || !(hasRunMigrations || hasUnsavedChanges), + disableButton: disableTopNav || !hasUnsavedChanges, run: () => quickSaveDashboard(), } as TopNavMenuData, @@ -211,7 +210,6 @@ export const useDashboardMenuItems = ({ }, [ disableTopNav, isSaveInProgress, - hasRunMigrations, hasUnsavedChanges, lastSavedId, dashboardInteractiveSave, diff --git a/src/plugins/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx b/src/plugins/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx index c040a412c3c9e..0511c13f9032d 100644 --- a/src/plugins/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx +++ b/src/plugins/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx @@ -87,7 +87,6 @@ export function InternalDashboardTopNav({ allDataViews, focusedPanelId, fullScreenMode, - hasRunMigrations, hasUnsavedChanges, lastSavedId, query, @@ -97,7 +96,6 @@ export function InternalDashboardTopNav({ dashboardApi.dataViews, dashboardApi.focusedPanelId$, dashboardApi.fullScreenMode$, - dashboardApi.hasRunMigrations$, dashboardApi.hasUnsavedChanges$, dashboardApi.savedObjectId, dashboardApi.query$, @@ -267,19 +265,6 @@ export function InternalDashboardTopNav({ } as EuiToolTipProps, }); } - if (hasRunMigrations && viewMode === 'edit') { - allBadges.push({ - 'data-test-subj': 'dashboardSaveRecommendedBadge', - badgeText: unsavedChangesBadgeStrings.getHasRunMigrationsText(), - title: '', - color: 'success', - iconType: 'save', - toolTipProps: { - content: unsavedChangesBadgeStrings.getHasRunMigrationsToolTipContent(), - position: 'bottom', - } as EuiToolTipProps, - }); - } const { showWriteControls } = getDashboardCapabilities(); if (showWriteControls && dashboardApi.isManaged) { @@ -328,7 +313,7 @@ export function InternalDashboardTopNav({ }); } return allBadges; - }, [hasUnsavedChanges, viewMode, hasRunMigrations, isPopoverOpen, dashboardApi, maybeRedirect]); + }, [hasUnsavedChanges, viewMode, isPopoverOpen, dashboardApi, maybeRedirect]); return (
diff --git a/src/plugins/dashboard/public/mocks.tsx b/src/plugins/dashboard/public/mocks.tsx index 2f47c52f9660f..1a275d805e5ed 100644 --- a/src/plugins/dashboard/public/mocks.tsx +++ b/src/plugins/dashboard/public/mocks.tsx @@ -100,7 +100,6 @@ export function buildMockDashboardApi({ viewMode: initialState.viewMode as ViewMode, id: savedObjectId ?? '123', } as SavedDashboardInput, - anyMigrationRun: false, references: [], }, }); diff --git a/src/plugins/dashboard/public/services/dashboard_content_management_service/lib/load_dashboard_state.ts b/src/plugins/dashboard/public/services/dashboard_content_management_service/lib/load_dashboard_state.ts index 2694411ed001a..e2db3c7c90950 100644 --- a/src/plugins/dashboard/public/services/dashboard_content_management_service/lib/load_dashboard_state.ts +++ b/src/plugins/dashboard/public/services/dashboard_content_management_service/lib/load_dashboard_state.ts @@ -32,7 +32,6 @@ import type { LoadDashboardReturn, } from '../types'; import { convertNumberToDashboardVersion } from './dashboard_versioning'; -import { migrateDashboardInput } from './migrate_dashboard_input'; export function migrateLegacyQuery(query: Query | { [key: string]: any } | string): Query { // Lucene was the only option before, so language-less queries are all lucene @@ -171,34 +170,32 @@ export const loadDashboardState = async ({ const panelMap = convertPanelsArrayToPanelMap(panels ?? []); - const { dashboardInput, anyMigrationRun } = migrateDashboardInput({ - ...DEFAULT_DASHBOARD_INPUT, - ...options, - - id: embeddableId, - refreshInterval, - timeRestore, - description, - timeRange, - filters, - panels: panelMap, - query, - title, - - viewMode: ViewMode.VIEW, // dashboards loaded from saved object default to view mode. If it was edited recently, the view mode from session storage will override this. - tags: savedObjectsTaggingService?.getTaggingApi()?.ui.getTagIdsFromReferences(references) ?? [], - - controlGroupInput: attributes.controlGroupInput, - - ...(version && { version: convertNumberToDashboardVersion(version) }), - }); - return { managed, references, resolveMeta, - dashboardInput, - anyMigrationRun, + dashboardInput: { + ...DEFAULT_DASHBOARD_INPUT, + ...options, + + id: embeddableId, + refreshInterval, + timeRestore, + description, + timeRange, + filters, + panels: panelMap, + query, + title, + + viewMode: ViewMode.VIEW, // dashboards loaded from saved object default to view mode. If it was edited recently, the view mode from session storage will override this. + tags: + savedObjectsTaggingService?.getTaggingApi()?.ui.getTagIdsFromReferences(references) ?? [], + + controlGroupInput: attributes.controlGroupInput, + + ...(version && { version: convertNumberToDashboardVersion(version) }), + }, dashboardFound: true, dashboardId: savedObjectId, }; diff --git a/src/plugins/dashboard/public/services/dashboard_content_management_service/lib/migrate_dashboard_input.test.ts b/src/plugins/dashboard/public/services/dashboard_content_management_service/lib/migrate_dashboard_input.test.ts deleted file mode 100644 index f0e715d624732..0000000000000 --- a/src/plugins/dashboard/public/services/dashboard_content_management_service/lib/migrate_dashboard_input.test.ts +++ /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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ViewMode } from '@kbn/embeddable-plugin/public'; -import { getSampleDashboardState, getSampleDashboardPanel } from '../../../mocks'; -import { embeddableService } from '../../kibana_services'; -import { SavedDashboardInput } from '../types'; -import { migrateDashboardInput } from './migrate_dashboard_input'; - -jest.mock('@kbn/embeddable-plugin/public', () => { - return { - ...jest.requireActual('@kbn/embeddable-plugin/public'), - runEmbeddableFactoryMigrations: jest - .fn() - .mockImplementation((input) => ({ input, migrationRun: true })), - }; -}); - -describe('Migrate dashboard input', () => { - it('should run factory migrations on all Dashboard content', () => { - const dashboardInput = { - ...getSampleDashboardState(), - id: '1', - viewMode: ViewMode.VIEW, - executionContext: { type: 'dashboard' }, - } as SavedDashboardInput; - dashboardInput.panels = { - panel1: getSampleDashboardPanel({ type: 'superLens', explicitInput: { id: 'panel1' } }), - panel2: getSampleDashboardPanel({ type: 'superLens', explicitInput: { id: 'panel2' } }), - panel3: getSampleDashboardPanel({ type: 'ultraDiscover', explicitInput: { id: 'panel3' } }), - panel4: getSampleDashboardPanel({ type: 'ultraDiscover', explicitInput: { id: 'panel4' } }), - }; - - embeddableService.getEmbeddableFactory = jest.fn(() => ({ - latestVersion: '1.0.0', - migrations: {}, - })) as unknown as typeof embeddableService.getEmbeddableFactory; - - const result = migrateDashboardInput(dashboardInput); - - // migration run should be true because the runEmbeddableFactoryMigrations mock above returns true. - expect(result.anyMigrationRun).toBe(true); - - expect(embeddableService.getEmbeddableFactory).toHaveBeenCalledTimes(4); // should be called 4 times for the panels, and 3 times for the controls - expect(embeddableService.getEmbeddableFactory).toHaveBeenCalledWith('superLens'); - expect(embeddableService.getEmbeddableFactory).toHaveBeenCalledWith('ultraDiscover'); - }); -}); diff --git a/src/plugins/dashboard/public/services/dashboard_content_management_service/lib/migrate_dashboard_input.ts b/src/plugins/dashboard/public/services/dashboard_content_management_service/lib/migrate_dashboard_input.ts deleted file mode 100644 index b0cfac9f97ce4..0000000000000 --- a/src/plugins/dashboard/public/services/dashboard_content_management_service/lib/migrate_dashboard_input.ts +++ /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", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - EmbeddableFactoryNotFoundError, - runEmbeddableFactoryMigrations, -} from '@kbn/embeddable-plugin/public'; -import { DashboardContainerInput, DashboardPanelState } from '../../../../common'; -import { embeddableService } from '../../kibana_services'; -import { SavedDashboardInput } from '../types'; - -/** - * Run Dashboard migrations clientside. We pre-emptively run all migrations for all content on this Dashboard so that - * we can ensure the `last saved state` which eventually resides in the Dashboard public state is fully migrated. - * This prevents the reset button from un-migrating the panels on the Dashboard. This also means that the migrations may - * get skipped at Embeddable create time - unless states with older versions are saved in the URL or session storage. - */ -export const migrateDashboardInput = (dashboardInput: SavedDashboardInput) => { - let anyMigrationRun = false; - if (!dashboardInput) return dashboardInput; - - const migratedPanels: DashboardContainerInput['panels'] = {}; - for (const [id, panel] of Object.entries(dashboardInput.panels)) { - // if the panel type is registered in the new embeddable system, we do not need to run migrations for it. - if (embeddableService.reactEmbeddableRegistryHasKey(panel.type)) { - migratedPanels[id] = panel; - continue; - } - - const factory = embeddableService.getEmbeddableFactory(panel.type); - if (!factory) throw new EmbeddableFactoryNotFoundError(panel.type); - // run last saved migrations for by value panels only. - if (!panel.explicitInput.savedObjectId) { - const { input: newInput, migrationRun: panelMigrationRun } = runEmbeddableFactoryMigrations( - panel.explicitInput, - factory - ); - if (panelMigrationRun) anyMigrationRun = true; - panel.explicitInput = newInput as DashboardPanelState['explicitInput']; - } else if (factory.latestVersion) { - // by reference panels are always considered to be of the latest version - panel.explicitInput.version = factory.latestVersion; - } - migratedPanels[id] = panel; - } - dashboardInput.panels = migratedPanels; - return { dashboardInput, anyMigrationRun }; -}; diff --git a/src/plugins/dashboard/public/services/dashboard_content_management_service/types.ts b/src/plugins/dashboard/public/services/dashboard_content_management_service/types.ts index e7dbcf1d230db..1922ed3e30dac 100644 --- a/src/plugins/dashboard/public/services/dashboard_content_management_service/types.ts +++ b/src/plugins/dashboard/public/services/dashboard_content_management_service/types.ts @@ -67,7 +67,6 @@ export interface LoadDashboardReturn { managed?: boolean; resolveMeta?: DashboardResolveMeta; dashboardInput: SavedDashboardInput; - anyMigrationRun?: boolean; /** * Raw references returned directly from the Dashboard saved object. These diff --git a/x-pack/platform/plugins/private/translations/translations/fr-FR.json b/x-pack/platform/plugins/private/translations/translations/fr-FR.json index 79b8cc8c74439..414a9a7ee12a9 100644 --- a/x-pack/platform/plugins/private/translations/translations/fr-FR.json +++ b/x-pack/platform/plugins/private/translations/translations/fr-FR.json @@ -1466,8 +1466,6 @@ "dashboard.featureCatalogue.dashboardDescription": "Affichez et partagez une collection de visualisations et de recherches enregistrées.", "dashboard.featureCatalogue.dashboardSubtitle": "Analysez des données à l’aide de tableaux de bord.", "dashboard.featureCatalogue.dashboardTitle": "Dashboard", - "dashboard.hasRunMigrationsBadge": "Enregistrement recommandé", - "dashboard.hasRunMigrationsBadgeToolTipContent": "Un ou plusieurs panneaux de ce tableau de bord ont été mis à jour vers une nouvelle version. Enregistrez le tableau de bord pour qu'il charge plus rapidement la prochaine fois.", "dashboard.labs.enableLabsDescription": "Cet indicateur détermine si l'utilisateur a accès au bouton Ateliers, moyen rapide d'activer et de désactiver les fonctionnalités de la version d'évaluation technique dans le tableau de bord.", "dashboard.labs.enableUI": "Activer le bouton Ateliers dans le tableau de bord", "dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription": "Analysez toutes vos données Elastic en un seul endroit, en créant un tableau de bord et en ajoutant des visualisations.", diff --git a/x-pack/platform/plugins/private/translations/translations/ja-JP.json b/x-pack/platform/plugins/private/translations/translations/ja-JP.json index 52c4a1bf5b8c9..6c3164faad045 100644 --- a/x-pack/platform/plugins/private/translations/translations/ja-JP.json +++ b/x-pack/platform/plugins/private/translations/translations/ja-JP.json @@ -1466,8 +1466,6 @@ "dashboard.featureCatalogue.dashboardDescription": "ビジュアライゼーションと保存された検索のコレクションの表示と共有を行います。", "dashboard.featureCatalogue.dashboardSubtitle": "ダッシュボードでデータを分析します。", "dashboard.featureCatalogue.dashboardTitle": "ダッシュボード", - "dashboard.hasRunMigrationsBadge": "推奨を保存", - "dashboard.hasRunMigrationsBadgeToolTipContent": "このダッシュボードの1つ以上のパネルが新しいバージョンに更新されました。ダッシュボードを保存すると、次回の読み込みが速くなります。", "dashboard.labs.enableLabsDescription": "このフラグはビューアーで[ラボ]ボタンを使用できるかどうかを決定します。ダッシュボードで実験的機能を有効および無効にするための簡単な方法です。", "dashboard.labs.enableUI": "ダッシュボードで[ラボ]ボタンを有効にする", "dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription": "ダッシュボードを作成し、ビジュアライゼーションを追加して、すべてのElasticデータを1つの場所で分析します。", diff --git a/x-pack/platform/plugins/private/translations/translations/zh-CN.json b/x-pack/platform/plugins/private/translations/translations/zh-CN.json index c7b9faa1dd4b9..3fb56f88c24e0 100644 --- a/x-pack/platform/plugins/private/translations/translations/zh-CN.json +++ b/x-pack/platform/plugins/private/translations/translations/zh-CN.json @@ -1479,8 +1479,6 @@ "dashboard.featureCatalogue.dashboardDescription": "显示和共享可视化和已保存搜索的集合。", "dashboard.featureCatalogue.dashboardSubtitle": "在仪表板中分析数据。", "dashboard.featureCatalogue.dashboardTitle": "仪表板", - "dashboard.hasRunMigrationsBadge": "保存推荐项", - "dashboard.hasRunMigrationsBadgeToolTipContent": "此仪表板上的一个或多个面板已更新到新版本。保存该仪表板以便下次更快加载。", "dashboard.labs.enableLabsDescription": "此标志决定查看者是否有权访问用于在仪表板中快速启用和禁用技术预览功能的'实验'按钮。", "dashboard.labs.enableUI": "在仪表板中启用实验按钮", "dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription": "通过创建仪表板并添加可视化,在一个位置分析所有 Elastic 数据。",