From 69ccde46da53b66334e858a92a11e09ff5fedd7e Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 09:00:12 -0600 Subject: [PATCH 01/25] [aiops] synchronously register embeddables and actions to fix flaky add panel test --- .../embeddable_change_point_chart_factory.tsx | 2 ++ .../public/embeddables/ensure_capabilities.ts | 16 ++++++++++ .../embeddable_log_rate_analysis_factory.tsx | 2 ++ .../embeddable_pattern_analysis_factory.tsx | 2 ++ .../plugins/shared/aiops/public/plugin.tsx | 16 +++++----- .../ui_actions/create_change_point_chart.tsx | 3 +- .../create_pattern_analysis_action.tsx | 3 +- .../public/ui_actions/has_capabilities.ts | 14 +++++++++ .../shared/aiops/public/ui_actions/index.ts | 30 +++++++++++-------- 9 files changed, 66 insertions(+), 22 deletions(-) create mode 100644 x-pack/platform/plugins/shared/aiops/public/embeddables/ensure_capabilities.ts create mode 100644 x-pack/platform/plugins/shared/aiops/public/ui_actions/has_capabilities.ts diff --git a/x-pack/platform/plugins/shared/aiops/public/embeddables/change_point_chart/embeddable_change_point_chart_factory.tsx b/x-pack/platform/plugins/shared/aiops/public/embeddables/change_point_chart/embeddable_change_point_chart_factory.tsx index c670f979b19a4..2f12db2f8cd37 100644 --- a/x-pack/platform/plugins/shared/aiops/public/embeddables/change_point_chart/embeddable_change_point_chart_factory.tsx +++ b/x-pack/platform/plugins/shared/aiops/public/embeddables/change_point_chart/embeddable_change_point_chart_factory.tsx @@ -35,6 +35,7 @@ import { } from './initialize_change_point_controls'; import type { ChangePointEmbeddableApi } from './types'; import type { ChangePointEmbeddableState } from '../../../common/embeddables/change_point_chart/types'; +import { ensureCapabilities } from '../ensure_capabilities'; export type EmbeddableChangePointChartType = typeof EMBEDDABLE_CHANGE_POINT_CHART_TYPE; @@ -45,6 +46,7 @@ export const getChangePointChartEmbeddableFactory = ( type: EMBEDDABLE_CHANGE_POINT_CHART_TYPE, buildEmbeddable: async ({ initialState, finalizeApi, uuid, parentApi }) => { const [coreStart, pluginStart] = await getStartServices(); + ensureCapabilities(coreStart); const timeRangeManager = initializeTimeRangeManager(initialState); const titleManager = initializeTitleManager(initialState); diff --git a/x-pack/platform/plugins/shared/aiops/public/embeddables/ensure_capabilities.ts b/x-pack/platform/plugins/shared/aiops/public/embeddables/ensure_capabilities.ts new file mode 100644 index 0000000000000..54fa1a35590c7 --- /dev/null +++ b/x-pack/platform/plugins/shared/aiops/public/embeddables/ensure_capabilities.ts @@ -0,0 +1,16 @@ +/* + * 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 { CoreStart } from '@kbn/core/public'; + +export function ensureCapabilities(coreStart: CoreStart) { + const { canUseAiops } = coreStart.application.capabilities.ml; + const aiopsEnabled = coreStart.application.capabilities.aiops.enabled; + if (!canUseAiops || !aiopsEnabled) { + throw new Error('Invalid license'); + } +} diff --git a/x-pack/platform/plugins/shared/aiops/public/embeddables/log_rate_analysis/embeddable_log_rate_analysis_factory.tsx b/x-pack/platform/plugins/shared/aiops/public/embeddables/log_rate_analysis/embeddable_log_rate_analysis_factory.tsx index c85d75a56de03..0e3d10da244ed 100644 --- a/x-pack/platform/plugins/shared/aiops/public/embeddables/log_rate_analysis/embeddable_log_rate_analysis_factory.tsx +++ b/x-pack/platform/plugins/shared/aiops/public/embeddables/log_rate_analysis/embeddable_log_rate_analysis_factory.tsx @@ -34,6 +34,7 @@ import { initializeLogRateAnalysisControls } from './initialize_log_rate_analysi import type { LogRateAnalysisEmbeddableApi } from './types'; import { EmbeddableLogRateAnalysisUserInput } from './log_rate_analysis_config_input'; import type { LogRateAnalysisEmbeddableState } from '../../../common/embeddables/log_rate_analysis/types'; +import { ensureCapabilities } from '../ensure_capabilities'; export type EmbeddableLogRateAnalysisType = typeof EMBEDDABLE_LOG_RATE_ANALYSIS_TYPE; @@ -44,6 +45,7 @@ export const getLogRateAnalysisEmbeddableFactory = ( type: EMBEDDABLE_LOG_RATE_ANALYSIS_TYPE, buildEmbeddable: async ({ initialState, finalizeApi, uuid, parentApi }) => { const [coreStart, pluginStart] = await getStartServices(); + ensureCapabilities(coreStart); const runtimeState = initialState; const timeRangeManager = initializeTimeRangeManager(initialState); const titleManager = initializeTitleManager(initialState); diff --git a/x-pack/platform/plugins/shared/aiops/public/embeddables/pattern_analysis/embeddable_pattern_analysis_factory.tsx b/x-pack/platform/plugins/shared/aiops/public/embeddables/pattern_analysis/embeddable_pattern_analysis_factory.tsx index 04cb3be8b91ed..90840bca3ade8 100644 --- a/x-pack/platform/plugins/shared/aiops/public/embeddables/pattern_analysis/embeddable_pattern_analysis_factory.tsx +++ b/x-pack/platform/plugins/shared/aiops/public/embeddables/pattern_analysis/embeddable_pattern_analysis_factory.tsx @@ -30,6 +30,7 @@ import type { AiopsPluginStart, AiopsPluginStartDeps } from '../../types'; import { initializePatternAnalysisControls } from './initialize_pattern_analysis_controls'; import type { PatternAnalysisEmbeddableApi } from './types'; import type { PatternAnalysisEmbeddableState } from '../../../common/embeddables/pattern_analysis/types'; +import { ensureCapabilities } from '../ensure_capabilities'; export type EmbeddablePatternAnalysisType = typeof EMBEDDABLE_PATTERN_ANALYSIS_TYPE; @@ -40,6 +41,7 @@ export const getPatternAnalysisEmbeddableFactory = ( type: EMBEDDABLE_PATTERN_ANALYSIS_TYPE, buildEmbeddable: async ({ initialState, finalizeApi, uuid, parentApi }) => { const [coreStart, pluginStart] = await getStartServices(); + ensureCapabilities(coreStart); const runtimeState = initialState; const timeRangeManager = initializeTimeRangeManager(initialState); const titleManager = initializeTitleManager(initialState); diff --git a/x-pack/platform/plugins/shared/aiops/public/plugin.tsx b/x-pack/platform/plugins/shared/aiops/public/plugin.tsx index 846041f08fc87..18538be9b5238 100755 --- a/x-pack/platform/plugins/shared/aiops/public/plugin.tsx +++ b/x-pack/platform/plugins/shared/aiops/public/plugin.tsx @@ -26,19 +26,19 @@ export class AiopsPlugin implements Plugin { public setup(core: AiopsCoreSetup, { embeddable, cases, uiActions }: AiopsPluginSetupDeps) { + if (embeddable) { + registerEmbeddables(embeddable, core); + } + + if (uiActions) { + registerAiopsUiActions(uiActions, core); + } + core.getStartServices().then(([coreStart, pluginStart]) => { const { canUseAiops } = coreStart.application.capabilities.ml; const aiopsEnabled = coreStart.application.capabilities.aiops.enabled; if (canUseAiops && aiopsEnabled) { - if (embeddable) { - registerEmbeddables(embeddable, core); - } - - if (uiActions) { - registerAiopsUiActions(uiActions, coreStart, pluginStart); - } - if (cases) { registerCases(cases, coreStart, pluginStart); } diff --git a/x-pack/platform/plugins/shared/aiops/public/ui_actions/create_change_point_chart.tsx b/x-pack/platform/plugins/shared/aiops/public/ui_actions/create_change_point_chart.tsx index a682f15076097..5ddec562a9d3a 100644 --- a/x-pack/platform/plugins/shared/aiops/public/ui_actions/create_change_point_chart.tsx +++ b/x-pack/platform/plugins/shared/aiops/public/ui_actions/create_change_point_chart.tsx @@ -19,6 +19,7 @@ import type { AiopsPluginStartDeps } from '../types'; import type { ChangePointChartActionContext } from './change_point_action_context'; import type { ChangePointEmbeddableState } from '../../common/embeddables/change_point_chart/types'; +import { hasCapabilities } from './has_capabilities'; const parentApiIsCompatible = async ( parentApi: unknown @@ -51,7 +52,7 @@ export function createAddChangePointChartAction( defaultMessage: 'Change point detection', }), async isCompatible(context: EmbeddableApiContext) { - return Boolean(await parentApiIsCompatible(context.embeddable)); + return hasCapabilities(coreStart) && Boolean(await parentApiIsCompatible(context.embeddable)); }, async execute(context) { const presentationContainerParent = await parentApiIsCompatible(context.embeddable); diff --git a/x-pack/platform/plugins/shared/aiops/public/ui_actions/create_pattern_analysis_action.tsx b/x-pack/platform/plugins/shared/aiops/public/ui_actions/create_pattern_analysis_action.tsx index 8775d1119a8b2..cb222c5f18876 100644 --- a/x-pack/platform/plugins/shared/aiops/public/ui_actions/create_pattern_analysis_action.tsx +++ b/x-pack/platform/plugins/shared/aiops/public/ui_actions/create_pattern_analysis_action.tsx @@ -20,6 +20,7 @@ import type { PatternAnalysisEmbeddableApi } from '../embeddables/pattern_analys import type { PatternAnalysisActionContext } from './pattern_analysis_action_context'; import { DEFAULT_MINIMUM_TIME_RANGE_OPTION } from '../components/log_categorization/log_categorization_for_embeddable/minimum_time_range'; +import { hasCapabilities } from './has_capabilities'; const parentApiIsCompatible = async ( parentApi: unknown @@ -42,7 +43,7 @@ export function createAddPatternAnalysisEmbeddableAction( defaultMessage: 'Pattern analysis', }), async isCompatible(context: EmbeddableApiContext) { - return Boolean(await parentApiIsCompatible(context.embeddable)); + return hasCapabilities(coreStart) && Boolean(await parentApiIsCompatible(context.embeddable)); }, async execute(context) { const presentationContainerParent = await parentApiIsCompatible(context.embeddable); diff --git a/x-pack/platform/plugins/shared/aiops/public/ui_actions/has_capabilities.ts b/x-pack/platform/plugins/shared/aiops/public/ui_actions/has_capabilities.ts new file mode 100644 index 0000000000000..e4f595f597c88 --- /dev/null +++ b/x-pack/platform/plugins/shared/aiops/public/ui_actions/has_capabilities.ts @@ -0,0 +1,14 @@ +/* + * 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 { CoreStart } from '@kbn/core/public'; + +export function hasCapabilities(coreStart: CoreStart) { + const { canUseAiops } = coreStart.application.capabilities.ml; + const aiopsEnabled = coreStart.application.capabilities.aiops.enabled; + return canUseAiops && aiopsEnabled; +} diff --git a/x-pack/platform/plugins/shared/aiops/public/ui_actions/index.ts b/x-pack/platform/plugins/shared/aiops/public/ui_actions/index.ts index e25f0c81e957e..04e904183e2b5 100644 --- a/x-pack/platform/plugins/shared/aiops/public/ui_actions/index.ts +++ b/x-pack/platform/plugins/shared/aiops/public/ui_actions/index.ts @@ -6,24 +6,20 @@ */ import type { UiActionsSetup } from '@kbn/ui-actions-plugin/public'; -import type { CoreStart } from '@kbn/core/public'; import { ADD_PANEL_TRIGGER, CATEGORIZE_FIELD_TRIGGER, ON_OPEN_PANEL_MENU, } from '@kbn/ui-actions-plugin/common/trigger_ids'; -import type { AiopsPluginStartDeps } from '../types'; +import type { AiopsCoreSetup } from '../plugin'; -export function registerAiopsUiActions( - uiActions: UiActionsSetup, - coreStart: CoreStart, - pluginStart: AiopsPluginStartDeps -) { +export function registerAiopsUiActions(uiActions: UiActionsSetup, core: AiopsCoreSetup) { uiActions.addTriggerActionAsync( ADD_PANEL_TRIGGER, 'create-pattern-analysis-embeddable', async () => { - const { createAddPatternAnalysisEmbeddableAction } = await import('./actions'); + const [{ createAddPatternAnalysisEmbeddableAction }, [coreStart, pluginStart]] = + await Promise.all([import('./actions'), core.getStartServices()]); const addPatternAnalysisAction = createAddPatternAnalysisEmbeddableAction( coreStart, pluginStart @@ -32,18 +28,27 @@ export function registerAiopsUiActions( } ); uiActions.addTriggerActionAsync(ADD_PANEL_TRIGGER, 'create-change-point-chart', async () => { - const { createAddChangePointChartAction } = await import('./actions'); + const [{ createAddChangePointChartAction }, [coreStart, pluginStart]] = await Promise.all([ + import('./actions'), + core.getStartServices(), + ]); const addChangePointChartAction = createAddChangePointChartAction(coreStart, pluginStart); return addChangePointChartAction; }); uiActions.addTriggerActionAsync(CATEGORIZE_FIELD_TRIGGER, 'ACTION_CATEGORIZE_FIELD', async () => { - const { createCategorizeFieldAction } = await import('./actions'); + const [{ createCategorizeFieldAction }, [coreStart, pluginStart]] = await Promise.all([ + import('./actions'), + core.getStartServices(), + ]); return createCategorizeFieldAction(coreStart, pluginStart); }); uiActions.addTriggerActionAsync(ON_OPEN_PANEL_MENU, 'open-change-point-in-ml-app', async () => { - const { createOpenChangePointInMlAppAction } = await import('./actions'); + const [{ createOpenChangePointInMlAppAction }, [coreStart, pluginStart]] = await Promise.all([ + import('./actions'), + core.getStartServices(), + ]); const openChangePointInMlAppAction = createOpenChangePointInMlAppAction(coreStart, pluginStart); return openChangePointInMlAppAction; }); @@ -52,7 +57,8 @@ export function registerAiopsUiActions( ADD_PANEL_TRIGGER, 'create-log-rate-analysis-embeddable', async () => { - const { createAddLogRateAnalysisEmbeddableAction } = await import('./actions'); + const [{ createAddLogRateAnalysisEmbeddableAction }, [coreStart, pluginStart]] = + await Promise.all([import('./actions'), core.getStartServices()]); const addLogRateAnalysisAction = createAddLogRateAnalysisEmbeddableAction( coreStart, pluginStart From b8afc1636ea12d75ec3ef37d615ebd017babdfec Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 09:05:17 -0600 Subject: [PATCH 02/25] unskip test --- .../scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts index 6e40b7bb6de68..ff604badf3473 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts @@ -47,8 +47,7 @@ const getExpected = (config: ScoutTestConfig) => { * This test exists to ensures additions to menu * notify our team and can be reviewed by design. */ -// Failing: See https://github.com/elastic/kibana/issues/268101 -spaceTest.describe.skip( +spaceTest.describe( 'Dashboard add panel flyout', { tag: [ From 336c9f5d1ada62cecc547b05e0c1aba089ae5d06 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 09:43:58 -0600 Subject: [PATCH 03/25] update expects --- .../ui/parallel_tests/dashboard_add_panel_flyout.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts index ff604badf3473..f2e30e2590947 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts @@ -19,8 +19,8 @@ const getExpected = (config: ScoutTestConfig) => { 'visualizationsGroup', 'controlsGroup', 'annotation-and-navigationGroup', - 'mlGroup', 'logs-aiopsGroup', + 'mlGroup', 'legacyGroup', ], count: 20, @@ -32,8 +32,8 @@ const getExpected = (config: ScoutTestConfig) => { 'visualizationsGroup', 'controlsGroup', 'annotation-and-navigationGroup', - 'mlGroup', 'logs-aiopsGroup', + 'mlGroup', 'observabilityGroup', 'legacyGroup', ], From 54ba095ce80795045410f9f84e74e04b22c0b4c7 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 09:45:13 -0600 Subject: [PATCH 04/25] cleanu --- .../public/ui_actions/create_log_rate_analysis_actions.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/platform/plugins/shared/aiops/public/ui_actions/create_log_rate_analysis_actions.tsx b/x-pack/platform/plugins/shared/aiops/public/ui_actions/create_log_rate_analysis_actions.tsx index c25efb315d81c..ea9aac826407c 100644 --- a/x-pack/platform/plugins/shared/aiops/public/ui_actions/create_log_rate_analysis_actions.tsx +++ b/x-pack/platform/plugins/shared/aiops/public/ui_actions/create_log_rate_analysis_actions.tsx @@ -22,6 +22,7 @@ import type { AiopsPluginStartDeps } from '../types'; import type { LogRateAnalysisActionContext } from './log_rate_analysis_action_context'; import { EmbeddableLogRateAnalysisUserInput } from '../embeddables/log_rate_analysis/log_rate_analysis_config_input'; +import { hasCapabilities } from './has_capabilities'; const parentApiIsCompatible = async ( parentApi: unknown @@ -44,7 +45,7 @@ export function createAddLogRateAnalysisEmbeddableAction( defaultMessage: 'Log rate analysis', }), async isCompatible(context: EmbeddableApiContext) { - return Boolean(await parentApiIsCompatible(context.embeddable)); + return hasCapabilities(coreStart) && Boolean(await parentApiIsCompatible(context.embeddable)); }, async execute(context) { const presentationContainerParent = await parentApiIsCompatible(context.embeddable); From b007923818dbe5460654dfc405b199911f3fdef5 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 10:38:37 -0600 Subject: [PATCH 05/25] log actions --- .../src/playwright/page_objects/dashboard_app.ts | 15 +++++++++++++-- .../dashboard_add_panel_flyout.spec.ts | 6 ++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/platform/packages/shared/kbn-scout/src/playwright/page_objects/dashboard_app.ts b/src/platform/packages/shared/kbn-scout/src/playwright/page_objects/dashboard_app.ts index 46855497762f2..dc8c277854c2c 100644 --- a/src/platform/packages/shared/kbn-scout/src/playwright/page_objects/dashboard_app.ts +++ b/src/platform/packages/shared/kbn-scout/src/playwright/page_objects/dashboard_app.ts @@ -504,8 +504,19 @@ export class DashboardApp { ); } - async getAddPanelFlyoutPanelTypesCount(): Promise { - return this.panelSelectionFlyout.locator('[data-test-subj*="create-action-"]').count(); + async getAddPanelFlyoutActions(): Promise { + const addPanelActions = await this.panelSelectionFlyout + .locator('[data-test-subj*="create-action-"]') + .all(); + + return await Promise.all( + addPanelActions.map(async (action) => { + const testSubj = await action.getAttribute('data-test-subj'); + // remove prefix so strings like 'create-action-Links' become 'Links' + const match = testSubj?.match(/create-action-(.*)/); + return match?.[1] ?? ''; + }) + ); } /** diff --git a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts index f2e30e2590947..171b46433c032 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts @@ -79,7 +79,7 @@ spaceTest.describe( await scoutSpace.savedObjects.cleanStandardList(); }); - spaceTest('renders add panel flyout', async ({ pageObjects }) => { + spaceTest('renders add panel flyout', async ({ pageObjects, log }) => { await spaceTest.step('open new dashboard and add panel flyout', async () => { await pageObjects.dashboard.openNewDashboard(); await pageObjects.dashboard.openAddPanelFlyout(); @@ -91,7 +91,9 @@ spaceTest.describe( }); await spaceTest.step('verify total panel count', async () => { - expect(await pageObjects.dashboard.getAddPanelFlyoutPanelTypesCount()).toBe(expectedCount); + const addPanelActions = await pageObjects.dashboard.getAddPanelFlyoutActions(); + log.debug(`Add panel actions: ${addPanelActions.join(',')}`); + expect(addPanelActions).toHaveLength(expectedCount); }); }); } From 570d2bb4a1f2eb99cda642179dfc25f4a0a6935c Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 12:19:37 -0600 Subject: [PATCH 06/25] slo --- .../shared/embeddable/public/plugin.tsx | 2 + .../react_embeddable_registry.ts | 12 ++ .../alerts/slo_alerts_embeddable_factory.tsx | 2 + .../burn_rate_react_embeddable_factory.tsx | 2 + .../public/embeddable/slo/ensure_license.ts | 17 ++ .../error_budget_react_embeddable_factory.tsx | 2 + .../slo/overview/slo_embeddable_factory.tsx | 2 + .../slo/public/register_embeddables.ts | 169 +++++++++--------- .../ui_actions/create_alerts_panel_action.tsx | 3 +- .../create_burn_rate_panel_action.tsx | 3 +- .../ui_actions/create_error_budget_action.tsx | 3 +- .../create_overview_panel_action.tsx | 3 +- .../slo/public/ui_actions/is_valid_license.ts | 19 ++ .../public/ui_actions/register_ui_actions.ts | 55 +++--- 14 files changed, 177 insertions(+), 117 deletions(-) create mode 100644 x-pack/solutions/observability/plugins/slo/public/embeddable/slo/ensure_license.ts create mode 100644 x-pack/solutions/observability/plugins/slo/public/ui_actions/is_valid_license.ts diff --git a/src/platform/plugins/shared/embeddable/public/plugin.tsx b/src/platform/plugins/shared/embeddable/public/plugin.tsx index 2c9339da363c3..bd5e292a82c35 100644 --- a/src/platform/plugins/shared/embeddable/public/plugin.tsx +++ b/src/platform/plugins/shared/embeddable/public/plugin.tsx @@ -33,6 +33,7 @@ import { } from './bwc/legacy_url_transform'; import { registerDrilldown } from './drilldowns/registry'; import { registerActions } from './ui_actions/register_actions'; +import { closeSetup } from './react_embeddable_system/react_embeddable_registry'; export class EmbeddablePublicPlugin implements Plugin { private stateTransferService: EmbeddableStateTransfer = {} as EmbeddableStateTransfer; @@ -53,6 +54,7 @@ export class EmbeddablePublicPlugin implements Plugin { this.appList = appList; }); diff --git a/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts b/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts index 9693f49d7a9af..3ad3d115fa0f5 100644 --- a/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts +++ b/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts @@ -14,6 +14,8 @@ const registry: { [key: string]: () => Promise> } = export const TYPE_REGEX = /^[a-z_]+$/; // lowercase letters and underscores +let isSetupComplete = false; + /** * Registers an embeddable public defintion. This should be called at plugin setup time. * Be sure to register an embeddable server definition for this type. @@ -30,6 +32,12 @@ export const registerEmbeddablePublicDefinition = < type: string, getFactory: () => Promise> ) => { + if (isSetupComplete) + throw new Error( + i18n.translate('embeddableApi.reactEmbeddable.setCompleteError', { + defaultMessage: 'Embeddables must be registered during plugin setup phase. Do not register embeddables asynchronously', + }) + ); if (registry[type] !== undefined) throw new Error( i18n.translate('embeddableApi.reactEmbeddable.factoryAlreadyExistsError', { @@ -56,3 +64,7 @@ export const getReactEmbeddableFactory = async < ): Promise | undefined> => { return registry[key]?.(); }; + +export function closeSetup() { + isSetupComplete = true; +} diff --git a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/alerts/slo_alerts_embeddable_factory.tsx b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/alerts/slo_alerts_embeddable_factory.tsx index 0e4b0288ea83b..314c345480862 100644 --- a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/alerts/slo_alerts_embeddable_factory.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/alerts/slo_alerts_embeddable_factory.tsx @@ -32,6 +32,7 @@ import { import { SloAlertsWrapper } from './slo_alerts_wrapper'; import type { AlertsCustomState, SloAlertsApi, SloAlertsEmbeddableState } from './types'; import { openSloConfiguration } from './slo_alerts_open_configuration'; +import { ensureLicense } from '../ensure_license'; const queryClient = new QueryClient(); export const getAlertsPanelTitle = () => @@ -59,6 +60,7 @@ export function getAlertsEmbeddableFactory({ uuid, parentApi, }) => { + await ensureLicense(pluginsStart.licensing); const deps = { ...coreStart, ...pluginsStart }; const drilldownsManager = initializeDrilldownsManager(uuid, initialState); async function onEdit() { diff --git a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/burn_rate/burn_rate_react_embeddable_factory.tsx b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/burn_rate/burn_rate_react_embeddable_factory.tsx index 8de8bc16bf7ca..34096371e0994 100644 --- a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/burn_rate/burn_rate_react_embeddable_factory.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/burn_rate/burn_rate_react_embeddable_factory.tsx @@ -24,6 +24,7 @@ import { SLO_BURN_RATE_EMBEDDABLE_ID } from '../../../../common/embeddables/burn import type { BurnRateApi, BurnRateCustomState, BurnRateEmbeddableState } from './types'; import type { SLOPublicPluginsStart, SLORepositoryClient } from '../../../types'; import { PluginContext } from '../../../context/plugin_context'; +import { ensureLicense } from '../ensure_license'; const getTitle = () => i18n.translate('xpack.slo.burnRateEmbeddable.title', { @@ -48,6 +49,7 @@ export const getBurnRateEmbeddableFactory = ({ parentApi, initializeDrilldownsManager, }) => { + await ensureLicense(pluginsStart.licensing); const deps = { ...coreStart, ...pluginsStart }; const titleManager = initializeTitleManager(initialState); const defaultTitle$ = new BehaviorSubject(getTitle()); diff --git a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/ensure_license.ts b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/ensure_license.ts new file mode 100644 index 0000000000000..c5bcf5c42136e --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/ensure_license.ts @@ -0,0 +1,17 @@ +/* + * 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 { firstValueFrom } from 'rxjs'; +import type { LicensingPluginStart } from '@kbn/licensing-plugin/public'; + +export async function ensureLicense(licensing: LicensingPluginStart) { + const license = await firstValueFrom(licensing.license$); + const hasPlatinumLicense = license.hasAtLeast('platinum'); + if (!hasPlatinumLicense) { + throw new Error('Invalid license'); + } +} diff --git a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/error_budget/error_budget_react_embeddable_factory.tsx b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/error_budget/error_budget_react_embeddable_factory.tsx index be388f7a1b1e7..7c3f0df2d1048 100644 --- a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/error_budget/error_budget_react_embeddable_factory.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/error_budget/error_budget_react_embeddable_factory.tsx @@ -29,6 +29,7 @@ import { import { SloErrorBudget } from './error_budget_burn_down'; import type { ErrorBudgetApi, ErrorBudgetEmbeddableState } from './types'; import type { ErrorBudgetCustomState } from '../../../../common/embeddables/error_budget/types'; +import { ensureLicense } from '../ensure_license'; const getErrorBudgetPanelTitle = () => i18n.translate('xpack.slo.errorBudgetEmbeddable.title', { @@ -53,6 +54,7 @@ export const getErrorBudgetEmbeddableFactory = ({ uuid, parentApi, }) => { + await ensureLicense(pluginsStart.licensing); const deps = { ...coreStart, ...pluginsStart }; const drilldownsManager = initializeDrilldownsManager(uuid, initialState); const titleManager = initializeTitleManager(initialState); diff --git a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx index b9d50a5df1281..216b0a63193da 100644 --- a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx @@ -38,6 +38,7 @@ import type { SingleOverviewCustomState, } from '../../../../common/embeddables/overview/types'; import { openSloConfiguration } from './slo_overview_open_configuration'; +import { ensureLicense } from '../ensure_license'; const getOverviewPanelTitle = () => i18n.translate('xpack.slo.sloEmbeddable.displayName', { @@ -61,6 +62,7 @@ export const getOverviewEmbeddableFactory = ({ uuid, parentApi, }) => { + await ensureLicense(pluginsStart.licensing); const deps = { ...coreStart, ...pluginsStart }; const state = initialState; diff --git a/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts b/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts index 479be3fcfb930..d141175f8a10c 100644 --- a/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts +++ b/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts @@ -7,7 +7,6 @@ import type { CoreSetup } from '@kbn/core/public'; import type { Reference } from '@kbn/content-management-utils'; import type { DrilldownTransforms } from '@kbn/embeddable-plugin/common'; -import { firstValueFrom } from 'rxjs'; import { ALL_VALUE } from '@kbn/slo-schema/src/constants'; import type { AlertsEmbeddableState } from '../server/lib/embeddables/alerts_schema'; import { SLO_ALERTS_EMBEDDABLE_ID } from '../common/embeddables/alerts/constants'; @@ -29,105 +28,99 @@ export interface RegisterEmbeddablesDeps { kibanaVersion: string; } -export const registerEmbeddables = async ({ +export const registerEmbeddables = ({ core, plugins, sloClient, kibanaVersion, -}: RegisterEmbeddablesDeps): Promise => { - const licensing = plugins.licensing; - const license = await firstValueFrom(licensing.license$); - - const hasPlatinumLicense = license.hasAtLeast('platinum'); - if (hasPlatinumLicense) { - const [coreStart, pluginsStart] = await core.getStartServices(); - - pluginsStart.presentationUtil.registerPanelPlacementSettings( - SLO_OVERVIEW_EMBEDDABLE_ID, - (serializedState?: OverviewEmbeddableState) => { - if ( - (serializedState as SingleOverviewCustomState)?.slo_instance_id === ALL_VALUE || - (serializedState as GroupOverviewCustomState)?.group_filters - ) { - return { placementSettings: { width: 24, height: 8 } }; - } - return { placementSettings: { width: 12, height: 8 } }; - } - ); - pluginsStart.presentationUtil.registerPanelPlacementSettings( - SLO_BURN_RATE_EMBEDDABLE_ID, - () => { - return { placementSettings: { width: 14, height: 7 } }; +}: RegisterEmbeddablesDeps) => { + // const [coreStart, pluginsStart] = await core.getStartServices(); + plugins.presentationUtil.registerPanelPlacementSettings( + SLO_OVERVIEW_EMBEDDABLE_ID, + (serializedState?: OverviewEmbeddableState) => { + if ( + (serializedState as SingleOverviewCustomState)?.slo_instance_id === ALL_VALUE || + (serializedState as GroupOverviewCustomState)?.group_filters + ) { + return { placementSettings: { width: 24, height: 8 } }; } - ); + return { placementSettings: { width: 12, height: 8 } }; + } + ); + plugins.presentationUtil.registerPanelPlacementSettings(SLO_BURN_RATE_EMBEDDABLE_ID, () => { + return { placementSettings: { width: 14, height: 7 } }; + }); - plugins.embeddable.registerEmbeddablePublicDefinition(SLO_OVERVIEW_EMBEDDABLE_ID, async () => { - const { getOverviewEmbeddableFactory } = await import( - './embeddable/slo/overview/slo_embeddable_factory' + plugins.embeddable.registerEmbeddablePublicDefinition(SLO_OVERVIEW_EMBEDDABLE_ID, async () => { + const [{ getOverviewEmbeddableFactory }, [coreStart, pluginsStart]] = await Promise.all([ + import('./embeddable/slo/overview/slo_embeddable_factory'), + core.getStartServices(), + ]); + return getOverviewEmbeddableFactory({ coreStart, pluginsStart, sloClient }); + }); + plugins.embeddable.registerLegacyURLTransform( + SLO_OVERVIEW_EMBEDDABLE_ID, + async (transformDrilldownsOut: DrilldownTransforms['transformOut']) => { + const { getTransformOut } = await import( + '../common/embeddables/overview/transforms/get_transform_out' ); - return getOverviewEmbeddableFactory({ coreStart, pluginsStart, sloClient }); - }); - plugins.embeddable.registerLegacyURLTransform( - SLO_OVERVIEW_EMBEDDABLE_ID, - async (transformDrilldownsOut: DrilldownTransforms['transformOut']) => { - const { getTransformOut } = await import( - '../common/embeddables/overview/transforms/get_transform_out' - ); - const transformOut = getTransformOut(transformDrilldownsOut); - return ( - storedState: object, - panelReferences?: Reference[], - containerReferences?: Reference[], - id?: string - ) => transformOut(storedState as OverviewEmbeddableState, panelReferences); - } - ); + const transformOut = getTransformOut(transformDrilldownsOut); + return ( + storedState: object, + panelReferences?: Reference[], + containerReferences?: Reference[], + id?: string + ) => transformOut(storedState as OverviewEmbeddableState, panelReferences); + } + ); - plugins.embeddable.registerEmbeddablePublicDefinition(SLO_ALERTS_EMBEDDABLE_ID, async () => { - const { getAlertsEmbeddableFactory } = await import( - './embeddable/slo/alerts/slo_alerts_embeddable_factory' - ); + plugins.embeddable.registerEmbeddablePublicDefinition(SLO_ALERTS_EMBEDDABLE_ID, async () => { + const [{ getAlertsEmbeddableFactory }, [coreStart, pluginsStart]] = await Promise.all([ + import('./embeddable/slo/alerts/slo_alerts_embeddable_factory'), + core.getStartServices(), + ]); - return getAlertsEmbeddableFactory({ coreStart, pluginsStart, sloClient, kibanaVersion }); - }); - plugins.embeddable.registerLegacyURLTransform( - SLO_ALERTS_EMBEDDABLE_ID, - async (transformDrilldownsOut: DrilldownTransforms['transformOut']) => { - const { getTransformOut } = await import( - '../common/embeddables/alerts/transforms/get_transform_out' - ); - const transformOut = getTransformOut(transformDrilldownsOut); - return ( - storedState: object, - panelReferences?: Reference[], - containerReferences?: Reference[], - id?: string - ) => transformOut(storedState as AlertsEmbeddableState, panelReferences); - } - ); - - plugins.embeddable.registerEmbeddablePublicDefinition(SLO_ERROR_BUDGET_ID, async () => { - const { getErrorBudgetEmbeddableFactory } = await import( - './embeddable/slo/error_budget/error_budget_react_embeddable_factory' + return getAlertsEmbeddableFactory({ coreStart, pluginsStart, sloClient, kibanaVersion }); + }); + plugins.embeddable.registerLegacyURLTransform( + SLO_ALERTS_EMBEDDABLE_ID, + async (transformDrilldownsOut: DrilldownTransforms['transformOut']) => { + const { getTransformOut } = await import( + '../common/embeddables/alerts/transforms/get_transform_out' ); - return getErrorBudgetEmbeddableFactory({ - coreStart, - pluginsStart, - sloClient, - }); + const transformOut = getTransformOut(transformDrilldownsOut); + return ( + storedState: object, + panelReferences?: Reference[], + containerReferences?: Reference[], + id?: string + ) => transformOut(storedState as AlertsEmbeddableState, panelReferences); + } + ); + + plugins.embeddable.registerEmbeddablePublicDefinition(SLO_ERROR_BUDGET_ID, async () => { + const [{ getErrorBudgetEmbeddableFactory }, [coreStart, pluginsStart]] = await Promise.all([ + import('./embeddable/slo/error_budget/error_budget_react_embeddable_factory'), + core.getStartServices(), + ]); + return getErrorBudgetEmbeddableFactory({ + coreStart, + pluginsStart, + sloClient, }); + }); - plugins.embeddable.registerEmbeddablePublicDefinition(SLO_BURN_RATE_EMBEDDABLE_ID, async () => { - const { getBurnRateEmbeddableFactory } = await import( - './embeddable/slo/burn_rate/burn_rate_react_embeddable_factory' - ); - return getBurnRateEmbeddableFactory({ - coreStart, - pluginsStart, - sloClient, - }); + plugins.embeddable.registerEmbeddablePublicDefinition(SLO_BURN_RATE_EMBEDDABLE_ID, async () => { + const [{ getBurnRateEmbeddableFactory }, [coreStart, pluginsStart]] = await Promise.all([ + import('./embeddable/slo/burn_rate/burn_rate_react_embeddable_factory'), + core.getStartServices(), + ]); + return getBurnRateEmbeddableFactory({ + coreStart, + pluginsStart, + sloClient, }); + }); - registerSloUiActions(plugins.uiActions, coreStart, pluginsStart, sloClient); - } + registerSloUiActions(plugins.uiActions, core, sloClient); }; diff --git a/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_alerts_panel_action.tsx b/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_alerts_panel_action.tsx index 396381cbe8d46..69a4c48728b10 100644 --- a/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_alerts_panel_action.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_alerts_panel_action.tsx @@ -20,6 +20,7 @@ import { } from '../../common/embeddables/alerts/constants'; import type { SLORepositoryClient } from '../types'; import { openSloConfiguration } from '../embeddable/slo/alerts/slo_alerts_open_configuration'; +import { isValidLicense } from './is_valid_license'; export function createAddAlertsPanelAction( coreStart: CoreStart, @@ -32,7 +33,7 @@ export function createAddAlertsPanelAction( getIconType: () => 'alert', order: 10, isCompatible: async ({ embeddable }) => { - return apiIsPresentationContainer(embeddable); + return (await isValidLicense(pluginsStart)) && apiIsPresentationContainer(embeddable); }, execute: async ({ embeddable }) => { if (!apiIsPresentationContainer(embeddable)) throw new IncompatibleActionError(); diff --git a/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_burn_rate_panel_action.tsx b/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_burn_rate_panel_action.tsx index fa642e91b9998..7139a5a05562d 100644 --- a/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_burn_rate_panel_action.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_burn_rate_panel_action.tsx @@ -19,6 +19,7 @@ import { SLO_BURN_RATE_EMBEDDABLE_ID, } from '../embeddable/slo/burn_rate/constants'; import type { SLORepositoryClient } from '../types'; +import { isValidLicense } from './is_valid_license'; export function createBurnRatePanelAction( coreStart: CoreStart, @@ -31,7 +32,7 @@ export function createBurnRatePanelAction( order: 20, getIconType: () => 'chartGauge', isCompatible: async ({ embeddable }) => { - return apiIsPresentationContainer(embeddable); + return (await isValidLicense(pluginsStart)) && apiIsPresentationContainer(embeddable); }, execute: async ({ embeddable }) => { if (!apiIsPresentationContainer(embeddable)) throw new IncompatibleActionError(); diff --git a/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_error_budget_action.tsx b/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_error_budget_action.tsx index 56f35afbbd543..7753445c332a6 100644 --- a/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_error_budget_action.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_error_budget_action.tsx @@ -20,6 +20,7 @@ import { } from '../embeddable/slo/error_budget/constants'; import type { SLORepositoryClient } from '../types'; import { openSloConfiguration } from '../embeddable/slo/error_budget/error_budget_open_configuration'; +import { isValidLicense } from './is_valid_license'; export function createAddErrorBudgetPanelAction( coreStart: CoreStart, @@ -32,7 +33,7 @@ export function createAddErrorBudgetPanelAction( order: 6, getIconType: () => 'chartLine', isCompatible: async ({ embeddable }) => { - return apiIsPresentationContainer(embeddable); + return (await isValidLicense(pluginsStart)) && apiIsPresentationContainer(embeddable); }, execute: async ({ embeddable }) => { if (!apiIsPresentationContainer(embeddable)) throw new IncompatibleActionError(); diff --git a/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_overview_panel_action.tsx b/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_overview_panel_action.tsx index ac69eaa3d8932..5be562981ad42 100644 --- a/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_overview_panel_action.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_overview_panel_action.tsx @@ -18,6 +18,7 @@ import { ADD_SLO_OVERVIEW_ACTION_ID } from '../embeddable/slo/overview/constants import { SLO_OVERVIEW_EMBEDDABLE_ID } from '../../common/embeddables/overview/constants'; import type { SLORepositoryClient } from '../types'; import { openSloConfiguration } from '../embeddable/slo/overview/slo_overview_open_configuration'; +import { isValidLicense } from './is_valid_license'; export function createOverviewPanelAction( coreStart: CoreStart, @@ -30,7 +31,7 @@ export function createOverviewPanelAction( order: 20, getIconType: () => 'chartGauge', isCompatible: async ({ embeddable }) => { - return apiIsPresentationContainer(embeddable); + return (await isValidLicense(pluginsStart)) && apiIsPresentationContainer(embeddable); }, execute: async ({ embeddable }) => { if (!apiIsPresentationContainer(embeddable)) throw new IncompatibleActionError(); diff --git a/x-pack/solutions/observability/plugins/slo/public/ui_actions/is_valid_license.ts b/x-pack/solutions/observability/plugins/slo/public/ui_actions/is_valid_license.ts new file mode 100644 index 0000000000000..e8d84203fe30c --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/public/ui_actions/is_valid_license.ts @@ -0,0 +1,19 @@ +/* + * 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 { firstValueFrom } from 'rxjs'; +import type { SLOPublicPluginsStart } from '..'; + +export async function isValidLicense(pluginsStart: SLOPublicPluginsStart) { + const { serverless, cloud } = pluginsStart; + if (serverless && cloud?.serverless.projectType !== 'observability') { + return false; + } + + const license = await firstValueFrom(pluginsStart.licensing.license$); + return license.hasAtLeast('platinum'); +} diff --git a/x-pack/solutions/observability/plugins/slo/public/ui_actions/register_ui_actions.ts b/x-pack/solutions/observability/plugins/slo/public/ui_actions/register_ui_actions.ts index 1344f2654ddac..9df9081fc80ba 100644 --- a/x-pack/solutions/observability/plugins/slo/public/ui_actions/register_ui_actions.ts +++ b/x-pack/solutions/observability/plugins/slo/public/ui_actions/register_ui_actions.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { CoreStart } from '@kbn/core/public'; +import type { CoreSetup } from '@kbn/core/public'; import { ADD_PANEL_TRIGGER } from '@kbn/ui-actions-plugin/common/trigger_ids'; import type { UiActionsPublicSetup } from '@kbn/ui-actions-plugin/public/plugin'; import { ADD_SLO_ALERTS_ACTION_ID } from '../../common/embeddables/alerts/constants'; @@ -17,30 +17,35 @@ import { ADD_BURN_RATE_ACTION_ID } from '../embeddable/slo/burn_rate/constants'; export function registerSloUiActions( uiActions: UiActionsPublicSetup, - coreStart: CoreStart, - pluginsStart: SLOPublicPluginsStart, + core: CoreSetup, sloClient: SLORepositoryClient ) { - const { serverless, cloud } = pluginsStart; - - // Assign triggers - // Only register these actions in stateful kibana, and the serverless observability project - if (Boolean((serverless && cloud?.serverless.projectType === 'observability') || !serverless)) { - uiActions.addTriggerActionAsync(ADD_PANEL_TRIGGER, ADD_SLO_OVERVIEW_ACTION_ID, async () => { - const { createOverviewPanelAction } = await import('./add_panel_actions_module'); - return createOverviewPanelAction(coreStart, pluginsStart, sloClient); - }); - uiActions.addTriggerActionAsync(ADD_PANEL_TRIGGER, ADD_SLO_ERROR_BUDGET_ACTION_ID, async () => { - const { createAddErrorBudgetPanelAction } = await import('./add_panel_actions_module'); - return createAddErrorBudgetPanelAction(coreStart, pluginsStart, sloClient); - }); - uiActions.addTriggerActionAsync(ADD_PANEL_TRIGGER, ADD_SLO_ALERTS_ACTION_ID, async () => { - const { createAddAlertsPanelAction } = await import('./add_panel_actions_module'); - return createAddAlertsPanelAction(coreStart, pluginsStart, sloClient); - }); - uiActions.addTriggerActionAsync(ADD_PANEL_TRIGGER, ADD_BURN_RATE_ACTION_ID, async () => { - const { createBurnRatePanelAction } = await import('./add_panel_actions_module'); - return createBurnRatePanelAction(coreStart, pluginsStart, sloClient); - }); - } + uiActions.addTriggerActionAsync(ADD_PANEL_TRIGGER, ADD_SLO_OVERVIEW_ACTION_ID, async () => { + const [{ createOverviewPanelAction }, [coreStart, pluginsStart]] = await Promise.all([ + import('./add_panel_actions_module'), + core.getStartServices(), + ]); + return createOverviewPanelAction(coreStart, pluginsStart, sloClient); + }); + uiActions.addTriggerActionAsync(ADD_PANEL_TRIGGER, ADD_SLO_ERROR_BUDGET_ACTION_ID, async () => { + const [{ createAddErrorBudgetPanelAction }, [coreStart, pluginsStart]] = await Promise.all([ + import('./add_panel_actions_module'), + core.getStartServices(), + ]); + return createAddErrorBudgetPanelAction(coreStart, pluginsStart, sloClient); + }); + uiActions.addTriggerActionAsync(ADD_PANEL_TRIGGER, ADD_SLO_ALERTS_ACTION_ID, async () => { + const [{ createAddAlertsPanelAction }, [coreStart, pluginsStart]] = await Promise.all([ + import('./add_panel_actions_module'), + core.getStartServices(), + ]); + return createAddAlertsPanelAction(coreStart, pluginsStart, sloClient); + }); + uiActions.addTriggerActionAsync(ADD_PANEL_TRIGGER, ADD_BURN_RATE_ACTION_ID, async () => { + const [{ createBurnRatePanelAction }, [coreStart, pluginsStart]] = await Promise.all([ + import('./add_panel_actions_module'), + core.getStartServices(), + ]); + return createBurnRatePanelAction(coreStart, pluginsStart, sloClient); + }); } From fd9fae8ec4ed922b7c864aadc55b2c436356ce27 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 12:24:41 -0600 Subject: [PATCH 07/25] clean up --- .../observability/plugins/slo/public/register_embeddables.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts b/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts index d141175f8a10c..01e1df19539c2 100644 --- a/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts +++ b/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts @@ -34,7 +34,6 @@ export const registerEmbeddables = ({ sloClient, kibanaVersion, }: RegisterEmbeddablesDeps) => { - // const [coreStart, pluginsStart] = await core.getStartServices(); plugins.presentationUtil.registerPanelPlacementSettings( SLO_OVERVIEW_EMBEDDABLE_ID, (serializedState?: OverviewEmbeddableState) => { From fec79a1595e0142468ad2153c4b1c5268332fd57 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 7 May 2026 18:42:36 +0000 Subject: [PATCH 08/25] Changes from node scripts/eslint_all_files --no-cache --fix --- .../react_embeddable_system/react_embeddable_registry.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts b/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts index 3ad3d115fa0f5..0effcde0eb295 100644 --- a/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts +++ b/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts @@ -32,10 +32,11 @@ export const registerEmbeddablePublicDefinition = < type: string, getFactory: () => Promise> ) => { - if (isSetupComplete) + if (isSetupComplete) throw new Error( i18n.translate('embeddableApi.reactEmbeddable.setCompleteError', { - defaultMessage: 'Embeddables must be registered during plugin setup phase. Do not register embeddables asynchronously', + defaultMessage: + 'Embeddables must be registered during plugin setup phase. Do not register embeddables asynchronously', }) ); if (registry[type] !== undefined) From f39a253e40c067dcc55e1d3fe1c2686d8ecfcf95 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 12:44:34 -0600 Subject: [PATCH 09/25] revert embeddable check --- .../plugins/shared/embeddable/public/plugin.tsx | 2 -- .../react_embeddable_registry.ts | 13 ------------- 2 files changed, 15 deletions(-) diff --git a/src/platform/plugins/shared/embeddable/public/plugin.tsx b/src/platform/plugins/shared/embeddable/public/plugin.tsx index bd5e292a82c35..2c9339da363c3 100644 --- a/src/platform/plugins/shared/embeddable/public/plugin.tsx +++ b/src/platform/plugins/shared/embeddable/public/plugin.tsx @@ -33,7 +33,6 @@ import { } from './bwc/legacy_url_transform'; import { registerDrilldown } from './drilldowns/registry'; import { registerActions } from './ui_actions/register_actions'; -import { closeSetup } from './react_embeddable_system/react_embeddable_registry'; export class EmbeddablePublicPlugin implements Plugin { private stateTransferService: EmbeddableStateTransfer = {} as EmbeddableStateTransfer; @@ -54,7 +53,6 @@ export class EmbeddablePublicPlugin implements Plugin { this.appList = appList; }); diff --git a/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts b/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts index 0effcde0eb295..9693f49d7a9af 100644 --- a/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts +++ b/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts @@ -14,8 +14,6 @@ const registry: { [key: string]: () => Promise> } = export const TYPE_REGEX = /^[a-z_]+$/; // lowercase letters and underscores -let isSetupComplete = false; - /** * Registers an embeddable public defintion. This should be called at plugin setup time. * Be sure to register an embeddable server definition for this type. @@ -32,13 +30,6 @@ export const registerEmbeddablePublicDefinition = < type: string, getFactory: () => Promise> ) => { - if (isSetupComplete) - throw new Error( - i18n.translate('embeddableApi.reactEmbeddable.setCompleteError', { - defaultMessage: - 'Embeddables must be registered during plugin setup phase. Do not register embeddables asynchronously', - }) - ); if (registry[type] !== undefined) throw new Error( i18n.translate('embeddableApi.reactEmbeddable.factoryAlreadyExistsError', { @@ -65,7 +56,3 @@ export const getReactEmbeddableFactory = async < ): Promise | undefined> => { return registry[key]?.(); }; - -export function closeSetup() { - isSetupComplete = true; -} From 4e85d9bd5448ef8de02f509604eb92199c5acf36 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 13:23:03 -0600 Subject: [PATCH 10/25] Revert "revert embeddable check" This reverts commit f39a253e40c067dcc55e1d3fe1c2686d8ecfcf95. --- .../plugins/shared/embeddable/public/plugin.tsx | 2 ++ .../react_embeddable_registry.ts | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/platform/plugins/shared/embeddable/public/plugin.tsx b/src/platform/plugins/shared/embeddable/public/plugin.tsx index 2c9339da363c3..bd5e292a82c35 100644 --- a/src/platform/plugins/shared/embeddable/public/plugin.tsx +++ b/src/platform/plugins/shared/embeddable/public/plugin.tsx @@ -33,6 +33,7 @@ import { } from './bwc/legacy_url_transform'; import { registerDrilldown } from './drilldowns/registry'; import { registerActions } from './ui_actions/register_actions'; +import { closeSetup } from './react_embeddable_system/react_embeddable_registry'; export class EmbeddablePublicPlugin implements Plugin { private stateTransferService: EmbeddableStateTransfer = {} as EmbeddableStateTransfer; @@ -53,6 +54,7 @@ export class EmbeddablePublicPlugin implements Plugin { this.appList = appList; }); diff --git a/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts b/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts index 9693f49d7a9af..0effcde0eb295 100644 --- a/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts +++ b/src/platform/plugins/shared/embeddable/public/react_embeddable_system/react_embeddable_registry.ts @@ -14,6 +14,8 @@ const registry: { [key: string]: () => Promise> } = export const TYPE_REGEX = /^[a-z_]+$/; // lowercase letters and underscores +let isSetupComplete = false; + /** * Registers an embeddable public defintion. This should be called at plugin setup time. * Be sure to register an embeddable server definition for this type. @@ -30,6 +32,13 @@ export const registerEmbeddablePublicDefinition = < type: string, getFactory: () => Promise> ) => { + if (isSetupComplete) + throw new Error( + i18n.translate('embeddableApi.reactEmbeddable.setCompleteError', { + defaultMessage: + 'Embeddables must be registered during plugin setup phase. Do not register embeddables asynchronously', + }) + ); if (registry[type] !== undefined) throw new Error( i18n.translate('embeddableApi.reactEmbeddable.factoryAlreadyExistsError', { @@ -56,3 +65,7 @@ export const getReactEmbeddableFactory = async < ): Promise | undefined> => { return registry[key]?.(); }; + +export function closeSetup() { + isSetupComplete = true; +} From 8a479dc117eacbc9dce18098f1846624500a2a79 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 13:27:23 -0600 Subject: [PATCH 11/25] registerPanelPlacementSettings --- .../plugins/slo/public/plugin.ts | 26 +++++++++++++++++++ .../slo/public/register_embeddables.ts | 23 +--------------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/x-pack/solutions/observability/plugins/slo/public/plugin.ts b/x-pack/solutions/observability/plugins/slo/public/plugin.ts index 0fecb26991b6f..ad226d7e7ed9e 100644 --- a/x-pack/solutions/observability/plugins/slo/public/plugin.ts +++ b/x-pack/solutions/observability/plugins/slo/public/plugin.ts @@ -19,6 +19,7 @@ import { createRepositoryClient } from '@kbn/server-route-repository-client'; import { SLOS_BASE_PATH } from '@kbn/slo-shared-plugin/common/locators/paths'; import { lazy } from 'react'; import { BehaviorSubject } from 'rxjs'; +import { ALL_VALUE } from '@kbn/slo-schema'; import { PLUGIN_NAME, sloAppId } from '../common'; import type { ExperimentalFeatures, SLOConfig } from '../common/config'; import type { SLORouteRepository } from '../server/routes/get_slo_server_route_repository'; @@ -36,6 +37,13 @@ import type { } from './types'; import { SloTelemetryService } from './services/telemetry'; import { getLazyWithContextProviders } from './utils/get_lazy_with_context_providers'; +import { SLO_OVERVIEW_EMBEDDABLE_ID } from '../common/embeddables/overview/constants'; +import type { + GroupOverviewCustomState, + OverviewEmbeddableState, + SingleOverviewCustomState, +} from '../server/lib/embeddables/schema'; +import { SLO_BURN_RATE_EMBEDDABLE_ID } from '../common/embeddables/burn_rate/constants'; export class SLOPlugin implements Plugin @@ -173,6 +181,24 @@ export class SLOPlugin createSLOFlyout: getCreateSLOFormFlyout, }); + // TODO move to registerEmbeddables when PresentationUtilPluginSetup exposes registerPanelPlacementSettings + // https://github.com/elastic/kibana/issues/268287 + plugins.presentationUtil.registerPanelPlacementSettings( + SLO_OVERVIEW_EMBEDDABLE_ID, + (serializedState?: OverviewEmbeddableState) => { + if ( + (serializedState as SingleOverviewCustomState)?.slo_instance_id === ALL_VALUE || + (serializedState as GroupOverviewCustomState)?.group_filters + ) { + return { placementSettings: { width: 24, height: 8 } }; + } + return { placementSettings: { width: 12, height: 8 } }; + } + ); + plugins.presentationUtil.registerPanelPlacementSettings(SLO_BURN_RATE_EMBEDDABLE_ID, () => { + return { placementSettings: { width: 14, height: 7 } }; + }); + return { getCreateSLOFormFlyout, getSLODetailsFlyout, diff --git a/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts b/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts index 01e1df19539c2..5507504a5c098 100644 --- a/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts +++ b/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts @@ -7,17 +7,12 @@ import type { CoreSetup } from '@kbn/core/public'; import type { Reference } from '@kbn/content-management-utils'; import type { DrilldownTransforms } from '@kbn/embeddable-plugin/common'; -import { ALL_VALUE } from '@kbn/slo-schema/src/constants'; import type { AlertsEmbeddableState } from '../server/lib/embeddables/alerts_schema'; import { SLO_ALERTS_EMBEDDABLE_ID } from '../common/embeddables/alerts/constants'; import { SLO_BURN_RATE_EMBEDDABLE_ID } from './embeddable/slo/burn_rate/constants'; import { SLO_ERROR_BUDGET_ID } from './embeddable/slo/error_budget/constants'; import { SLO_OVERVIEW_EMBEDDABLE_ID } from '../common/embeddables/overview/constants'; -import type { - GroupOverviewCustomState, - OverviewEmbeddableState, - SingleOverviewCustomState, -} from '../common/embeddables/overview/types'; +import type { OverviewEmbeddableState } from '../common/embeddables/overview/types'; import { registerSloUiActions } from './ui_actions/register_ui_actions'; import type { SLOPublicPluginsSetup, SLOPublicPluginsStart, SLORepositoryClient } from './types'; @@ -34,22 +29,6 @@ export const registerEmbeddables = ({ sloClient, kibanaVersion, }: RegisterEmbeddablesDeps) => { - plugins.presentationUtil.registerPanelPlacementSettings( - SLO_OVERVIEW_EMBEDDABLE_ID, - (serializedState?: OverviewEmbeddableState) => { - if ( - (serializedState as SingleOverviewCustomState)?.slo_instance_id === ALL_VALUE || - (serializedState as GroupOverviewCustomState)?.group_filters - ) { - return { placementSettings: { width: 24, height: 8 } }; - } - return { placementSettings: { width: 12, height: 8 } }; - } - ); - plugins.presentationUtil.registerPanelPlacementSettings(SLO_BURN_RATE_EMBEDDABLE_ID, () => { - return { placementSettings: { width: 14, height: 7 } }; - }); - plugins.embeddable.registerEmbeddablePublicDefinition(SLO_OVERVIEW_EMBEDDABLE_ID, async () => { const [{ getOverviewEmbeddableFactory }, [coreStart, pluginsStart]] = await Promise.all([ import('./embeddable/slo/overview/slo_embeddable_factory'), From d0ea6b654cd915b60c572c6204c0fd591b83e54a Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 13:29:47 -0600 Subject: [PATCH 12/25] Revert "registerPanelPlacementSettings" This reverts commit 8a479dc117eacbc9dce18098f1846624500a2a79. --- .../plugins/slo/public/plugin.ts | 26 ------------------- .../slo/public/register_embeddables.ts | 23 +++++++++++++++- 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/x-pack/solutions/observability/plugins/slo/public/plugin.ts b/x-pack/solutions/observability/plugins/slo/public/plugin.ts index ad226d7e7ed9e..0fecb26991b6f 100644 --- a/x-pack/solutions/observability/plugins/slo/public/plugin.ts +++ b/x-pack/solutions/observability/plugins/slo/public/plugin.ts @@ -19,7 +19,6 @@ import { createRepositoryClient } from '@kbn/server-route-repository-client'; import { SLOS_BASE_PATH } from '@kbn/slo-shared-plugin/common/locators/paths'; import { lazy } from 'react'; import { BehaviorSubject } from 'rxjs'; -import { ALL_VALUE } from '@kbn/slo-schema'; import { PLUGIN_NAME, sloAppId } from '../common'; import type { ExperimentalFeatures, SLOConfig } from '../common/config'; import type { SLORouteRepository } from '../server/routes/get_slo_server_route_repository'; @@ -37,13 +36,6 @@ import type { } from './types'; import { SloTelemetryService } from './services/telemetry'; import { getLazyWithContextProviders } from './utils/get_lazy_with_context_providers'; -import { SLO_OVERVIEW_EMBEDDABLE_ID } from '../common/embeddables/overview/constants'; -import type { - GroupOverviewCustomState, - OverviewEmbeddableState, - SingleOverviewCustomState, -} from '../server/lib/embeddables/schema'; -import { SLO_BURN_RATE_EMBEDDABLE_ID } from '../common/embeddables/burn_rate/constants'; export class SLOPlugin implements Plugin @@ -181,24 +173,6 @@ export class SLOPlugin createSLOFlyout: getCreateSLOFormFlyout, }); - // TODO move to registerEmbeddables when PresentationUtilPluginSetup exposes registerPanelPlacementSettings - // https://github.com/elastic/kibana/issues/268287 - plugins.presentationUtil.registerPanelPlacementSettings( - SLO_OVERVIEW_EMBEDDABLE_ID, - (serializedState?: OverviewEmbeddableState) => { - if ( - (serializedState as SingleOverviewCustomState)?.slo_instance_id === ALL_VALUE || - (serializedState as GroupOverviewCustomState)?.group_filters - ) { - return { placementSettings: { width: 24, height: 8 } }; - } - return { placementSettings: { width: 12, height: 8 } }; - } - ); - plugins.presentationUtil.registerPanelPlacementSettings(SLO_BURN_RATE_EMBEDDABLE_ID, () => { - return { placementSettings: { width: 14, height: 7 } }; - }); - return { getCreateSLOFormFlyout, getSLODetailsFlyout, diff --git a/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts b/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts index 5507504a5c098..01e1df19539c2 100644 --- a/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts +++ b/x-pack/solutions/observability/plugins/slo/public/register_embeddables.ts @@ -7,12 +7,17 @@ import type { CoreSetup } from '@kbn/core/public'; import type { Reference } from '@kbn/content-management-utils'; import type { DrilldownTransforms } from '@kbn/embeddable-plugin/common'; +import { ALL_VALUE } from '@kbn/slo-schema/src/constants'; import type { AlertsEmbeddableState } from '../server/lib/embeddables/alerts_schema'; import { SLO_ALERTS_EMBEDDABLE_ID } from '../common/embeddables/alerts/constants'; import { SLO_BURN_RATE_EMBEDDABLE_ID } from './embeddable/slo/burn_rate/constants'; import { SLO_ERROR_BUDGET_ID } from './embeddable/slo/error_budget/constants'; import { SLO_OVERVIEW_EMBEDDABLE_ID } from '../common/embeddables/overview/constants'; -import type { OverviewEmbeddableState } from '../common/embeddables/overview/types'; +import type { + GroupOverviewCustomState, + OverviewEmbeddableState, + SingleOverviewCustomState, +} from '../common/embeddables/overview/types'; import { registerSloUiActions } from './ui_actions/register_ui_actions'; import type { SLOPublicPluginsSetup, SLOPublicPluginsStart, SLORepositoryClient } from './types'; @@ -29,6 +34,22 @@ export const registerEmbeddables = ({ sloClient, kibanaVersion, }: RegisterEmbeddablesDeps) => { + plugins.presentationUtil.registerPanelPlacementSettings( + SLO_OVERVIEW_EMBEDDABLE_ID, + (serializedState?: OverviewEmbeddableState) => { + if ( + (serializedState as SingleOverviewCustomState)?.slo_instance_id === ALL_VALUE || + (serializedState as GroupOverviewCustomState)?.group_filters + ) { + return { placementSettings: { width: 24, height: 8 } }; + } + return { placementSettings: { width: 12, height: 8 } }; + } + ); + plugins.presentationUtil.registerPanelPlacementSettings(SLO_BURN_RATE_EMBEDDABLE_ID, () => { + return { placementSettings: { width: 14, height: 7 } }; + }); + plugins.embeddable.registerEmbeddablePublicDefinition(SLO_OVERVIEW_EMBEDDABLE_ID, async () => { const [{ getOverviewEmbeddableFactory }, [coreStart, pluginsStart]] = await Promise.all([ import('./embeddable/slo/overview/slo_embeddable_factory'), From 4382745fb0713d7137d4e163da127a57b3c22d81 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 13:30:28 -0600 Subject: [PATCH 13/25] setup.registerPanelPlacementSettings --- .../plugins/shared/presentation_util/public/plugin.ts | 4 +++- .../plugins/shared/presentation_util/public/types.ts | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/platform/plugins/shared/presentation_util/public/plugin.ts b/src/platform/plugins/shared/presentation_util/public/plugin.ts index 7ef724425aaf8..18ea64171a03e 100644 --- a/src/platform/plugins/shared/presentation_util/public/plugin.ts +++ b/src/platform/plugins/shared/presentation_util/public/plugin.ts @@ -35,7 +35,9 @@ export class PresentationUtilPlugin _coreSetup: CoreSetup, _setupPlugins: PresentationUtilPluginSetupDeps ): PresentationUtilPluginSetup { - return {}; + return { + registerPanelPlacementSettings + }; } public start( diff --git a/src/platform/plugins/shared/presentation_util/public/types.ts b/src/platform/plugins/shared/presentation_util/public/types.ts index 622800666ea48..1097028e42ed9 100644 --- a/src/platform/plugins/shared/presentation_util/public/types.ts +++ b/src/platform/plugins/shared/presentation_util/public/types.ts @@ -16,10 +16,17 @@ import type { } from './registries/panel_placement'; // eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface PresentationUtilPluginSetup {} +export interface PresentationUtilPluginSetup { + registerPanelPlacementSettings: typeof registerPanelPlacementSettings; +} export interface PresentationUtilPluginStart { labsService: PresentationLabsService; + /** + * @deprecated + * + * Use setup.registerPanelPlacementSettings + */ registerPanelPlacementSettings: typeof registerPanelPlacementSettings; getPanelPlacementSettings: typeof getPanelPlacementSettings; } From 529cd33bc5eff486102ce60fc9047afd3657c9a6 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 7 May 2026 20:13:54 +0000 Subject: [PATCH 14/25] Changes from node scripts/eslint_all_files --no-cache --fix --- src/platform/plugins/shared/presentation_util/public/plugin.ts | 2 +- src/platform/plugins/shared/presentation_util/public/types.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/platform/plugins/shared/presentation_util/public/plugin.ts b/src/platform/plugins/shared/presentation_util/public/plugin.ts index 18ea64171a03e..da9b298ddd95d 100644 --- a/src/platform/plugins/shared/presentation_util/public/plugin.ts +++ b/src/platform/plugins/shared/presentation_util/public/plugin.ts @@ -36,7 +36,7 @@ export class PresentationUtilPlugin _setupPlugins: PresentationUtilPluginSetupDeps ): PresentationUtilPluginSetup { return { - registerPanelPlacementSettings + registerPanelPlacementSettings, }; } diff --git a/src/platform/plugins/shared/presentation_util/public/types.ts b/src/platform/plugins/shared/presentation_util/public/types.ts index 1097028e42ed9..da0724bd94b18 100644 --- a/src/platform/plugins/shared/presentation_util/public/types.ts +++ b/src/platform/plugins/shared/presentation_util/public/types.ts @@ -15,7 +15,6 @@ import type { registerPanelPlacementSettings, } from './registries/panel_placement'; -// eslint-disable-next-line @typescript-eslint/no-empty-interface export interface PresentationUtilPluginSetup { registerPanelPlacementSettings: typeof registerPanelPlacementSettings; } From 6479db86331f450d96ee957af123244177f60b9a Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 14:21:09 -0600 Subject: [PATCH 15/25] remove FTR dashboard_panel_listing.ts --- .../group5/dashboard_panel_listing.ts | 77 ------------------- .../functional/apps/dashboard/group5/index.ts | 1 - 2 files changed, 78 deletions(-) delete mode 100644 src/platform/test/functional/apps/dashboard/group5/dashboard_panel_listing.ts diff --git a/src/platform/test/functional/apps/dashboard/group5/dashboard_panel_listing.ts b/src/platform/test/functional/apps/dashboard/group5/dashboard_panel_listing.ts deleted file mode 100644 index 7d4f86b07c845..0000000000000 --- a/src/platform/test/functional/apps/dashboard/group5/dashboard_panel_listing.ts +++ /dev/null @@ -1,77 +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 expect from '@kbn/expect'; - -import type { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService, getPageObjects }: FtrProviderContext) { - const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'settings', 'common']); - const testSubjects = getService('testSubjects'); - const kibanaServer = getService('kibanaServer'); - const dashboardAddPanel = getService('dashboardAddPanel'); - - describe('dashboard panel listing', function () { - this.tags('skipFIPS'); - before(async () => { - await kibanaServer.savedObjects.cleanStandardList(); - await kibanaServer.importExport.load( - 'src/platform/test/functional/fixtures/kbn_archiver/dashboard/current/kibana' - ); - await kibanaServer.uiSettings.replace({ - defaultIndex: '0bf35f60-3dc9-11e8-8660-4d65aa086b3c', - }); - }); - - after(async () => { - await kibanaServer.savedObjects.cleanStandardList(); - }); - - it('renders a panel with predefined order of panel groups and panels', async () => { - await PageObjects.dashboard.navigateToApp(); - await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.switchToEditMode(); - - await dashboardAddPanel.openAddPanelFlyout(); - - const panelSelectionFlyout = await testSubjects.find('dashboardPanelSelectionFlyout'); - const panelGroupByOrder = new Map(); - const panelGroups = await panelSelectionFlyout.findAllByCssSelector( - '[data-test-subj*="dashboardEditorMenu-"]' - ); - const panelTypes = await panelSelectionFlyout.findAllByCssSelector( - '[data-test-subj*="create-action-"]' - ); - - for (let i = 0; i < panelGroups.length; i++) { - const panelGroup = panelGroups[i]; - const order = await panelGroup.getAttribute('data-group-sort-order'); - // @ts-ignore - const [, panelGroupTitle] = (await panelGroup.getAttribute('data-test-subj'))?.match( - /dashboardEditorMenu-(.*)/ - ); - - panelGroupByOrder.set(order, panelGroupTitle); - } - - expect(panelGroupByOrder.size).to.eql(5); - - expect([...panelGroupByOrder.values()]).to.eql([ - 'visualizationsGroup', - 'controlsGroup', - 'annotation-and-navigationGroup', - 'observabilityGroup', - 'legacyGroup', - ]); - - // Any changes to the number of panels needs to be audited by @elastic/kibana-presentation - expect(panelTypes.length).to.eql(17); - }); - }); -} diff --git a/src/platform/test/functional/apps/dashboard/group5/index.ts b/src/platform/test/functional/apps/dashboard/group5/index.ts index 3b30b98fe4026..115e7ed2d1713 100644 --- a/src/platform/test/functional/apps/dashboard/group5/index.ts +++ b/src/platform/test/functional/apps/dashboard/group5/index.ts @@ -39,7 +39,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./dashboard_settings')); loadTestFile(require.resolve('./data_shared_attributes')); loadTestFile(require.resolve('./dashboard_back_button')); - loadTestFile(require.resolve('./dashboard_panel_listing')); // Note: This one must be last because it unloads some data for one of its tests! // No, this isn't ideal, but loading/unloading takes so much time and these are all bunched From 2e644a412595c6c8781695bb6420c6767c2cc914 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 14:34:57 -0600 Subject: [PATCH 16/25] sync register links embeddable --- .../plugins/private/links/public/mocks.ts | 4 - .../plugins/private/links/public/plugin.ts | 166 +++++++++--------- .../links/public/services/kibana_services.ts | 7 - 3 files changed, 81 insertions(+), 96 deletions(-) diff --git a/src/platform/plugins/private/links/public/mocks.ts b/src/platform/plugins/private/links/public/mocks.ts index 674ee581efc40..eb52becefb2f5 100644 --- a/src/platform/plugins/private/links/public/mocks.ts +++ b/src/platform/plugins/private/links/public/mocks.ts @@ -11,8 +11,6 @@ import { coreMock } from '@kbn/core/public/mocks'; import { dashboardPluginMock } from '@kbn/dashboard-plugin/public/mocks'; import { embeddablePluginMock } from '@kbn/embeddable-plugin/public/mocks'; import { contentManagementMock } from '@kbn/content-management-plugin/public/mocks'; -import { presentationUtilPluginMock } from '@kbn/presentation-util-plugin/public/mocks'; -import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks'; import { BehaviorSubject } from 'rxjs'; import { getMockPresentationContainer } from '@kbn/presentation-publishing/interfaces/containers/mocks'; import type { AggregateQuery, Filter, Query, TimeRange } from '@kbn/es-query'; @@ -40,8 +38,6 @@ export const setStubKibanaServices = () => { dashboard: dashboardPluginMock.createStartContract(), embeddable: embeddablePluginMock.createStartContract(), contentManagement: contentManagementMock.createStartContract(), - presentationUtil: presentationUtilPluginMock.createStartContract(), - uiActions: uiActionsPluginMock.createStartContract(), }); }; diff --git a/src/platform/plugins/private/links/public/plugin.ts b/src/platform/plugins/private/links/public/plugin.ts index a19c3141d7895..7b7cc7eabf96e 100644 --- a/src/platform/plugins/private/links/public/plugin.ts +++ b/src/platform/plugins/private/links/public/plugin.ts @@ -15,11 +15,11 @@ import type { import type { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; import type { DashboardStart } from '@kbn/dashboard-plugin/public'; import type { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public'; -import type { PresentationUtilPluginStart } from '@kbn/presentation-util-plugin/public'; +import type { PresentationUtilPluginSetup } from '@kbn/presentation-util-plugin/public'; import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; import type { VisualizationsSetup } from '@kbn/visualizations-plugin/public'; -import type { UiActionsPublicStart } from '@kbn/ui-actions-plugin/public/plugin'; +import type { UiActionsPublicSetup } from '@kbn/ui-actions-plugin/public/plugin'; import { ADD_PANEL_TRIGGER } from '@kbn/ui-actions-plugin/common/trigger_ids'; import type { LinksEmbeddableState } from '../common'; import { @@ -39,14 +39,14 @@ export interface LinksSetupDependencies { embeddable: EmbeddableSetup; visualizations: VisualizationsSetup; contentManagement: ContentManagementPublicSetup; + presentationUtil: PresentationUtilPluginSetup; + uiActions: UiActionsPublicSetup; } export interface LinksStartDependencies { embeddable: EmbeddableStart; dashboard: DashboardStart; - presentationUtil: PresentationUtilPluginStart; contentManagement: ContentManagementPublicStart; - uiActions: UiActionsPublicStart; usageCollection?: UsageCollectionStart; } @@ -56,93 +56,85 @@ export class LinksPlugin constructor() {} public setup(core: CoreSetup, plugins: LinksSetupDependencies) { - core.getStartServices().then(([_, deps]) => { - plugins.contentManagement.registry.register({ - id: CONTENT_ID, - version: { - latest: LATEST_VERSION, - }, - name: APP_NAME, - }); - - plugins.embeddable.registerAddFromLibraryType({ - onAdd: async (container, savedObject) => { - container.addNewPanel( - { - panelType: LINKS_EMBEDDABLE_TYPE, - serializedState: { - ref_id: savedObject.id, - }, + plugins.contentManagement.registry.register({ + id: CONTENT_ID, + version: { + latest: LATEST_VERSION, + }, + name: APP_NAME, + }); + + plugins.embeddable.registerAddFromLibraryType({ + onAdd: async (container, savedObject) => { + container.addNewPanel( + { + panelType: LINKS_EMBEDDABLE_TYPE, + serializedState: { + ref_id: savedObject.id, }, - { - displaySuccessMessage: true, + }, + { + displaySuccessMessage: true, + } + ); + }, + savedObjectType: LINKS_SAVED_OBJECT_TYPE, + savedObjectName: APP_NAME, + getIconForSavedObject: () => APP_ICON, + }); + + plugins.embeddable.registerEmbeddablePublicDefinition(LINKS_EMBEDDABLE_TYPE, async () => { + const { getLinksEmbeddableFactory } = await import('./embeddable/links_embeddable'); + return getLinksEmbeddableFactory(); + }); + + plugins.embeddable.registerLegacyURLTransform(LINKS_EMBEDDABLE_TYPE, async () => { + const { transformOut } = await import('../common/embeddable/transforms/transform_out'); + return transformOut; + }); + + plugins.visualizations.registerAlias({ + disableCreate: true, // do not allow creation through visualization listing page + name: CONTENT_ID, + title: APP_NAME, + icon: APP_ICON, + description: i18n.translate('links.description', { + defaultMessage: 'Use links to navigate to commonly used dashboards and websites.', + }), + stage: 'production', + appExtensions: { + visualizations: { + docTypes: [CONTENT_ID], + searchFields: ['title^3'], + client: getLinksClient, + toListItem( + linkItem: Omit & { + attributes: { title: string; description?: string }; } - ); - }, - savedObjectType: LINKS_SAVED_OBJECT_TYPE, - savedObjectName: APP_NAME, - getIconForSavedObject: () => APP_ICON, - }); - - plugins.embeddable.registerEmbeddablePublicDefinition(LINKS_EMBEDDABLE_TYPE, async () => { - const { getLinksEmbeddableFactory } = await import('./embeddable/links_embeddable'); - return getLinksEmbeddableFactory(); - }); - - plugins.embeddable.registerLegacyURLTransform(LINKS_EMBEDDABLE_TYPE, async () => { - const { transformOut } = await import('../common/embeddable/transforms/transform_out'); - return transformOut; - }); - - plugins.visualizations.registerAlias({ - disableCreate: true, // do not allow creation through visualization listing page - name: CONTENT_ID, - title: APP_NAME, - icon: APP_ICON, - description: i18n.translate('links.description', { - defaultMessage: 'Use links to navigate to commonly used dashboards and websites.', - }), - stage: 'production', - appExtensions: { - visualizations: { - docTypes: [CONTENT_ID], - searchFields: ['title^3'], - client: getLinksClient, - toListItem( - linkItem: Omit & { - attributes: { title: string; description?: string }; - } - ) { - const { id, type, updatedAt, attributes } = linkItem; - const { title, description } = attributes; - - return { - id, - title, - editor: { - onEdit: async (refId: string) => { - const { onVisualizationsEdit } = await import( - './editor/on_visualizations_edit' - ); - onVisualizationsEdit(refId); - }, + ) { + const { id, type, updatedAt, attributes } = linkItem; + const { title, description } = attributes; + + return { + id, + title, + editor: { + onEdit: async (refId: string) => { + const { onVisualizationsEdit } = await import('./editor/on_visualizations_edit'); + onVisualizationsEdit(refId); }, - description, - updatedAt, - icon: APP_ICON, - typeTitle: APP_NAME, - stage: 'production', - savedObjectType: type, - }; - }, + }, + description, + updatedAt, + icon: APP_ICON, + typeTitle: APP_NAME, + stage: 'production', + savedObjectType: type, + }; }, }, - }); + }, }); - } - - public start(core: CoreStart, plugins: LinksStartDependencies) { - setKibanaServices(core, plugins); plugins.uiActions.addTriggerActionAsync( ADD_PANEL_TRIGGER, @@ -161,6 +153,10 @@ export class LinksPlugin return { placementSettings }; } ); + } + + public start(core: CoreStart, plugins: LinksStartDependencies) { + setKibanaServices(core, plugins); return {}; } diff --git a/src/platform/plugins/private/links/public/services/kibana_services.ts b/src/platform/plugins/private/links/public/services/kibana_services.ts index de62446cb32e9..4f2c05592ea5e 100644 --- a/src/platform/plugins/private/links/public/services/kibana_services.ts +++ b/src/platform/plugins/private/links/public/services/kibana_services.ts @@ -13,18 +13,13 @@ import type { ContentManagementPublicStart } from '@kbn/content-management-plugi import type { CoreStart } from '@kbn/core/public'; import type { DashboardStart } from '@kbn/dashboard-plugin/public'; import type { EmbeddableStart } from '@kbn/embeddable-plugin/public'; -import type { PresentationUtilPluginStart } from '@kbn/presentation-util-plugin/public'; - -import type { UiActionsPublicStart } from '@kbn/ui-actions-plugin/public/plugin'; import { CONTENT_ID } from '../../common'; import type { LinksStartDependencies } from '../plugin'; export let coreServices: CoreStart; export let dashboardServices: DashboardStart; export let embeddableService: EmbeddableStart; -export let presentationUtil: PresentationUtilPluginStart; export let contentManagement: ContentManagementPublicStart; -export let uiActions: UiActionsPublicStart; export let trackUiMetric: ( type: string, eventNames: string | string[], @@ -49,9 +44,7 @@ export const setKibanaServices = (kibanaCore: CoreStart, deps: LinksStartDepende coreServices = kibanaCore; dashboardServices = deps.dashboard; embeddableService = deps.embeddable; - presentationUtil = deps.presentationUtil; contentManagement = deps.contentManagement; - uiActions = deps.uiActions; if (deps.usageCollection) trackUiMetric = deps.usageCollection.reportUiCounter.bind(deps.usageCollection, CONTENT_ID); From ab0495191ffe31bb16c8b93ce4aef0e7fe47a4d8 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 14:43:32 -0600 Subject: [PATCH 17/25] async import apm --- .../embeddable/register_embeddables.tsx | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/x-pack/solutions/observability/plugins/apm/public/embeddable/register_embeddables.tsx b/x-pack/solutions/observability/plugins/apm/public/embeddable/register_embeddables.tsx index 88e6f714671ab..b35a83e60f2d0 100644 --- a/x-pack/solutions/observability/plugins/apm/public/embeddable/register_embeddables.tsx +++ b/x-pack/solutions/observability/plugins/apm/public/embeddable/register_embeddables.tsx @@ -18,27 +18,28 @@ import { APM_SERVICE_MAP_EMBEDDABLE, } from './service_map/constants'; -export async function registerEmbeddables( - deps: Omit -) { +export function registerEmbeddables(deps: Omit) { const coreSetup = deps.coreSetup as CoreSetup; const pluginsSetup = deps.pluginsSetup; - const [coreStart, pluginsStart] = await coreSetup.getStartServices(); const registerEmbeddablePublicDefinition = pluginsSetup.embeddable.registerEmbeddablePublicDefinition; registerEmbeddablePublicDefinition(APM_ALERTING_LATENCY_CHART_EMBEDDABLE, async () => { - const { getApmAlertingLatencyChartEmbeddableFactory } = await import( - './alerting/alerting_latency_chart/react_embeddable_factory' - ); + const [{ getApmAlertingLatencyChartEmbeddableFactory }, [coreStart, pluginsStart]] = + await Promise.all([ + import('./alerting/alerting_latency_chart/react_embeddable_factory'), + coreSetup.getStartServices(), + ]); return getApmAlertingLatencyChartEmbeddableFactory({ ...deps, coreStart, pluginsStart }); }); registerEmbeddablePublicDefinition(APM_ALERTING_THROUGHPUT_CHART_EMBEDDABLE, async () => { - const { getApmAlertingThroughputChartEmbeddableFactory } = await import( - './alerting/alerting_throughput_chart/react_embeddable_factory' - ); + const [{ getApmAlertingThroughputChartEmbeddableFactory }, [coreStart, pluginsStart]] = + await Promise.all([ + import('./alerting/alerting_throughput_chart/react_embeddable_factory'), + coreSetup.getStartServices(), + ]); return getApmAlertingThroughputChartEmbeddableFactory({ ...deps, coreStart, pluginsStart }); }); @@ -46,9 +47,13 @@ export async function registerEmbeddables( registerEmbeddablePublicDefinition( APM_ALERTING_FAILED_TRANSACTIONS_CHART_EMBEDDABLE, async () => { - const { getApmAlertingFailedTransactionsChartEmbeddableFactory } = await import( - './alerting/alerting_failed_transactions_chart/react_embeddable_factory' - ); + const [ + { getApmAlertingFailedTransactionsChartEmbeddableFactory }, + [coreStart, pluginsStart], + ] = await Promise.all([ + import('./alerting/alerting_failed_transactions_chart/react_embeddable_factory'), + coreSetup.getStartServices(), + ]); return getApmAlertingFailedTransactionsChartEmbeddableFactory({ ...deps, @@ -59,9 +64,10 @@ export async function registerEmbeddables( ); registerEmbeddablePublicDefinition(APM_SERVICE_MAP_EMBEDDABLE, async () => { - const { getServiceMapEmbeddableFactory } = await import( - './service_map/service_map_embeddable_factory' - ); + const [{ getServiceMapEmbeddableFactory }, [coreStart, pluginsStart]] = await Promise.all([ + import('./service_map/service_map_embeddable_factory'), + coreSetup.getStartServices(), + ]); return getServiceMapEmbeddableFactory({ ...deps, coreStart, pluginsStart }); }); @@ -70,9 +76,10 @@ export async function registerEmbeddables( ADD_PANEL_TRIGGER, ADD_APM_SERVICE_MAP_PANEL_ACTION_ID, async () => { - const { createAddServiceMapPanelAction } = await import( - './service_map/create_add_service_map_panel_action' - ); + const [{ createAddServiceMapPanelAction }, [coreStart, pluginsStart]] = await Promise.all([ + import('./service_map/create_add_service_map_panel_action'), + coreSetup.getStartServices(), + ]); return createAddServiceMapPanelAction({ ...deps, coreStart, pluginsStart }); } ); From 32990f8f18204711ecb32b2f499ff1ddcf4ce60b Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 14:57:48 -0600 Subject: [PATCH 18/25] remove async import --- .../observability/plugins/apm/public/plugin.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/x-pack/solutions/observability/plugins/apm/public/plugin.ts b/x-pack/solutions/observability/plugins/apm/public/plugin.ts index 7f0b64f2264a0..9f389b7010035 100644 --- a/x-pack/solutions/observability/plugins/apm/public/plugin.ts +++ b/x-pack/solutions/observability/plugins/apm/public/plugin.ts @@ -108,6 +108,7 @@ import { TelemetryService } from './services/telemetry'; import { createLazyFocusedTraceWaterfallRenderer } from './components/shared/focused_trace_waterfall/lazy_create_focused_trace_waterfall_renderer'; import { createLazyFullTraceWaterfallRenderer } from './components/shared/trace_waterfall/lazy_create_full_trace_waterfall_renderer'; import type { ApmCoreSetup } from './components/alerting/utils/create_lazy_component_with_context'; +import { registerEmbeddables } from './embeddable/register_embeddables'; export type ApmPluginSetup = ReturnType; export type ApmPluginStart = ReturnType; @@ -515,15 +516,13 @@ export class ApmPlugin implements Plugin { registerApmRuleTypes(observabilityRuleTypeRegistry, core as ApmCoreSetup); } ); - import('./embeddable/register_embeddables').then(({ registerEmbeddables }) => { - registerEmbeddables({ - coreSetup: core, - pluginsSetup: plugins, - config, - kibanaEnvironment, - observabilityRuleTypeRegistry, - telemetry, - }); + registerEmbeddables({ + coreSetup: core, + pluginsSetup: plugins, + config, + kibanaEnvironment, + observabilityRuleTypeRegistry, + telemetry, }); const locator = plugins.share.url.locators.create(new APMServiceDetailLocator(core.uiSettings)); From df58b192ba2f98644b224a0270a30a9e8d2a664c Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 16:27:27 -0600 Subject: [PATCH 19/25] setup test to see what values are returned --- .../scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts index 171b46433c032..bf569f14129d6 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts @@ -93,6 +93,7 @@ spaceTest.describe( await spaceTest.step('verify total panel count', async () => { const addPanelActions = await pageObjects.dashboard.getAddPanelFlyoutActions(); log.debug(`Add panel actions: ${addPanelActions.join(',')}`); + expect(addPanelActions).toStrictEqual([]); expect(addPanelActions).toHaveLength(expectedCount); }); }); From a0476916b66d122ef54855ef679c2796cb0ced19 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 18:32:58 -0600 Subject: [PATCH 20/25] include values in error message --- .../ui/parallel_tests/dashboard_add_panel_flyout.spec.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts index bf569f14129d6..d2d7f0e3eb2bc 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts @@ -93,8 +93,11 @@ spaceTest.describe( await spaceTest.step('verify total panel count', async () => { const addPanelActions = await pageObjects.dashboard.getAddPanelFlyoutActions(); log.debug(`Add panel actions: ${addPanelActions.join(',')}`); - expect(addPanelActions).toStrictEqual([]); - expect(addPanelActions).toHaveLength(expectedCount); + try { + expect(addPanelActions).toHaveLength(expectedCount); + } catch (error) { + throw new Error(`${error.message}, values: ${addPanelActions.join(',')}`) + } }); }); } From b7d40dad06a0e0b9ff678597627036110108d58a Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 8 May 2026 00:54:52 +0000 Subject: [PATCH 21/25] Changes from node scripts/eslint_all_files --no-cache --fix --- .../scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts index d2d7f0e3eb2bc..9d83468cae69d 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts @@ -96,7 +96,7 @@ spaceTest.describe( try { expect(addPanelActions).toHaveLength(expectedCount); } catch (error) { - throw new Error(`${error.message}, values: ${addPanelActions.join(',')}`) + throw new Error(`${error.message}, values: ${addPanelActions.join(',')}`); } }); }); From 646514a09105530d21a9f55d912b6166e0022f3a Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 19:21:14 -0600 Subject: [PATCH 22/25] update expects --- .../dashboard_add_panel_flyout.spec.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts index 9d83468cae69d..a8fe34401883e 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts @@ -13,7 +13,21 @@ import { expect } from '@kbn/scout/ui'; import { DASHBOARD_DEFAULT_INDEX_TITLE, DASHBOARD_SAVED_SEARCH_ARCHIVE } from '../constants'; const getExpected = (config: ScoutTestConfig) => { - if (config.projectType === 'es' || config.projectType === 'security') { + if (config.projectType === 'es') { + return { + groups: [ + 'visualizationsGroup', + 'controlsGroup', + 'annotation-and-navigationGroup', + 'logs-aiopsGroup', + 'mlGroup', + 'legacyGroup', + ], + count: 17, + }; + } + + if (config.projectType === 'security') { return { groups: [ 'visualizationsGroup', From 2931dd1342d2cc5caf5d749030e446744f24fb00 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 7 May 2026 19:21:48 -0600 Subject: [PATCH 23/25] eslint --- .../scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts index a8fe34401883e..0b0cb8a8b94a6 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts @@ -26,7 +26,7 @@ const getExpected = (config: ScoutTestConfig) => { count: 17, }; } - + if (config.projectType === 'security') { return { groups: [ From 00fa8ea1f499bae279919e274da2a2a36bb2911f Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 8 May 2026 08:16:22 -0600 Subject: [PATCH 24/25] clean up test --- .../ui/parallel_tests/dashboard_add_panel_flyout.spec.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts index 0b0cb8a8b94a6..5903222202392 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/ui/parallel_tests/dashboard_add_panel_flyout.spec.ts @@ -106,12 +106,8 @@ spaceTest.describe( await spaceTest.step('verify total panel count', async () => { const addPanelActions = await pageObjects.dashboard.getAddPanelFlyoutActions(); - log.debug(`Add panel actions: ${addPanelActions.join(',')}`); - try { - expect(addPanelActions).toHaveLength(expectedCount); - } catch (error) { - throw new Error(`${error.message}, values: ${addPanelActions.join(',')}`); - } + log.info(`Add panel actions: ${addPanelActions.join(',')}`); + expect(addPanelActions).toHaveLength(expectedCount); }); }); } From 818c48089f10d4c44e0dd570e247a134b434c420 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 8 May 2026 08:29:51 -0600 Subject: [PATCH 25/25] limits --- packages/kbn-optimizer/limits.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index d668f0fdc4227..1d95e48af3304 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -9,7 +9,7 @@ pageLoadAssetSize: aiops: 15227 alerting: 22371 alertingVTwo: 76778 - apm: 27979 + apm: 28027 apmSourcesAccess: 2278 automaticImport: 18629 banners: 4006