Skip to content

Commit

Permalink
[controls] lazy load control actions (elastic#206876)
Browse files Browse the repository at this point in the history
* register control actions with async method
* move floating actions into controls plugin
* replace `PANEL_HOVER_TRIGGER` => `CONTROL_HOVER_TRIGGER`
* Load controls in single chunk
<img width="400" alt="Screenshot 2025-01-16 at 11 40 08 AM"
src="https://github.com/user-attachments/assets/3171c9bf-26bc-4c07-950d-c35603cfb65a"
/>

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
3 people authored and cqliu1 committed Jan 21, 2025
1 parent e11f42e commit f7a275e
Show file tree
Hide file tree
Showing 35 changed files with 203 additions and 231 deletions.
6 changes: 3 additions & 3 deletions packages/kbn-optimizer/limits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pageLoadAssetSize:
cloudSecurityPosture: 34398
console: 61298
contentManagement: 16254
controls: 60000
controls: 12000
core: 564663
crossClusterReplication: 65408
customIntegrations: 22034
Expand All @@ -37,7 +37,7 @@ pageLoadAssetSize:
discover: 99999
discoverEnhanced: 42730
discoverShared: 17111
embeddable: 87309
embeddable: 24000
embeddableEnhanced: 22107
enterpriseSearch: 66810
entityManager: 17175
Expand Down Expand Up @@ -123,7 +123,7 @@ pageLoadAssetSize:
osquery: 107090
painlessLab: 179748
presentationPanel: 11468
presentationUtil: 33186
presentationUtil: 25000
productDocBase: 22500
profiling: 36694
remoteClusters: 51327
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ export {
contextMenuTrigger,
CONTEXT_MENU_TRIGGER,
panelBadgeTrigger,
panelHoverTrigger,
panelNotificationTrigger,
PANEL_BADGE_TRIGGER,
PANEL_HOVER_TRIGGER,
PANEL_NOTIFICATION_TRIGGER,
} from './triggers';
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,6 @@ export const contextMenuTrigger: Trigger = {
}),
};

export const PANEL_HOVER_TRIGGER = 'PANEL_HOVER_TRIGGER';
export const panelHoverTrigger: Trigger = {
id: PANEL_HOVER_TRIGGER,
title: i18n.translate('presentationPanel.hoverTrigger.title', {
defaultMessage: 'Panel hover',
}),
description: i18n.translate('presentationPanel.hoverTrigger.description', {
defaultMessage: "A new action will be added to the panel's hover menu",
}),
};

export const PANEL_BADGE_TRIGGER = 'PANEL_BADGE_TRIGGER';
export const panelBadgeTrigger: Trigger = {
id: PANEL_BADGE_TRIGGER,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,43 @@ import React, { SyntheticEvent } from 'react';

import { EuiButtonIcon, EuiToolTip } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import type { EmbeddableApiContext, HasUniqueId } from '@kbn/presentation-publishing';
import {
apiCanAccessViewMode,
apiHasParentApi,
apiHasType,
apiHasUniqueId,
apiIsOfType,
HasParentApi,
type EmbeddableApiContext,
type HasUniqueId,
HasType,
} from '@kbn/presentation-publishing';
import {
IncompatibleActionError,
FrequentCompatibilityChangeAction,
type Action,
} from '@kbn/ui-actions-plugin/public';
import { isClearableControl } from '../types';
import { PresentationContainer, apiIsPresentationContainer } from '@kbn/presentation-containers';
import { CONTROL_GROUP_TYPE } from '../../common';
import { CanClearSelections, isClearableControl } from '../types';

import { ACTION_CLEAR_CONTROL } from './constants';

type ClearControlActionApi = HasType &
HasUniqueId &
CanClearSelections &
HasParentApi<PresentationContainer & HasType>;

import { ACTION_CLEAR_CONTROL } from '.';
const compatibilityCheck = (api: unknown | null): api is ClearControlActionApi =>
Boolean(
apiHasType(api) &&
apiHasUniqueId(api) &&
isClearableControl(api) &&
apiHasParentApi(api) &&
apiCanAccessViewMode(api.parentApi) &&
apiIsOfType(api.parentApi, CONTROL_GROUP_TYPE) &&
apiIsPresentationContainer(api.parentApi)
);

export class ClearControlAction
implements Action<EmbeddableApiContext>, FrequentCompatibilityChangeAction<EmbeddableApiContext>
Expand Down Expand Up @@ -73,12 +101,10 @@ export class ClearControlAction
}

public async isCompatible({ embeddable }: EmbeddableApiContext) {
const { isCompatible } = await import('./clear_control_action_compatibility_check');
return isCompatible(embeddable);
return compatibilityCheck(embeddable);
}

public async execute({ embeddable }: EmbeddableApiContext) {
const { compatibilityCheck } = await import('./clear_control_action_compatibility_check');
if (!compatibilityCheck(embeddable)) throw new IncompatibleActionError();

embeddable.clearSelections();
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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 { i18n } from '@kbn/i18n';
import { Trigger } from '@kbn/ui-actions-plugin/public';

export const CONTROL_HOVER_TRIGGER = 'CONTROL_HOVER_TRIGGER';
export const controlHoverTrigger: Trigger = {
id: CONTROL_HOVER_TRIGGER,
title: i18n.translate('controls.hoverTrigger.title', {
defaultMessage: 'Control hover',
}),
description: i18n.translate('controls.hoverTrigger.description', {
defaultMessage: "Add action to controls's hover menu",
}),
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,40 @@ import React from 'react';

import { EuiButtonIcon, EuiToolTip } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import type { HasUniqueId, EmbeddableApiContext } from '@kbn/presentation-publishing';
import {
type HasUniqueId,
type EmbeddableApiContext,
type HasType,
type HasParentApi,
type PublishesViewMode,
apiHasType,
apiHasUniqueId,
apiHasParentApi,
apiCanAccessViewMode,
apiIsOfType,
getInheritedViewMode,
} from '@kbn/presentation-publishing';
import { IncompatibleActionError, type Action } from '@kbn/ui-actions-plugin/public';

import { ACTION_DELETE_CONTROL } from '.';
import { PresentationContainer, apiIsPresentationContainer } from '@kbn/presentation-containers';
import { CONTROL_GROUP_TYPE } from '../../common';
import { ACTION_DELETE_CONTROL } from './constants';
import { coreServices } from '../services/kibana_services';

type DeleteControlActionApi = HasType &
HasUniqueId &
HasParentApi<PresentationContainer & PublishesViewMode & HasType>;

export const compatibilityCheck = (api: unknown | null): api is DeleteControlActionApi =>
Boolean(
apiHasType(api) &&
apiHasUniqueId(api) &&
apiHasParentApi(api) &&
apiCanAccessViewMode(api.parentApi) &&
apiIsOfType(api.parentApi, CONTROL_GROUP_TYPE) &&
apiIsPresentationContainer(api.parentApi)
);

export class DeleteControlAction implements Action<EmbeddableApiContext> {
public readonly type = ACTION_DELETE_CONTROL;
public readonly id = ACTION_DELETE_CONTROL;
Expand Down Expand Up @@ -49,12 +77,10 @@ export class DeleteControlAction implements Action<EmbeddableApiContext> {
}

public async isCompatible({ embeddable }: EmbeddableApiContext) {
const { isCompatible } = await import('./delete_control_action_compatibility_check');
return isCompatible(embeddable);
return compatibilityCheck(embeddable) && getInheritedViewMode(embeddable.parentApi) === 'edit';
}

public async execute({ embeddable }: EmbeddableApiContext) {
const { compatibilityCheck } = await import('./delete_control_action_compatibility_check');
if (!compatibilityCheck(embeddable)) throw new IncompatibleActionError();

coreServices.overlays
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,35 @@ import React from 'react';

import { EuiButtonIcon, EuiToolTip } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import type { EmbeddableApiContext, HasUniqueId } from '@kbn/presentation-publishing';
import {
apiHasType,
apiHasUniqueId,
hasEditCapabilities,
type EmbeddableApiContext,
type HasUniqueId,
apiHasParentApi,
apiCanAccessViewMode,
apiIsOfType,
getInheritedViewMode,
} from '@kbn/presentation-publishing';
import { IncompatibleActionError, type Action } from '@kbn/ui-actions-plugin/public';

import { ACTION_EDIT_CONTROL } from '.';
import { apiIsPresentationContainer } from '@kbn/presentation-containers';
import { CONTROL_GROUP_TYPE } from '../../common';
import { ACTION_EDIT_CONTROL } from './constants';
import { DataControlApi } from '../controls/data_controls/types';

const compatibilityCheck = (api: unknown): api is DataControlApi => {
return Boolean(
apiHasType(api) &&
apiHasUniqueId(api) &&
hasEditCapabilities(api) &&
apiHasParentApi(api) &&
apiCanAccessViewMode(api.parentApi) &&
apiIsOfType(api.parentApi, CONTROL_GROUP_TYPE) &&
apiIsPresentationContainer(api.parentApi)
);
};

export class EditControlAction implements Action<EmbeddableApiContext> {
public readonly type = ACTION_EDIT_CONTROL;
Expand Down Expand Up @@ -48,12 +73,14 @@ export class EditControlAction implements Action<EmbeddableApiContext> {
}

public async isCompatible({ embeddable }: EmbeddableApiContext) {
const { isCompatible } = await import('./edit_control_action_compatibility_check');
return isCompatible(embeddable);
return (
compatibilityCheck(embeddable) &&
getInheritedViewMode(embeddable.parentApi) === 'edit' &&
embeddable.isEditingEnabled()
);
}

public async execute({ embeddable }: EmbeddableApiContext) {
const { compatibilityCheck } = await import('./edit_control_action_compatibility_check');
if (!compatibilityCheck(embeddable)) throw new IncompatibleActionError();
await embeddable.onEdit();
}
Expand Down

This file was deleted.

Loading

0 comments on commit f7a275e

Please sign in to comment.