mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
# Backport This will backport the following commits from `main` to `8.x`: - [[controls] lazy load control actions (#206876)](https://github.com/elastic/kibana/pull/206876) <!--- Backport version: 9.6.4 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Nathan Reese","email":"reese.nathan@elastic.co"},"sourceCommit":{"committedDate":"2025-01-20T21:00:48Z","message":"[controls] lazy load control actions (#206876)\n\n* register control actions with async method\r\n* move floating actions into controls plugin\r\n* replace `PANEL_HOVER_TRIGGER` => `CONTROL_HOVER_TRIGGER`\r\n* Load controls in single chunk\r\n<img width=\"400\" alt=\"Screenshot 2025-01-16 at 11 40 08 AM\"\r\nsrc=\"https://github.com/user-attachments/assets/3171c9bf-26bc-4c07-950d-c35603cfb65a\"\r\n/>\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>","sha":"f4df5856f249552f01ccb020a3ffd90c1517b71d","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Feature:Embedding","Team:Presentation","release_note:skip","v9.0.0","project:embeddableRebuild","backport:version","v8.18.0"],"title":"[controls] lazy load control actions","number":206876,"url":"https://github.com/elastic/kibana/pull/206876","mergeCommit":{"message":"[controls] lazy load control actions (#206876)\n\n* register control actions with async method\r\n* move floating actions into controls plugin\r\n* replace `PANEL_HOVER_TRIGGER` => `CONTROL_HOVER_TRIGGER`\r\n* Load controls in single chunk\r\n<img width=\"400\" alt=\"Screenshot 2025-01-16 at 11 40 08 AM\"\r\nsrc=\"https://github.com/user-attachments/assets/3171c9bf-26bc-4c07-950d-c35603cfb65a\"\r\n/>\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>","sha":"f4df5856f249552f01ccb020a3ffd90c1517b71d"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/206876","number":206876,"mergeCommit":{"message":"[controls] lazy load control actions (#206876)\n\n* register control actions with async method\r\n* move floating actions into controls plugin\r\n* replace `PANEL_HOVER_TRIGGER` => `CONTROL_HOVER_TRIGGER`\r\n* Load controls in single chunk\r\n<img width=\"400\" alt=\"Screenshot 2025-01-16 at 11 40 08 AM\"\r\nsrc=\"https://github.com/user-attachments/assets/3171c9bf-26bc-4c07-950d-c35603cfb65a\"\r\n/>\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>","sha":"f4df5856f249552f01ccb020a3ffd90c1517b71d"}},{"branch":"8.x","label":"v8.18.0","branchLabelMappingKey":"^v8.18.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT-->
This commit is contained in:
parent
216d9b58b2
commit
c570a3431f
35 changed files with 204 additions and 232 deletions
|
@ -19,7 +19,7 @@ pageLoadAssetSize:
|
|||
cloudSecurityPosture: 19109
|
||||
console: 46091
|
||||
contentManagement: 16254
|
||||
controls: 60000
|
||||
controls: 12000
|
||||
core: 564663
|
||||
crossClusterReplication: 65408
|
||||
customIntegrations: 22034
|
||||
|
@ -38,7 +38,7 @@ pageLoadAssetSize:
|
|||
discover: 99999
|
||||
discoverEnhanced: 42730
|
||||
discoverShared: 17111
|
||||
embeddable: 87309
|
||||
embeddable: 24000
|
||||
embeddableEnhanced: 22107
|
||||
enterpriseSearch: 66810
|
||||
entityManager: 17175
|
||||
|
@ -123,8 +123,8 @@ pageLoadAssetSize:
|
|||
observabilityShared: 111036
|
||||
osquery: 107090
|
||||
painlessLab: 179748
|
||||
presentationPanel: 11501
|
||||
presentationUtil: 33186
|
||||
presentationPanel: 12000
|
||||
presentationUtil: 25000
|
||||
productDocBase: 22500
|
||||
profiling: 36694
|
||||
remoteClusters: 51327
|
||||
|
|
|
@ -11,9 +11,7 @@ export {
|
|||
contextMenuTrigger,
|
||||
CONTEXT_MENU_TRIGGER,
|
||||
panelBadgeTrigger,
|
||||
panelHoverTrigger,
|
||||
panelNotificationTrigger,
|
||||
PANEL_BADGE_TRIGGER,
|
||||
PANEL_HOVER_TRIGGER,
|
||||
PANEL_NOTIFICATION_TRIGGER,
|
||||
} from './triggers';
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 '.';
|
||||
import { ACTION_CLEAR_CONTROL } from './constants';
|
||||
|
||||
type ClearControlActionApi = HasType &
|
||||
HasUniqueId &
|
||||
CanClearSelections &
|
||||
HasParentApi<PresentationContainer & HasType>;
|
||||
|
||||
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>
|
||||
|
@ -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();
|
||||
|
|
|
@ -1,42 +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 { PresentationContainer, apiIsPresentationContainer } from '@kbn/presentation-containers';
|
||||
import {
|
||||
HasParentApi,
|
||||
HasType,
|
||||
HasUniqueId,
|
||||
apiCanAccessViewMode,
|
||||
apiHasParentApi,
|
||||
apiHasType,
|
||||
apiHasUniqueId,
|
||||
apiIsOfType,
|
||||
} from '@kbn/presentation-publishing';
|
||||
import { CONTROL_GROUP_TYPE } from '../../common';
|
||||
import { isClearableControl, type CanClearSelections } from '../types';
|
||||
|
||||
type ClearControlActionApi = HasType &
|
||||
HasUniqueId &
|
||||
CanClearSelections &
|
||||
HasParentApi<PresentationContainer & HasType>;
|
||||
|
||||
export 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 function isCompatible(api: unknown) {
|
||||
return compatibilityCheck(api);
|
||||
}
|
|
@ -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",
|
||||
}),
|
||||
};
|
|
@ -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;
|
||||
|
@ -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
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the "Elastic License
|
||||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { ViewMode } from '@kbn/embeddable-plugin/public';
|
||||
import { PresentationContainer, apiIsPresentationContainer } from '@kbn/presentation-containers';
|
||||
import {
|
||||
HasParentApi,
|
||||
HasType,
|
||||
HasUniqueId,
|
||||
PublishesViewMode,
|
||||
apiCanAccessViewMode,
|
||||
apiHasParentApi,
|
||||
apiHasType,
|
||||
apiHasUniqueId,
|
||||
apiIsOfType,
|
||||
getInheritedViewMode,
|
||||
} from '@kbn/presentation-publishing';
|
||||
import { CONTROL_GROUP_TYPE } from '../../common';
|
||||
|
||||
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 function isCompatible(api: unknown) {
|
||||
return compatibilityCheck(api) && getInheritedViewMode(api.parentApi) === ViewMode.EDIT;
|
||||
}
|
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the "Elastic License
|
||||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { ViewMode } from '@kbn/embeddable-plugin/public';
|
||||
import { apiIsPresentationContainer } from '@kbn/presentation-containers';
|
||||
import {
|
||||
apiCanAccessViewMode,
|
||||
apiHasParentApi,
|
||||
apiHasType,
|
||||
apiHasUniqueId,
|
||||
apiIsOfType,
|
||||
getInheritedViewMode,
|
||||
hasEditCapabilities,
|
||||
} from '@kbn/presentation-publishing';
|
||||
|
||||
import { CONTROL_GROUP_TYPE } from '../../common';
|
||||
import { DataControlApi } from '../controls/data_controls/types';
|
||||
|
||||
export 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 function isCompatible(api: unknown) {
|
||||
return (
|
||||
compatibilityCheck(api) &&
|
||||
getInheritedViewMode(api.parentApi) === ViewMode.EDIT &&
|
||||
api.isEditingEnabled()
|
||||
);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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 { UiActionsStart } from '@kbn/ui-actions-plugin/public';
|
||||
import { ACTION_CLEAR_CONTROL, ACTION_DELETE_CONTROL, ACTION_EDIT_CONTROL } from './constants';
|
||||
import { CONTROL_HOVER_TRIGGER, controlHoverTrigger } from './controls_hover_trigger';
|
||||
|
||||
export function registerActions(uiActions: UiActionsStart) {
|
||||
uiActions.registerTrigger(controlHoverTrigger);
|
||||
|
||||
uiActions.registerActionAsync(ACTION_DELETE_CONTROL, async () => {
|
||||
const { DeleteControlAction } = await import('../controls_module');
|
||||
return new DeleteControlAction();
|
||||
});
|
||||
uiActions.attachAction(CONTROL_HOVER_TRIGGER, ACTION_DELETE_CONTROL);
|
||||
|
||||
uiActions.registerActionAsync(ACTION_EDIT_CONTROL, async () => {
|
||||
const { EditControlAction } = await import('../controls_module');
|
||||
return new EditControlAction();
|
||||
});
|
||||
uiActions.attachAction(CONTROL_HOVER_TRIGGER, ACTION_EDIT_CONTROL);
|
||||
|
||||
uiActions.registerActionAsync(ACTION_CLEAR_CONTROL, async () => {
|
||||
const { ClearControlAction } = await import('../controls_module');
|
||||
return new ClearControlAction();
|
||||
});
|
||||
uiActions.attachAction(CONTROL_HOVER_TRIGGER, ACTION_CLEAR_CONTROL);
|
||||
}
|
|
@ -11,12 +11,12 @@ import React, { useImperativeHandle } from 'react';
|
|||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
import { setMockedPresentationUtilServices } from '@kbn/presentation-util-plugin/public/mocks';
|
||||
import { uiActionsService } from '@kbn/presentation-util-plugin/public/services/kibana_services';
|
||||
import { render, waitFor } from '@testing-library/react';
|
||||
import { Action } from '@kbn/ui-actions-plugin/public';
|
||||
|
||||
import type { ControlLabelPosition, ControlWidth } from '../../../common';
|
||||
import { uiActionsService } from '../../services/kibana_services';
|
||||
import { ControlPanel } from './control_panel';
|
||||
import { Action } from '@kbn/ui-actions-plugin/public';
|
||||
|
||||
describe('render', () => {
|
||||
let mockApi = {};
|
||||
|
|
|
@ -27,7 +27,7 @@ import {
|
|||
apiPublishesViewMode,
|
||||
useBatchedOptionalPublishingSubjects,
|
||||
} from '@kbn/presentation-publishing';
|
||||
import { FloatingActions } from '@kbn/presentation-util-plugin/public';
|
||||
import { FloatingActions } from './floating_actions';
|
||||
import { DEFAULT_CONTROL_GROW, DEFAULT_CONTROL_WIDTH } from '../../../common';
|
||||
|
||||
import { ControlPanelProps, DefaultControlApi } from '../../controls/types';
|
||||
|
|
|
@ -12,16 +12,13 @@ import React, { FC, ReactElement, useEffect, useState } from 'react';
|
|||
import { v4 } from 'uuid';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import {
|
||||
PANEL_HOVER_TRIGGER,
|
||||
panelHoverTrigger,
|
||||
type ViewMode,
|
||||
} from '@kbn/embeddable-plugin/public';
|
||||
import { type ViewMode } from '@kbn/embeddable-plugin/public';
|
||||
import { apiHasUniqueId } from '@kbn/presentation-publishing';
|
||||
import { Action } from '@kbn/ui-actions-plugin/public';
|
||||
import { AnyApiAction } from '@kbn/presentation-panel-plugin/public/panel_actions/types';
|
||||
import { uiActionsService } from '../../services/kibana_services';
|
||||
import './floating_actions.scss';
|
||||
import { CONTROL_HOVER_TRIGGER, controlHoverTrigger } from '../../actions/controls_hover_trigger';
|
||||
|
||||
export interface FloatingActionsProps {
|
||||
children: ReactElement;
|
||||
|
@ -53,7 +50,7 @@ export const FloatingActions: FC<FloatingActionsProps> = ({
|
|||
let canceled = false;
|
||||
const context = {
|
||||
embeddable: api,
|
||||
trigger: panelHoverTrigger,
|
||||
trigger: controlHoverTrigger,
|
||||
};
|
||||
|
||||
const sortByOrder = (a: Action | FloatingActionItem, b: Action | FloatingActionItem) => {
|
||||
|
@ -62,7 +59,7 @@ export const FloatingActions: FC<FloatingActionsProps> = ({
|
|||
|
||||
const getActions: () => Promise<FloatingActionItem[]> = async () => {
|
||||
const actions = (
|
||||
await uiActionsService.getTriggerCompatibleActions(PANEL_HOVER_TRIGGER, context)
|
||||
await uiActionsService.getTriggerCompatibleActions(CONTROL_HOVER_TRIGGER, context)
|
||||
)
|
||||
.filter((action) => {
|
||||
return action.MenuItem !== undefined && (disabledActions ?? []).indexOf(action.id) === -1;
|
||||
|
@ -92,7 +89,10 @@ export const FloatingActions: FC<FloatingActionsProps> = ({
|
|||
setFloatingActions(actions);
|
||||
|
||||
const frequentlyChangingActions =
|
||||
await uiActionsService.getFrequentlyChangingActionsForTrigger(PANEL_HOVER_TRIGGER, context);
|
||||
await uiActionsService.getFrequentlyChangingActionsForTrigger(
|
||||
CONTROL_HOVER_TRIGGER,
|
||||
context
|
||||
);
|
||||
if (canceled) return;
|
||||
|
||||
for (const action of frequentlyChangingActions) {
|
|
@ -12,7 +12,7 @@ import { dynamic } from '@kbn/shared-ux-utility';
|
|||
import type { ControlGroupRendererProps } from './control_group_renderer';
|
||||
|
||||
const Component = dynamic(async () => {
|
||||
const { ControlGroupRenderer } = await import('./control_group_renderer');
|
||||
const { ControlGroupRenderer } = await import('../../controls_module');
|
||||
return {
|
||||
default: ControlGroupRenderer,
|
||||
};
|
||||
|
|
|
@ -14,7 +14,7 @@ import { untilPluginStartServicesReady } from '../services/kibana_services';
|
|||
export function registerControlGroupEmbeddable(embeddableSetup: EmbeddableSetup) {
|
||||
embeddableSetup.registerReactEmbeddableFactory(CONTROL_GROUP_TYPE, async () => {
|
||||
const [{ getControlGroupEmbeddableFactory }] = await Promise.all([
|
||||
import('./get_control_group_factory'),
|
||||
import('../controls_module'),
|
||||
untilPluginStartServicesReady(),
|
||||
]);
|
||||
return getControlGroupEmbeddableFactory();
|
||||
|
|
|
@ -14,7 +14,7 @@ import { registerControlFactory } from '../../../control_factory_registry';
|
|||
export function registerOptionsListControl() {
|
||||
registerControlFactory(OPTIONS_LIST_CONTROL, async () => {
|
||||
const [{ getOptionsListControlFactory }] = await Promise.all([
|
||||
import('./get_options_list_control_factory'),
|
||||
import('../../../controls_module'),
|
||||
untilPluginStartServicesReady(),
|
||||
]);
|
||||
return getOptionsListControlFactory();
|
||||
|
|
|
@ -14,7 +14,7 @@ import { registerControlFactory } from '../../../control_factory_registry';
|
|||
export function registerRangeSliderControl() {
|
||||
registerControlFactory(RANGE_SLIDER_CONTROL, async () => {
|
||||
const [{ getRangesliderControlFactory }] = await Promise.all([
|
||||
import('./get_range_slider_control_factory'),
|
||||
import('../../../controls_module'),
|
||||
untilPluginStartServicesReady(),
|
||||
]);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import { registerControlFactory } from '../../control_factory_registry';
|
|||
export function registerTimeSliderControl() {
|
||||
registerControlFactory(TIME_SLIDER_CONTROL, async () => {
|
||||
const [{ getTimesliderControlFactory }] = await Promise.all([
|
||||
import('./get_timeslider_control_factory'),
|
||||
import('../../controls_module'),
|
||||
untilPluginStartServicesReady(),
|
||||
]);
|
||||
return getTimesliderControlFactory();
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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".
|
||||
*/
|
||||
|
||||
export { ClearControlAction } from './actions/clear_control_action';
|
||||
export { DeleteControlAction } from './actions/delete_control_action';
|
||||
export { EditControlAction } from './actions/edit_control_action';
|
||||
|
||||
export { getControlGroupEmbeddableFactory } from './control_group/get_control_group_factory';
|
||||
|
||||
export { getOptionsListControlFactory } from './controls/data_controls/options_list_control/get_options_list_control_factory';
|
||||
export { getRangesliderControlFactory } from './controls/data_controls/range_slider/get_range_slider_control_factory';
|
||||
export { getTimesliderControlFactory } from './controls/timeslider_control/get_timeslider_control_factory';
|
||||
|
||||
export { ControlGroupRenderer } from './control_group/control_group_renderer/control_group_renderer';
|
|
@ -14,9 +14,13 @@ export {
|
|||
type ControlGroupStateBuilder,
|
||||
} from './control_group/utils/control_group_state_builder';
|
||||
|
||||
export type { ControlGroupApi, ControlStateTransform } from './control_group/types';
|
||||
export {
|
||||
ACTION_CLEAR_CONTROL,
|
||||
ACTION_DELETE_CONTROL,
|
||||
ACTION_EDIT_CONTROL,
|
||||
} from './actions/constants';
|
||||
|
||||
export { ACTION_CLEAR_CONTROL, ACTION_DELETE_CONTROL, ACTION_EDIT_CONTROL } from './actions';
|
||||
export type { ControlGroupApi, ControlStateTransform } from './control_group/types';
|
||||
|
||||
export type { DataControlApi, DataControlFactory } from './controls/data_controls/types';
|
||||
|
||||
|
|
|
@ -8,17 +8,13 @@
|
|||
*/
|
||||
|
||||
import type { CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import { PANEL_HOVER_TRIGGER } from '@kbn/embeddable-plugin/public';
|
||||
|
||||
import { ClearControlAction } from './actions/clear_control_action';
|
||||
import { DeleteControlAction } from './actions/delete_control_action';
|
||||
import { EditControlAction } from './actions/edit_control_action';
|
||||
import { registerControlGroupEmbeddable } from './control_group/register_control_group_embeddable';
|
||||
import { registerOptionsListControl } from './controls/data_controls/options_list_control/register_options_list_control';
|
||||
import { registerRangeSliderControl } from './controls/data_controls/range_slider/register_range_slider_control';
|
||||
import { registerTimeSliderControl } from './controls/timeslider_control/register_timeslider_control';
|
||||
import { setKibanaServices, untilPluginStartServicesReady } from './services/kibana_services';
|
||||
import { setKibanaServices } from './services/kibana_services';
|
||||
import type { ControlsPluginSetupDeps, ControlsPluginStartDeps } from './types';
|
||||
import { registerActions } from './actions/register_actions';
|
||||
|
||||
export class ControlsPlugin
|
||||
implements Plugin<void, void, ControlsPluginSetupDeps, ControlsPluginStartDeps>
|
||||
|
@ -36,22 +32,9 @@ export class ControlsPlugin
|
|||
}
|
||||
|
||||
public start(coreStart: CoreStart, startPlugins: ControlsPluginStartDeps) {
|
||||
const { uiActions } = startPlugins;
|
||||
setKibanaServices(coreStart, startPlugins);
|
||||
|
||||
untilPluginStartServicesReady().then(() => {
|
||||
const deleteControlAction = new DeleteControlAction();
|
||||
uiActions.registerAction(deleteControlAction);
|
||||
uiActions.attachAction(PANEL_HOVER_TRIGGER, deleteControlAction.id);
|
||||
|
||||
const editControlAction = new EditControlAction();
|
||||
uiActions.registerAction(editControlAction);
|
||||
uiActions.attachAction(PANEL_HOVER_TRIGGER, editControlAction.id);
|
||||
|
||||
const clearControlAction = new ClearControlAction();
|
||||
uiActions.registerAction(clearControlAction);
|
||||
uiActions.attachAction(PANEL_HOVER_TRIGGER, clearControlAction.id);
|
||||
});
|
||||
registerActions(startPlugins.uiActions);
|
||||
}
|
||||
|
||||
public stop() {}
|
||||
|
|
|
@ -12,12 +12,14 @@ import { BehaviorSubject } from 'rxjs';
|
|||
import { CoreStart } from '@kbn/core/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
|
||||
import { UiActionsStart } from '@kbn/ui-actions-plugin/public';
|
||||
|
||||
import { ControlsPluginStartDeps } from '../types';
|
||||
|
||||
export let coreServices: CoreStart;
|
||||
export let dataService: DataPublicPluginStart;
|
||||
export let dataViewsService: DataViewsPublicPluginStart;
|
||||
export let uiActionsService: UiActionsStart;
|
||||
|
||||
const servicesReady$ = new BehaviorSubject(false);
|
||||
|
||||
|
@ -25,6 +27,7 @@ export const setKibanaServices = (kibanaCore: CoreStart, deps: ControlsPluginSta
|
|||
coreServices = kibanaCore;
|
||||
dataService = deps.data;
|
||||
dataViewsService = deps.dataViews;
|
||||
uiActionsService = deps.uiActions;
|
||||
|
||||
servicesReady$.next(true);
|
||||
};
|
||||
|
|
|
@ -25,10 +25,8 @@ export {
|
|||
isValueClickTriggerContext,
|
||||
MULTI_VALUE_CLICK_TRIGGER,
|
||||
panelBadgeTrigger,
|
||||
panelHoverTrigger,
|
||||
panelNotificationTrigger,
|
||||
PANEL_BADGE_TRIGGER,
|
||||
PANEL_HOVER_TRIGGER,
|
||||
PANEL_NOTIFICATION_TRIGGER,
|
||||
SELECT_RANGE_TRIGGER,
|
||||
VALUE_CLICK_TRIGGER,
|
||||
|
|
|
@ -16,12 +16,10 @@ import {
|
|||
selectRangeTrigger,
|
||||
valueClickTrigger,
|
||||
cellValueTrigger,
|
||||
panelHoverTrigger,
|
||||
} from './triggers';
|
||||
|
||||
export const registerTriggers = (uiActions: UiActionsSetup) => {
|
||||
uiActions.registerTrigger(contextMenuTrigger);
|
||||
uiActions.registerTrigger(panelHoverTrigger);
|
||||
uiActions.registerTrigger(panelBadgeTrigger);
|
||||
uiActions.registerTrigger(panelNotificationTrigger);
|
||||
uiActions.registerTrigger(selectRangeTrigger);
|
||||
|
|
|
@ -75,17 +75,6 @@ export const contextMenuTrigger: Trigger = {
|
|||
}),
|
||||
};
|
||||
|
||||
export const PANEL_HOVER_TRIGGER = 'PANEL_HOVER_TRIGGER';
|
||||
export const panelHoverTrigger: Trigger = {
|
||||
id: PANEL_HOVER_TRIGGER,
|
||||
title: i18n.translate('embeddableApi.panelHoverTrigger.title', {
|
||||
defaultMessage: 'Panel hover',
|
||||
}),
|
||||
description: i18n.translate('embeddableApi.panelHoverTrigger.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,
|
||||
|
|
|
@ -61,8 +61,6 @@ export {
|
|||
DEFAULT_DASHBOARD_DRILLDOWN_OPTIONS,
|
||||
} from './dashboard_drilldown_options/types';
|
||||
|
||||
export { FloatingActions } from './floating_actions/floating_actions';
|
||||
|
||||
/**
|
||||
* A lazily-loaded ExpressionInput component.
|
||||
*/
|
||||
|
|
|
@ -13,7 +13,7 @@ import type { CSSProperties, HTMLAttributes } from 'react';
|
|||
|
||||
import type { ExpressionFunction } from '@kbn/expressions-plugin/common';
|
||||
|
||||
import { OnSaveProps, SaveModalState } from '@kbn/saved-objects-plugin/public';
|
||||
import type { OnSaveProps, SaveModalState } from '@kbn/saved-objects-plugin/public';
|
||||
|
||||
interface SaveModalDocumentInfo {
|
||||
id?: string;
|
||||
|
|
|
@ -24,7 +24,6 @@ export {
|
|||
withSuspense,
|
||||
LazyDataViewPicker,
|
||||
LazyFieldPicker,
|
||||
FloatingActions,
|
||||
type DashboardDrilldownOptions,
|
||||
DashboardDrilldownOptionsComponent,
|
||||
DEFAULT_DASHBOARD_DRILLDOWN_OPTIONS,
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
"kbn_references": [
|
||||
"@kbn/core",
|
||||
"@kbn/saved-objects-plugin",
|
||||
"@kbn/embeddable-plugin",
|
||||
"@kbn/kibana-react-plugin",
|
||||
"@kbn/i18n",
|
||||
"@kbn/expressions-plugin",
|
||||
|
@ -34,9 +33,7 @@
|
|||
"@kbn/code-editor",
|
||||
"@kbn/calculate-width-from-char-count",
|
||||
"@kbn/field-utils",
|
||||
"@kbn/presentation-publishing",
|
||||
"@kbn/core-ui-settings-browser",
|
||||
"@kbn/presentation-panel-plugin",
|
||||
],
|
||||
"exclude": ["target/**/*"]
|
||||
}
|
||||
|
|
|
@ -2826,8 +2826,6 @@
|
|||
"embeddableApi.multiValueClickTrigger.title": "Clics multiples",
|
||||
"embeddableApi.panelBadgeTrigger.description": "Des actions apparaissent dans la barre de titre lorsqu'un élément pouvant être intégré est chargé dans un panneau.",
|
||||
"embeddableApi.panelBadgeTrigger.title": "Badges du panneau",
|
||||
"embeddableApi.panelHoverTrigger.description": "Une nouvelle action sera ajoutée au menu flottant du panneau",
|
||||
"embeddableApi.panelHoverTrigger.title": "Menu contextuel du panneau",
|
||||
"embeddableApi.panelNotificationTrigger.description": "Les actions apparaissent dans l’angle supérieur droit des panneaux.",
|
||||
"embeddableApi.panelNotificationTrigger.title": "Notifications du panneau",
|
||||
"embeddableApi.reactEmbeddable.factoryAlreadyExistsError": "Une usine incorporable pour le type : {key} est déjà enregistrée.",
|
||||
|
@ -6287,8 +6285,6 @@
|
|||
"presentationPanel.filters.filtersTitle": "Filtres",
|
||||
"presentationPanel.filters.queryTitle": "Recherche",
|
||||
"presentationPanel.header.titleAriaLabel": "Cliquez pour modifier le titre : {title}",
|
||||
"presentationPanel.hoverTrigger.description": "Une nouvelle action sera ajoutée au menu flottant du panneau",
|
||||
"presentationPanel.hoverTrigger.title": "Menu contextuel du panneau",
|
||||
"presentationPanel.notificationTrigger.description": "Les actions de notification apparaissent dans l'angle supérieur droit des panneaux.",
|
||||
"presentationPanel.notificationTrigger.title": "Notifications du panneau",
|
||||
"presentationPanel.placeholderTitle": "[Aucun titre]",
|
||||
|
|
|
@ -2820,8 +2820,6 @@
|
|||
"embeddableApi.multiValueClickTrigger.title": "マルチクリック",
|
||||
"embeddableApi.panelBadgeTrigger.description": "パネルに埋め込み可能なファイルが読み込まれるときに、アクションがタイトルバーに表示されます。",
|
||||
"embeddableApi.panelBadgeTrigger.title": "パネルバッジ",
|
||||
"embeddableApi.panelHoverTrigger.description": "新しいアクションがパネルのマウスオーバーメニューに追加されます",
|
||||
"embeddableApi.panelHoverTrigger.title": "パネルマウスオーバー",
|
||||
"embeddableApi.panelNotificationTrigger.description": "パネルの右上にアクションが表示されます。",
|
||||
"embeddableApi.panelNotificationTrigger.title": "パネル通知",
|
||||
"embeddableApi.reactEmbeddable.factoryAlreadyExistsError": "タイプ\"{key}\"の埋め込み可能ファクトリはすでに登録されています。",
|
||||
|
@ -6280,8 +6278,6 @@
|
|||
"presentationPanel.filters.filtersTitle": "フィルター",
|
||||
"presentationPanel.filters.queryTitle": "クエリー",
|
||||
"presentationPanel.header.titleAriaLabel": "クリックしてタイトルを編集:{title}",
|
||||
"presentationPanel.hoverTrigger.description": "新しいアクションがパネルのマウスオーバーメニューに追加されます",
|
||||
"presentationPanel.hoverTrigger.title": "パネルマウスオーバー",
|
||||
"presentationPanel.notificationTrigger.description": "パネルの右上に通知アクションが表示されます。",
|
||||
"presentationPanel.notificationTrigger.title": "パネル通知",
|
||||
"presentationPanel.placeholderTitle": "[タイトルなし]",
|
||||
|
|
|
@ -2857,8 +2857,6 @@
|
|||
"embeddableApi.multiValueClickTrigger.title": "多次单击",
|
||||
"embeddableApi.panelBadgeTrigger.description": "可嵌入对象在面板加载后,操作便显示在标题栏中。",
|
||||
"embeddableApi.panelBadgeTrigger.title": "面板徽章",
|
||||
"embeddableApi.panelHoverTrigger.description": "会将一个新操作添加到该面板的悬停菜单",
|
||||
"embeddableApi.panelHoverTrigger.title": "面板悬停",
|
||||
"embeddableApi.panelNotificationTrigger.description": "操作显示在面板右上角。",
|
||||
"embeddableApi.panelNotificationTrigger.title": "面板通知",
|
||||
"embeddableApi.reactEmbeddable.factoryAlreadyExistsError": "已注册类型为 {key} 的可嵌入工厂。",
|
||||
|
@ -6323,8 +6321,6 @@
|
|||
"presentationPanel.filters.filtersTitle": "筛选",
|
||||
"presentationPanel.filters.queryTitle": "查询",
|
||||
"presentationPanel.header.titleAriaLabel": "单击可编辑标题:{title}",
|
||||
"presentationPanel.hoverTrigger.description": "会将一个新操作添加到该面板的悬停菜单",
|
||||
"presentationPanel.hoverTrigger.title": "面板悬停",
|
||||
"presentationPanel.notificationTrigger.description": "通知操作显示在面板右上角。",
|
||||
"presentationPanel.notificationTrigger.title": "面板通知",
|
||||
"presentationPanel.placeholderTitle": "[无标题]",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue