Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
69ccde4
[aiops] synchronously register embeddables and actions to fix flaky a…
nreese May 7, 2026
b8afc16
unskip test
nreese May 7, 2026
336c9f5
update expects
nreese May 7, 2026
54ba095
cleanu
nreese May 7, 2026
b007923
log actions
nreese May 7, 2026
570d2bb
slo
nreese May 7, 2026
fd9fae8
clean up
nreese May 7, 2026
fec79a1
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine May 7, 2026
66f97b3
Merge branch 'main' into aiops_sync_registration
nreese May 7, 2026
f39a253
revert embeddable check
nreese May 7, 2026
4e85d9b
Revert "revert embeddable check"
nreese May 7, 2026
8a479dc
registerPanelPlacementSettings
nreese May 7, 2026
d0ea6b6
Revert "registerPanelPlacementSettings"
nreese May 7, 2026
4382745
setup.registerPanelPlacementSettings
nreese May 7, 2026
529cd33
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine May 7, 2026
6479db8
remove FTR dashboard_panel_listing.ts
nreese May 7, 2026
2e644a4
sync register links embeddable
nreese May 7, 2026
ab04951
async import apm
nreese May 7, 2026
32990f8
remove async import
nreese May 7, 2026
df58b19
setup test to see what values are returned
nreese May 7, 2026
a047691
include values in error message
nreese May 8, 2026
b7d40da
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine May 8, 2026
d1ea476
Merge branch 'main' into aiops_sync_registration
nreese May 8, 2026
646514a
update expects
nreese May 8, 2026
2931dd1
eslint
nreese May 8, 2026
55e7b81
merge with main
nreese May 8, 2026
00fa8ea
clean up test
nreese May 8, 2026
818c480
limits
nreese May 8, 2026
4b7ab2b
Merge branch 'main' into aiops_sync_registration
nreese May 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/kbn-optimizer/limits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pageLoadAssetSize:
aiops: 15227
alerting: 22371
alertingVTwo: 76778
apm: 27979
apm: 28027
Copy link
Copy Markdown
Contributor Author

@nreese nreese May 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Increase expected because plugin was async importing ./embeddable/register_embeddables during setup method. This PR replaced the async import with a sync import to better reflect the actual page load metrics

apmSourcesAccess: 2278
automaticImport: 18629
banners: 4006
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -504,8 +504,19 @@ export class DashboardApp {
);
}

async getAddPanelFlyoutPanelTypesCount(): Promise<number> {
return this.panelSelectionFlyout.locator('[data-test-subj*="create-action-"]').count();
async getAddPanelFlyoutActions(): Promise<string[]> {
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] ?? '';
})
);
}

/**
Expand Down
4 changes: 0 additions & 4 deletions src/platform/plugins/private/links/public/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -40,8 +38,6 @@ export const setStubKibanaServices = () => {
dashboard: dashboardPluginMock.createStartContract(),
embeddable: embeddablePluginMock.createStartContract(),
contentManagement: contentManagementMock.createStartContract(),
presentationUtil: presentationUtilPluginMock.createStartContract(),
uiActions: uiActionsPluginMock.createStartContract(),
});
};

Expand Down
166 changes: 81 additions & 85 deletions src/platform/plugins/private/links/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
}

Expand All @@ -56,93 +56,85 @@ export class LinksPlugin
constructor() {}

public setup(core: CoreSetup<LinksStartDependencies>, plugins: LinksSetupDependencies) {
core.getStartServices().then(([_, deps]) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great to see this removed. No reason to get start contracts when they aren't used.

plugins.contentManagement.registry.register({
id: CONTENT_ID,
version: {
latest: LATEST_VERSION,
},
name: APP_NAME,
});

plugins.embeddable.registerAddFromLibraryType({
onAdd: async (container, savedObject) => {
container.addNewPanel<LinksEmbeddableState>(
{
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<LinksEmbeddableState>(
{
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<LinksCrudTypes['Item'], 'attributes'> & {
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<LinksCrudTypes['Item'], 'attributes'> & {
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,
Expand All @@ -161,6 +153,10 @@ export class LinksPlugin
return { placementSettings };
}
);
}

public start(core: CoreStart, plugins: LinksStartDependencies) {
setKibanaServices(core, plugins);

return {};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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[],
Expand All @@ -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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,28 @@ 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,
Copy link
Copy Markdown
Contributor Author

@nreese nreese May 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#267977 changed capabilities check from canGetMlInfo to canGetJobs which resulted in ML add panel actions not getting displayed in serverless es config. Confirmed with ML team that these changes are the correct behavior and the expect clause should be updated.

};
}

if (config.projectType === 'security') {
return {
groups: [
'visualizationsGroup',
'controlsGroup',
'annotation-and-navigationGroup',
'logs-aiopsGroup',
'mlGroup',
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated expects because aiops is rendered before ml once race condition is resolved. These 2 groups both specify order of 0

Image

'legacyGroup',
],
count: 20,
Expand All @@ -32,8 +46,8 @@ const getExpected = (config: ScoutTestConfig) => {
'visualizationsGroup',
'controlsGroup',
'annotation-and-navigationGroup',
'mlGroup',
'logs-aiopsGroup',
'mlGroup',
'observabilityGroup',
'legacyGroup',
],
Expand All @@ -47,8 +61,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: [
Expand Down Expand Up @@ -80,7 +93,7 @@ spaceTest.describe.skip(
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();
Expand All @@ -92,7 +105,9 @@ spaceTest.describe.skip(
});

await spaceTest.step('verify total panel count', async () => {
expect(await pageObjects.dashboard.getAddPanelFlyoutPanelTypesCount()).toBe(expectedCount);
const addPanelActions = await pageObjects.dashboard.getAddPanelFlyoutActions();
log.info(`Add panel actions: ${addPanelActions.join(',')}`);
expect(addPanelActions).toHaveLength(expectedCount);
});
});
}
Expand Down
2 changes: 2 additions & 0 deletions src/platform/plugins/shared/embeddable/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<EmbeddableSetup, EmbeddableStart> {
private stateTransferService: EmbeddableStateTransfer = {} as EmbeddableStateTransfer;
Expand All @@ -53,6 +54,7 @@ export class EmbeddablePublicPlugin implements Plugin<EmbeddableSetup, Embeddabl
}

public start(core: CoreStart, deps: EmbeddableStartDependencies): EmbeddableStart {
closeSetup();
this.appListSubscription = core.application.applications$.subscribe((appList) => {
this.appList = appList;
});
Expand Down
Loading
Loading