From 5e292f5bf4517514651a7c7136a3c87422ed08f8 Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Wed, 20 Mar 2024 16:53:07 +0100 Subject: [PATCH 1/9] update edit swim lane action --- .../embeddables/anomaly_charts/types.ts | 19 +++++++ .../anomaly_swimlane_embeddable.tsx | 13 +++++ .../anomaly_swimlane_initializer.tsx | 8 +-- .../anomaly_swimlane_setup_flyout.tsx | 7 +-- .../embeddables/anomaly_swimlane/types.ts | 25 +++++++++ x-pack/plugins/ml/public/embeddables/types.ts | 30 +++++++++- .../ui_actions/edit_swimlane_panel_action.tsx | 54 ++++++++++-------- x-pack/plugins/ml/public/ui_actions/index.ts | 1 - .../open_in_anomaly_explorer_action.tsx | 55 ++++--------------- 9 files changed, 134 insertions(+), 78 deletions(-) create mode 100644 x-pack/plugins/ml/public/embeddables/anomaly_charts/types.ts create mode 100644 x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_charts/types.ts b/x-pack/plugins/ml/public/embeddables/anomaly_charts/types.ts new file mode 100644 index 0000000000000..f8b1562884e8e --- /dev/null +++ b/x-pack/plugins/ml/public/embeddables/anomaly_charts/types.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 type { MlEntityField } from '@kbn/ml-anomaly-utils'; +import type { HasType, PublishingSubject } from '@kbn/presentation-publishing'; +import type { AnomalyExplorerChartsEmbeddableType } from '../constants'; +import type { MlEmbeddableBaseApi } from '../types'; + +export interface AnomalyChartsFieldSelectionApi { + entityFields: PublishingSubject; +} + +export type AnomalyChartsEmbeddableApi = HasType & + MlEmbeddableBaseApi & + AnomalyChartsFieldSelectionApi; diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx index 968d505dc46ee..9e8a88c1defd9 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx @@ -16,11 +16,13 @@ import { Subject, Subscription, type BehaviorSubject } from 'rxjs'; import type { AnomalySwimlaneEmbeddableInput, AnomalySwimlaneEmbeddableOutput, + AnomalySwimlaneEmbeddableUserInput, AnomalySwimlaneServices, } from '..'; import { ANOMALY_SWIMLANE_EMBEDDABLE_TYPE } from '..'; import type { JobId } from '../../../common/types/anomaly_detection_jobs'; import type { MlDependencies } from '../../application/app'; +import type { SwimlaneType } from '../../application/explorer/explorer_constants'; import { SWIM_LANE_SELECTION_TRIGGER } from '../../ui_actions'; import { AnomalyDetectionEmbeddable } from '../common/anomaly_detection_embeddable'; import { EmbeddableLoading } from '../common/components/embeddable_loading_fallback'; @@ -44,6 +46,7 @@ export class AnomalySwimlaneEmbeddable extends AnomalyDetectionEmbeddable< // API public viewBy: BehaviorSubject; + public swimlaneType: BehaviorSubject; public perPage: BehaviorSubject; public fromPage: BehaviorSubject; @@ -62,6 +65,12 @@ export class AnomalySwimlaneEmbeddable extends AnomalyDetectionEmbeddable< 'viewBy' ); + this.swimlaneType = embeddableInputToSubject( + this.apiSubscriptions, + this, + 'swimlaneType' + ); + this.perPage = embeddableOutputToSubject( this.apiSubscriptions, this, @@ -75,6 +84,10 @@ export class AnomalySwimlaneEmbeddable extends AnomalyDetectionEmbeddable< ); } + public updateUserInput(update: AnomalySwimlaneEmbeddableUserInput) { + this.updateInput(update); + } + public reportsEmbeddableLoad() { return true; } diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_initializer.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_initializer.tsx index d6875a9ce7a0d..92943f4286c12 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_initializer.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_initializer.tsx @@ -25,13 +25,9 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import type { SwimlaneType } from '../../application/explorer/explorer_constants'; import { SWIMLANE_TYPE } from '../../application/explorer/explorer_constants'; -import type { AnomalySwimlaneEmbeddableInput } from '..'; +import type { AnomalySwimlaneEmbeddableInput, AnomalySwimlaneEmbeddableUserInput } from '..'; -interface ExplicitInput { - panelTitle: string; - swimlaneType: SwimlaneType; - viewBy?: string; -} +export type ExplicitInput = Omit; export interface AnomalySwimlaneInitializerProps { defaultTitle: string; diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_setup_flyout.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_setup_flyout.tsx index 34ba32cd4a127..fa9185bb026a9 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_setup_flyout.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_setup_flyout.tsx @@ -14,15 +14,15 @@ import { VIEW_BY_JOB_LABEL } from '../../application/explorer/explorer_constants import { AnomalySwimlaneInitializer } from './anomaly_swimlane_initializer'; import { getDefaultSwimlanePanelTitle } from './anomaly_swimlane_embeddable'; import { HttpService } from '../../application/services/http_service'; -import type { AnomalySwimlaneEmbeddableInput } from '..'; +import type { AnomalySwimlaneEmbeddableInput, AnomalySwimlaneEmbeddableUserInput } from '..'; import { resolveJobSelection } from '../common/resolve_job_selection'; import { mlApiServicesProvider } from '../../application/services/ml_api_service'; export async function resolveAnomalySwimlaneUserInput( coreStart: CoreStart, dataViews: DataViewsContract, - input?: AnomalySwimlaneEmbeddableInput -): Promise> { + input?: Partial +): Promise { const { http, overlays, theme, i18n } = coreStart; const { getJobs } = mlApiServicesProvider(new HttpService(http)); @@ -44,7 +44,6 @@ export async function resolveAnomalySwimlaneUserInput( modalSession.close(); resolve({ jobIds, - title: explicitInput.panelTitle, ...explicitInput, }); }} diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts new file mode 100644 index 0000000000000..82728867e7be0 --- /dev/null +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts @@ -0,0 +1,25 @@ +/* + * 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 { HasType, PublishingSubject } from '@kbn/presentation-publishing'; +import type { SwimlaneType } from '../../application/explorer/explorer_constants'; +import type { JobId } from '../../shared'; +import type { AnomalySwimLaneEmbeddableType } from '../constants'; +import type { AnomalySwimlaneEmbeddableUserInput, MlEmbeddableBaseApi } from '../types'; + +export interface AnomalySwimLaneComponentApi { + jobIds: JobId[]; + swimlaneType: PublishingSubject; + viewBy: PublishingSubject; + perPage: PublishingSubject; + fromPage: PublishingSubject; + updateUserInput: (input: AnomalySwimlaneEmbeddableUserInput) => void; +} + +export type AnomalySwimLaneEmbeddableApi = HasType & + MlEmbeddableBaseApi & + AnomalySwimLaneComponentApi; diff --git a/x-pack/plugins/ml/public/embeddables/types.ts b/x-pack/plugins/ml/public/embeddables/types.ts index a0bd799352d4f..8c8359c6a812e 100644 --- a/x-pack/plugins/ml/public/embeddables/types.ts +++ b/x-pack/plugins/ml/public/embeddables/types.ts @@ -11,6 +11,14 @@ import type { DataView } from '@kbn/data-views-plugin/common'; import type { EmbeddableInput, EmbeddableOutput, IEmbeddable } from '@kbn/embeddable-plugin/public'; import type { Filter, Query, TimeRange } from '@kbn/es-query'; import type { MlEntityField } from '@kbn/ml-anomaly-utils'; +import type { + EmbeddableApiContext, + HasParentApi, + HasType, + PublishesPanelTitle, + PublishesUnifiedSearch, + PublishesViewMode, +} from '@kbn/presentation-publishing'; import type { JobId } from '../../common/types/anomaly_detection_jobs'; import type { MlDependencies } from '../application/app'; import type { MlCapabilitiesService } from '../application/capabilities/check_capabilities'; @@ -30,6 +38,21 @@ import type { MlEmbeddableTypes, } from './constants'; +export type MlEmbeddableBaseApi = Partial< + HasParentApi & + PublishesViewMode & + PublishesUnifiedSearch & + PublishesPanelTitle +>; + +/** Manual input by the user */ +export interface AnomalySwimlaneEmbeddableUserInput { + jobIds: JobId[]; + panelTitle: string; + swimlaneType: SwimlaneType; + viewBy?: string; +} + export interface AnomalySwimlaneEmbeddableCustomInput { jobIds: JobId[]; swimlaneType: SwimlaneType; @@ -66,8 +89,11 @@ export interface AnomalySwimlaneEmbeddableCustomOutput { export type AnomalySwimlaneEmbeddableOutput = EmbeddableOutput & AnomalySwimlaneEmbeddableCustomOutput; -export interface EditSwimlanePanelContext { - embeddable: IEmbeddable; +export type EditSwimLaneActionApi = HasType & + Partial>; + +export interface EditSwimlanePanelContext extends EmbeddableApiContext { + embeddable: EditSwimLaneActionApi; } export interface SwimLaneDrilldownContext extends EditSwimlanePanelContext { diff --git a/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx b/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx index c2933014e9feb..c1e56ec385703 100644 --- a/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx @@ -6,30 +6,36 @@ */ import { i18n } from '@kbn/i18n'; -import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public'; -import { ViewMode } from '@kbn/embeddable-plugin/public'; +import type { EmbeddableApiContext } from '@kbn/presentation-publishing'; +import { createAction, IncompatibleActionError } from '@kbn/ui-actions-plugin/public'; +import type { AnomalySwimLaneEmbeddableApi } from '../embeddables/anomaly_swimlane/types'; import type { MlCoreSetup } from '../plugin'; -import type { EditSwimlanePanelContext } from '../embeddables'; -import { ANOMALY_SWIMLANE_EMBEDDABLE_TYPE } from '../embeddables'; +import { + isAnomalyChartsEmbeddableContext, + isSwimLaneEmbeddableContext, +} from './open_in_anomaly_explorer_action'; export const EDIT_SWIMLANE_PANEL_ACTION = 'editSwimlanePanelAction'; -export function createEditSwimlanePanelAction( - getStartServices: MlCoreSetup['getStartServices'] -): UiActionsActionDefinition { - return { +export type EditSwimlanePanelActionContext = EmbeddableApiContext & { + embeddable: AnomalySwimLaneEmbeddableApi; +}; + +export function createEditSwimlanePanelAction(getStartServices: MlCoreSetup['getStartServices']) { + return createAction({ id: 'edit-anomaly-swimlane', type: EDIT_SWIMLANE_PANEL_ACTION, - getIconType(context): string { + order: 50, + getIconType(): string { return 'pencil'; }, getDisplayName: () => i18n.translate('xpack.ml.actions.editSwimlaneTitle', { defaultMessage: 'Edit swim lane', }), - async execute({ embeddable }) { - if (!embeddable) { - throw new Error('Not possible to execute an action without the embeddable context'); + async execute(context) { + if (!isSwimLaneEmbeddableContext(context)) { + throw new IncompatibleActionError(); } const [coreStart, deps] = await getStartServices(); @@ -39,21 +45,25 @@ export function createEditSwimlanePanelAction( '../embeddables/anomaly_swimlane/anomaly_swimlane_setup_flyout' ); - const result = await resolveAnomalySwimlaneUserInput( - coreStart, - deps.data.dataViews, - embeddable.getInput() - ); - embeddable.updateInput(result); + const { jobIds, viewBy, swimlaneType, panelTitle } = context.embeddable; + + const result = await resolveAnomalySwimlaneUserInput(coreStart, deps.data.dataViews, { + jobIds, + swimlaneType: swimlaneType.getValue(), + viewBy: viewBy.getValue(), + title: panelTitle?.getValue(), + }); + + context.embeddable.updateUserInput(result); } catch (e) { return Promise.reject(); } }, - async isCompatible({ embeddable }) { + async isCompatible(context: EmbeddableApiContext) { return ( - embeddable.type === ANOMALY_SWIMLANE_EMBEDDABLE_TYPE && - embeddable.getInput().viewMode === ViewMode.EDIT + isAnomalyChartsEmbeddableContext(context) && + context.embeddable.viewMode?.getValue() === 'edit' ); }, - }; + }); } diff --git a/x-pack/plugins/ml/public/ui_actions/index.ts b/x-pack/plugins/ml/public/ui_actions/index.ts index bdbd5f3f3e858..03afb2c44c40f 100644 --- a/x-pack/plugins/ml/public/ui_actions/index.ts +++ b/x-pack/plugins/ml/public/ui_actions/index.ts @@ -53,7 +53,6 @@ export function registerMlUiActions( const categorizationADJobAction = createCategorizationADJobAction(core.getStartServices); // Register actions - uiActions.registerAction(editSwimlanePanelAction); uiActions.registerAction(applyInfluencerFiltersAction); uiActions.registerAction(applyEntityFieldFilterAction); uiActions.registerAction(applyTimeRangeSelectionAction); diff --git a/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx b/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx index e955245adec86..60ce4b272a3bd 100644 --- a/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx @@ -10,42 +10,24 @@ import { i18n } from '@kbn/i18n'; import type { MlEntityField } from '@kbn/ml-anomaly-utils'; import { ML_ENTITY_FIELD_OPERATIONS } from '@kbn/ml-anomaly-utils'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; -import type { - EmbeddableApiContext, - HasParentApi, - HasType, - PublishesUnifiedSearch, - PublishingSubject, -} from '@kbn/presentation-publishing'; -import { apiHasType, apiIsOfType } from '@kbn/presentation-publishing'; +import type { EmbeddableApiContext } from '@kbn/presentation-publishing'; +import { apiIsOfType } from '@kbn/presentation-publishing'; import { createAction } from '@kbn/ui-actions-plugin/public'; import type { SerializableRecord } from '@kbn/utility-types'; import { ML_APP_LOCATOR } from '../../common/constants/locator'; import type { ExplorerAppState } from '../../common/types/locator'; import type { AppStateSelectedCells } from '../application/explorer/explorer_utils'; -import type { - AnomalyExplorerChartsEmbeddableType, - AnomalySwimLaneEmbeddableType, -} from '../embeddables'; +import type { MlEmbeddableBaseApi } from '../embeddables'; import { ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE, ANOMALY_SWIMLANE_EMBEDDABLE_TYPE, } from '../embeddables'; +import type { AnomalyChartsEmbeddableApi } from '../embeddables/anomaly_charts/types'; +import type { AnomalySwimLaneEmbeddableApi } from '../embeddables/anomaly_swimlane/types'; import type { MlCoreSetup } from '../plugin'; -import type { JobId } from '../shared'; - -export interface AnomalyChartsFieldSelectionApi { - entityFields: PublishingSubject; -} - -export interface SwimLaneDrilldownApi { - viewBy: PublishingSubject; - perPage: PublishingSubject; - fromPage: PublishingSubject; -} export interface OpenInAnomalyExplorerSwimLaneActionContext extends EmbeddableApiContext { - embeddable: OpenInAnomalyExplorerFromSwimLaneActionApi; + embeddable: AnomalySwimLaneEmbeddableApi; /** * Optional data provided by swim lane selection */ @@ -53,26 +35,13 @@ export interface OpenInAnomalyExplorerSwimLaneActionContext extends EmbeddableAp } export interface OpenInAnomalyExplorerAnomalyChartsActionContext extends EmbeddableApiContext { - embeddable: OpenInAnomalyExplorerFromAnomalyChartActionApi; + embeddable: AnomalyChartsEmbeddableApi; /** * Optional fields selected using anomaly charts */ data?: MlEntityField[]; } -export type OpenInAnomalyExplorerBaseActionApi = Partial< - HasParentApi & PublishesUnifiedSearch & { jobIds: JobId[] } ->; - -export type OpenInAnomalyExplorerFromSwimLaneActionApi = HasType & - OpenInAnomalyExplorerBaseActionApi & - SwimLaneDrilldownApi; - -export type OpenInAnomalyExplorerFromAnomalyChartActionApi = - HasType & - OpenInAnomalyExplorerBaseActionApi & - AnomalyChartsFieldSelectionApi; - export const OPEN_IN_ANOMALY_EXPLORER_ACTION = 'openInAnomalyExplorerAction'; export function isSwimLaneEmbeddableContext( @@ -93,17 +62,17 @@ export function isAnomalyChartsEmbeddableContext( ); } -export const isApiCompatible = (api: unknown | null): api is OpenInAnomalyExplorerBaseActionApi => - Boolean(apiHasType(api)); - -const getTimeRange = (embeddable: OpenInAnomalyExplorerBaseActionApi): TimeRange | undefined => { +const getTimeRange = (embeddable: MlEmbeddableBaseApi): TimeRange | undefined => { return embeddable.timeRange$?.getValue() ?? embeddable.parentApi?.timeRange$?.getValue(); }; export function createOpenInExplorerAction(getStartServices: MlCoreSetup['getStartServices']) { - return createAction({ + return createAction< + OpenInAnomalyExplorerSwimLaneActionContext | OpenInAnomalyExplorerAnomalyChartsActionContext + >({ id: 'open-in-anomaly-explorer', type: OPEN_IN_ANOMALY_EXPLORER_ACTION, + order: 40, getIconType(): string { return 'visTable'; }, From ac4b1846fbcbed97540ea63af576aa0d3e02dce7 Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Wed, 20 Mar 2024 17:32:57 +0100 Subject: [PATCH 2/9] fix register action --- .../ui_actions/edit_swimlane_panel_action.tsx | 8 ++--- x-pack/plugins/ml/public/ui_actions/index.ts | 29 +++++++++---------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx b/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx index c1e56ec385703..fdc43f11e6ec9 100644 --- a/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx @@ -10,10 +10,7 @@ import type { EmbeddableApiContext } from '@kbn/presentation-publishing'; import { createAction, IncompatibleActionError } from '@kbn/ui-actions-plugin/public'; import type { AnomalySwimLaneEmbeddableApi } from '../embeddables/anomaly_swimlane/types'; import type { MlCoreSetup } from '../plugin'; -import { - isAnomalyChartsEmbeddableContext, - isSwimLaneEmbeddableContext, -} from './open_in_anomaly_explorer_action'; +import { isSwimLaneEmbeddableContext } from './open_in_anomaly_explorer_action'; export const EDIT_SWIMLANE_PANEL_ACTION = 'editSwimlanePanelAction'; @@ -61,8 +58,7 @@ export function createEditSwimlanePanelAction(getStartServices: MlCoreSetup['get }, async isCompatible(context: EmbeddableApiContext) { return ( - isAnomalyChartsEmbeddableContext(context) && - context.embeddable.viewMode?.getValue() === 'edit' + isSwimLaneEmbeddableContext(context) && context.embeddable.viewMode?.getValue() === 'edit' ); }, }); diff --git a/x-pack/plugins/ml/public/ui_actions/index.ts b/x-pack/plugins/ml/public/ui_actions/index.ts index 03afb2c44c40f..7ef82f1c6f77e 100644 --- a/x-pack/plugins/ml/public/ui_actions/index.ts +++ b/x-pack/plugins/ml/public/ui_actions/index.ts @@ -6,31 +6,31 @@ */ import type { CoreSetup } from '@kbn/core/public'; -import type { UiActionsSetup } from '@kbn/ui-actions-plugin/public'; import { CONTEXT_MENU_TRIGGER } from '@kbn/embeddable-plugin/public'; import { CREATE_PATTERN_ANALYSIS_TO_ML_AD_JOB_TRIGGER } from '@kbn/ml-ui-actions'; +import type { UiActionsSetup } from '@kbn/ui-actions-plugin/public'; +import type { MlPluginStart, MlStartDependencies } from '../plugin'; +import { createApplyEntityFieldFiltersAction } from './apply_entity_filters_action'; +import { createApplyInfluencerFiltersAction } from './apply_influencer_filters_action'; +import { createApplyTimeRangeSelectionAction } from './apply_time_range_action'; +import { createClearSelectionAction } from './clear_selection_action'; +import { createEditAnomalyChartsPanelAction } from './edit_anomaly_charts_panel_action'; import { createEditSwimlanePanelAction } from './edit_swimlane_panel_action'; -import { createOpenInExplorerAction } from './open_in_anomaly_explorer_action'; -import { createVisToADJobAction } from './open_vis_in_ml_action'; import { createCategorizationADJobAction, createCategorizationADJobTrigger, } from './open_create_categorization_job_action'; -import type { MlPluginStart, MlStartDependencies } from '../plugin'; -import { createApplyInfluencerFiltersAction } from './apply_influencer_filters_action'; +import { createOpenInExplorerAction } from './open_in_anomaly_explorer_action'; +import { createVisToADJobAction } from './open_vis_in_ml_action'; import { entityFieldSelectionTrigger, EXPLORER_ENTITY_FIELD_SELECTION_TRIGGER, - SWIM_LANE_SELECTION_TRIGGER, swimLaneSelectionTrigger, + SWIM_LANE_SELECTION_TRIGGER, } from './triggers'; -import { createApplyTimeRangeSelectionAction } from './apply_time_range_action'; -import { createClearSelectionAction } from './clear_selection_action'; -import { createEditAnomalyChartsPanelAction } from './edit_anomaly_charts_panel_action'; -import { createApplyEntityFieldFiltersAction } from './apply_entity_filters_action'; +export { APPLY_INFLUENCER_FILTERS_ACTION } from './apply_influencer_filters_action'; export { APPLY_TIME_RANGE_SELECTION_ACTION } from './apply_time_range_action'; export { EDIT_SWIMLANE_PANEL_ACTION } from './edit_swimlane_panel_action'; -export { APPLY_INFLUENCER_FILTERS_ACTION } from './apply_influencer_filters_action'; export { OPEN_IN_ANOMALY_EXPLORER_ACTION } from './open_in_anomaly_explorer_action'; export { CREATE_LENS_VIS_TO_ML_AD_JOB_ACTION } from './open_vis_in_ml_action'; export { SWIM_LANE_SELECTION_TRIGGER }; @@ -57,13 +57,12 @@ export function registerMlUiActions( uiActions.registerAction(applyEntityFieldFilterAction); uiActions.registerAction(applyTimeRangeSelectionAction); uiActions.registerAction(clearSelectionAction); - uiActions.registerAction(editExplorerPanelAction); uiActions.registerAction(categorizationADJobAction); // Assign triggers - uiActions.attachAction(CONTEXT_MENU_TRIGGER, editSwimlanePanelAction.id); - uiActions.attachAction(CONTEXT_MENU_TRIGGER, editExplorerPanelAction.id); - uiActions.attachAction(CONTEXT_MENU_TRIGGER, openInExplorerAction.id); + uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, editSwimlanePanelAction); + uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, editExplorerPanelAction); + uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, openInExplorerAction); uiActions.registerTrigger(swimLaneSelectionTrigger); uiActions.registerTrigger(entityFieldSelectionTrigger); From 77896c03da5012893ed8be36d0fc3725f11117b8 Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Wed, 20 Mar 2024 22:57:21 +0100 Subject: [PATCH 3/9] update apply-time-range-selection action, refactor --- .../embeddables/anomaly_charts/types.ts | 2 ++ .../anomaly_swimlane_embeddable.tsx | 7 +++++ .../embeddables/anomaly_swimlane/types.ts | 1 + .../ui_actions/apply_time_range_action.tsx | 30 ++++++++++++------- .../ui_actions/edit_swimlane_panel_action.tsx | 11 ++++--- .../open_in_anomaly_explorer_action.tsx | 14 +++++---- 6 files changed, 45 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_charts/types.ts b/x-pack/plugins/ml/public/embeddables/anomaly_charts/types.ts index f8b1562884e8e..0e9e71c22f1cf 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_charts/types.ts +++ b/x-pack/plugins/ml/public/embeddables/anomaly_charts/types.ts @@ -7,10 +7,12 @@ import type { MlEntityField } from '@kbn/ml-anomaly-utils'; import type { HasType, PublishingSubject } from '@kbn/presentation-publishing'; +import type { JobId } from '../../shared'; import type { AnomalyExplorerChartsEmbeddableType } from '../constants'; import type { MlEmbeddableBaseApi } from '../types'; export interface AnomalyChartsFieldSelectionApi { + jobIds: JobId[]; entityFields: PublishingSubject; } diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx index 9e8a88c1defd9..6d2fe36e75df4 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx @@ -49,6 +49,7 @@ export class AnomalySwimlaneEmbeddable extends AnomalyDetectionEmbeddable< public swimlaneType: BehaviorSubject; public perPage: BehaviorSubject; public fromPage: BehaviorSubject; + public interval: BehaviorSubject; private apiSubscriptions = new Subscription(); @@ -82,6 +83,12 @@ export class AnomalySwimlaneEmbeddable extends AnomalyDetectionEmbeddable< this, 'fromPage' ); + + this.interval = embeddableOutputToSubject( + this.apiSubscriptions, + this, + 'interval' + ); } public updateUserInput(update: AnomalySwimlaneEmbeddableUserInput) { diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts index 82728867e7be0..542908d451310 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts @@ -17,6 +17,7 @@ export interface AnomalySwimLaneComponentApi { viewBy: PublishingSubject; perPage: PublishingSubject; fromPage: PublishingSubject; + interval: PublishingSubject; updateUserInput: (input: AnomalySwimlaneEmbeddableUserInput) => void; } diff --git a/x-pack/plugins/ml/public/ui_actions/apply_time_range_action.tsx b/x-pack/plugins/ml/public/ui_actions/apply_time_range_action.tsx index 2b6071db2388c..5d556b9e0f4ea 100644 --- a/x-pack/plugins/ml/public/ui_actions/apply_time_range_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/apply_time_range_action.tsx @@ -5,22 +5,32 @@ * 2.0. */ +import { DASHBOARD_APP_ID } from '@kbn/dashboard-plugin/public'; import { i18n } from '@kbn/i18n'; -import moment from 'moment'; +import type { EmbeddableApiContext } from '@kbn/presentation-publishing'; import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public'; -import { DASHBOARD_APP_ID } from '@kbn/dashboard-plugin/public'; +import moment from 'moment'; import { firstValueFrom } from 'rxjs'; +import type { AppStateSelectedCells } from '../application/explorer/explorer_utils'; +import type { AnomalySwimLaneEmbeddableApi } from '../embeddables/anomaly_swimlane/types'; import type { MlCoreSetup } from '../plugin'; -import type { SwimLaneDrilldownContext } from '../embeddables'; -import { ANOMALY_SWIMLANE_EMBEDDABLE_TYPE } from '../embeddables'; +import { isSwimLaneEmbeddableContext } from './open_in_anomaly_explorer_action'; export const APPLY_TIME_RANGE_SELECTION_ACTION = 'applyTimeRangeSelectionAction'; const supportedApps = [DASHBOARD_APP_ID]; +export interface ApplyTimeRangeSelectionActionContext extends EmbeddableApiContext { + embeddable: AnomalySwimLaneEmbeddableApi; + /** + * Optional data provided by swim lane selection + */ + data?: AppStateSelectedCells; +} + export function createApplyTimeRangeSelectionAction( getStartServices: MlCoreSetup['getStartServices'] -): UiActionsActionDefinition { +): UiActionsActionDefinition { return { id: 'apply-time-range-selection', type: APPLY_TIME_RANGE_SELECTION_ACTION, @@ -37,9 +47,9 @@ export function createApplyTimeRangeSelectionAction( } const [, pluginStart] = await getStartServices(); const timefilter = pluginStart.data.query.timefilter.timefilter; - const { interval } = embeddable.getOutput(); + const { interval } = embeddable; - if (!interval) { + if (!interval.getValue()) { throw new Error('Interval is required to set a time range'); } @@ -53,12 +63,12 @@ export function createApplyTimeRangeSelectionAction( mode: 'absolute', }); }, - async isCompatible({ embeddable, data }) { + async isCompatible(context) { const [{ application }] = await getStartServices(); const appId = await firstValueFrom(application.currentAppId$); return ( - embeddable.type === ANOMALY_SWIMLANE_EMBEDDABLE_TYPE && - data !== undefined && + isSwimLaneEmbeddableContext(context) && + context.data !== undefined && supportedApps.includes(appId!) ); }, diff --git a/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx b/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx index fdc43f11e6ec9..2620d3ba2b417 100644 --- a/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx @@ -7,7 +7,8 @@ import { i18n } from '@kbn/i18n'; import type { EmbeddableApiContext } from '@kbn/presentation-publishing'; -import { createAction, IncompatibleActionError } from '@kbn/ui-actions-plugin/public'; +import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public'; +import { IncompatibleActionError } from '@kbn/ui-actions-plugin/public'; import type { AnomalySwimLaneEmbeddableApi } from '../embeddables/anomaly_swimlane/types'; import type { MlCoreSetup } from '../plugin'; import { isSwimLaneEmbeddableContext } from './open_in_anomaly_explorer_action'; @@ -18,8 +19,10 @@ export type EditSwimlanePanelActionContext = EmbeddableApiContext & { embeddable: AnomalySwimLaneEmbeddableApi; }; -export function createEditSwimlanePanelAction(getStartServices: MlCoreSetup['getStartServices']) { - return createAction({ +export function createEditSwimlanePanelAction( + getStartServices: MlCoreSetup['getStartServices'] +): UiActionsActionDefinition { + return { id: 'edit-anomaly-swimlane', type: EDIT_SWIMLANE_PANEL_ACTION, order: 50, @@ -61,5 +64,5 @@ export function createEditSwimlanePanelAction(getStartServices: MlCoreSetup['get isSwimLaneEmbeddableContext(context) && context.embeddable.viewMode?.getValue() === 'edit' ); }, - }); + }; } diff --git a/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx b/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx index 60ce4b272a3bd..cd764cfb48d23 100644 --- a/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx @@ -12,7 +12,7 @@ import { ML_ENTITY_FIELD_OPERATIONS } from '@kbn/ml-anomaly-utils'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; import type { EmbeddableApiContext } from '@kbn/presentation-publishing'; import { apiIsOfType } from '@kbn/presentation-publishing'; -import { createAction } from '@kbn/ui-actions-plugin/public'; +import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public'; import type { SerializableRecord } from '@kbn/utility-types'; import { ML_APP_LOCATOR } from '../../common/constants/locator'; import type { ExplorerAppState } from '../../common/types/locator'; @@ -66,10 +66,12 @@ const getTimeRange = (embeddable: MlEmbeddableBaseApi): TimeRange | undefined => return embeddable.timeRange$?.getValue() ?? embeddable.parentApi?.timeRange$?.getValue(); }; -export function createOpenInExplorerAction(getStartServices: MlCoreSetup['getStartServices']) { - return createAction< - OpenInAnomalyExplorerSwimLaneActionContext | OpenInAnomalyExplorerAnomalyChartsActionContext - >({ +export function createOpenInExplorerAction( + getStartServices: MlCoreSetup['getStartServices'] +): UiActionsActionDefinition< + OpenInAnomalyExplorerSwimLaneActionContext | OpenInAnomalyExplorerAnomalyChartsActionContext +> { + return { id: 'open-in-anomaly-explorer', type: OPEN_IN_ANOMALY_EXPLORER_ACTION, order: 40, @@ -168,5 +170,5 @@ export function createOpenInExplorerAction(getStartServices: MlCoreSetup['getSta async isCompatible(context: EmbeddableApiContext) { return isSwimLaneEmbeddableContext(context) || isAnomalyChartsEmbeddableContext(context); }, - }); + }; } From 9be954f9d31071a529f689ed71cd783dc3b70907 Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Thu, 21 Mar 2024 13:27:22 +0100 Subject: [PATCH 4/9] fix jobIds input --- .../anomaly_charts_embeddable.tsx | 8 ++++++++ .../public/embeddables/anomaly_charts/types.ts | 2 +- .../anomaly_swimlane_embeddable.tsx | 17 ++++++++++++----- .../embeddables/anomaly_swimlane/types.ts | 2 +- .../common/anomaly_detection_embeddable.ts | 10 +++++----- .../ui_actions/edit_swimlane_panel_action.tsx | 2 +- .../open_in_anomaly_explorer_action.tsx | 4 ++-- 7 files changed, 30 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx index 1b8e77514e108..ded0f536ae96a 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx @@ -12,6 +12,7 @@ import { i18n } from '@kbn/i18n'; import { Subject, Subscription, type BehaviorSubject } from 'rxjs'; import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import type { IContainer } from '@kbn/embeddable-plugin/public'; +import { embeddableInputToSubject } from '@kbn/embeddable-plugin/public'; import { embeddableOutputToSubject } from '@kbn/embeddable-plugin/public'; import type { MlEntityField } from '@kbn/ml-anomaly-utils'; import { EmbeddableAnomalyChartsContainer } from './embeddable_anomaly_charts_container_lazy'; @@ -43,6 +44,7 @@ export class AnomalyChartsEmbeddable extends AnomalyDetectionEmbeddable< public readonly type: string = ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE; // API + public readonly jobIds: BehaviorSubject; public entityFields: BehaviorSubject; private apiSubscriptions = new Subscription(); @@ -54,6 +56,12 @@ export class AnomalyChartsEmbeddable extends AnomalyDetectionEmbeddable< ) { super(initialInput, services[2].anomalyDetectorService, services[1].data.dataViews, parent); + this.jobIds = embeddableInputToSubject( + this.apiSubscriptions, + this, + 'jobIds' + ); + this.entityFields = embeddableOutputToSubject( this.apiSubscriptions, this, diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_charts/types.ts b/x-pack/plugins/ml/public/embeddables/anomaly_charts/types.ts index 0e9e71c22f1cf..8f85987c275b2 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_charts/types.ts +++ b/x-pack/plugins/ml/public/embeddables/anomaly_charts/types.ts @@ -12,7 +12,7 @@ import type { AnomalyExplorerChartsEmbeddableType } from '../constants'; import type { MlEmbeddableBaseApi } from '../types'; export interface AnomalyChartsFieldSelectionApi { - jobIds: JobId[]; + jobIds: PublishingSubject; entityFields: PublishingSubject; } diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx index 6d2fe36e75df4..6e5a8a02ac35e 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx @@ -45,11 +45,12 @@ export class AnomalySwimlaneEmbeddable extends AnomalyDetectionEmbeddable< public readonly type: string = ANOMALY_SWIMLANE_EMBEDDABLE_TYPE; // API - public viewBy: BehaviorSubject; - public swimlaneType: BehaviorSubject; - public perPage: BehaviorSubject; - public fromPage: BehaviorSubject; - public interval: BehaviorSubject; + public readonly jobIds: BehaviorSubject; + public readonly viewBy: BehaviorSubject; + public readonly swimlaneType: BehaviorSubject; + public readonly perPage: BehaviorSubject; + public readonly fromPage: BehaviorSubject; + public readonly interval: BehaviorSubject; private apiSubscriptions = new Subscription(); @@ -60,6 +61,12 @@ export class AnomalySwimlaneEmbeddable extends AnomalyDetectionEmbeddable< ) { super(initialInput, services[2].anomalyDetectorService, services[1].data.dataViews, parent); + this.jobIds = embeddableInputToSubject( + this.apiSubscriptions, + this, + 'jobIds' + ); + this.viewBy = embeddableInputToSubject( this.apiSubscriptions, this, diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts index 542908d451310..1b96f60597a5f 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts @@ -12,7 +12,7 @@ import type { AnomalySwimLaneEmbeddableType } from '../constants'; import type { AnomalySwimlaneEmbeddableUserInput, MlEmbeddableBaseApi } from '../types'; export interface AnomalySwimLaneComponentApi { - jobIds: JobId[]; + jobIds: PublishingSubject; swimlaneType: PublishingSubject; viewBy: PublishingSubject; perPage: PublishingSubject; diff --git a/x-pack/plugins/ml/public/embeddables/common/anomaly_detection_embeddable.ts b/x-pack/plugins/ml/public/embeddables/common/anomaly_detection_embeddable.ts index 08c00273c44a0..84a03b05e869f 100644 --- a/x-pack/plugins/ml/public/embeddables/common/anomaly_detection_embeddable.ts +++ b/x-pack/plugins/ml/public/embeddables/common/anomaly_detection_embeddable.ts @@ -5,14 +5,15 @@ * 2.0. */ +import { type DataView } from '@kbn/data-views-plugin/common'; +import { type DataViewsContract } from '@kbn/data-views-plugin/public'; import { Embeddable, type EmbeddableInput, type EmbeddableOutput, type IContainer, } from '@kbn/embeddable-plugin/public'; -import { type DataView } from '@kbn/data-views-plugin/common'; -import { type DataViewsContract } from '@kbn/data-views-plugin/public'; +import type { BehaviorSubject } from 'rxjs'; import { firstValueFrom } from 'rxjs'; import { type AnomalyDetectorService } from '../../application/services/anomaly_detector_service'; import type { JobId } from '../../shared'; @@ -28,7 +29,8 @@ export abstract class AnomalyDetectionEmbeddable< // Need to defer embeddable load in order to resolve data views deferEmbeddableLoad = true; - public jobIds: JobId[] = []; + // API + public abstract jobIds: BehaviorSubject; protected constructor( initialInput: Input, @@ -46,8 +48,6 @@ export abstract class AnomalyDetectionEmbeddable< protected async initializeOutput(initialInput: CommonInput) { const { jobIds } = initialInput; - this.jobIds = jobIds; - try { const jobs = await firstValueFrom(this.anomalyDetectorService.getJobs$(jobIds)); diff --git a/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx b/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx index 2620d3ba2b417..db3f9a84476d9 100644 --- a/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx @@ -48,7 +48,7 @@ export function createEditSwimlanePanelAction( const { jobIds, viewBy, swimlaneType, panelTitle } = context.embeddable; const result = await resolveAnomalySwimlaneUserInput(coreStart, deps.data.dataViews, { - jobIds, + jobIds: jobIds.getValue(), swimlaneType: swimlaneType.getValue(), viewBy: viewBy.getValue(), title: panelTitle?.getValue(), diff --git a/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx b/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx index cd764cfb48d23..281873fea3fce 100644 --- a/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx @@ -95,7 +95,7 @@ export function createOpenInExplorerAction( return locator.getUrl({ page: 'explorer', pageState: { - jobIds, + jobIds: jobIds.getValue(), timeRange: getTimeRange(embeddable), mlExplorerSwimlane: { viewByFromPage: fromPage.getValue(), @@ -148,7 +148,7 @@ export function createOpenInExplorerAction( return locator.getUrl({ page: 'explorer', pageState: { - jobIds, + jobIds: jobIds.getValue(), timeRange: getTimeRange(embeddable), // @ts-ignore QueryDslQueryContainer is not compatible with SerializableRecord ...(mlExplorerFilter ? ({ mlExplorerFilter } as SerializableRecord) : {}), From f5b541480fe8bf47f575a6b481d1402f16142d5d Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Thu, 21 Mar 2024 13:44:55 +0100 Subject: [PATCH 5/9] edit panel title --- .../ml/public/embeddables/anomaly_swimlane/types.ts | 7 ++++++- .../ml/public/ui_actions/edit_swimlane_panel_action.tsx | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts index 1b96f60597a5f..66070dc2d9b00 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts @@ -5,7 +5,11 @@ * 2.0. */ -import type { HasType, PublishingSubject } from '@kbn/presentation-publishing'; +import type { + HasType, + PublishesWritablePanelTitle, + PublishingSubject, +} from '@kbn/presentation-publishing'; import type { SwimlaneType } from '../../application/explorer/explorer_constants'; import type { JobId } from '../../shared'; import type { AnomalySwimLaneEmbeddableType } from '../constants'; @@ -22,5 +26,6 @@ export interface AnomalySwimLaneComponentApi { } export type AnomalySwimLaneEmbeddableApi = HasType & + PublishesWritablePanelTitle & MlEmbeddableBaseApi & AnomalySwimLaneComponentApi; diff --git a/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx b/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx index db3f9a84476d9..2e43b202123b7 100644 --- a/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx @@ -55,6 +55,7 @@ export function createEditSwimlanePanelAction( }); context.embeddable.updateUserInput(result); + context.embeddable.setPanelTitle(result.panelTitle); } catch (e) { return Promise.reject(); } From 9ea94020d04b1bed650e1fa00cc8d35a05494fbe Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Thu, 21 Mar 2024 15:52:06 +0100 Subject: [PATCH 6/9] set title on init --- .../anomaly_swimlane_embeddable_factory.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.ts b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.ts index a9ab9c9f3424a..ebab6f5356994 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.ts +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.ts @@ -56,7 +56,12 @@ export class AnomalySwimlaneEmbeddableFactory try { const { resolveAnomalySwimlaneUserInput } = await import('./anomaly_swimlane_setup_flyout'); - return await resolveAnomalySwimlaneUserInput(coreStart, deps.data.dataViews); + const userInput = await resolveAnomalySwimlaneUserInput(coreStart, deps.data.dataViews); + + return { + ...userInput, + title: userInput.panelTitle, + }; } catch (e) { return Promise.reject(); } From 8309256e0dc0f6fed23bfe417c03ccd481c247f4 Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Thu, 21 Mar 2024 19:04:08 +0100 Subject: [PATCH 7/9] adjust apply_influencer_filters_action, refactor --- .../embeddables/anomaly_swimlane/types.ts | 14 +++++++++++ .../apply_influencer_filters_action.tsx | 23 ++++++++++--------- .../ui_actions/apply_time_range_action.tsx | 2 +- .../ui_actions/edit_swimlane_panel_action.tsx | 2 +- x-pack/plugins/ml/public/ui_actions/index.ts | 2 -- .../open_in_anomaly_explorer_action.tsx | 15 ++---------- 6 files changed, 30 insertions(+), 28 deletions(-) diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts index 66070dc2d9b00..e5c765abaf3ce 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts @@ -10,9 +10,12 @@ import type { PublishesWritablePanelTitle, PublishingSubject, } from '@kbn/presentation-publishing'; +import { apiIsOfType } from '@kbn/presentation-publishing'; +import { isPopulatedObject } from '@kbn/ml-is-populated-object'; import type { SwimlaneType } from '../../application/explorer/explorer_constants'; import type { JobId } from '../../shared'; import type { AnomalySwimLaneEmbeddableType } from '../constants'; +import { ANOMALY_SWIMLANE_EMBEDDABLE_TYPE } from '../constants'; import type { AnomalySwimlaneEmbeddableUserInput, MlEmbeddableBaseApi } from '../types'; export interface AnomalySwimLaneComponentApi { @@ -29,3 +32,14 @@ export type AnomalySwimLaneEmbeddableApi = HasType Date: Thu, 21 Mar 2024 19:07:04 +0100 Subject: [PATCH 8/9] replace embeddable api types with interfaces --- .../ml/public/embeddables/anomaly_charts/types.ts | 7 ++++--- .../ml/public/embeddables/anomaly_swimlane/types.ts | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_charts/types.ts b/x-pack/plugins/ml/public/embeddables/anomaly_charts/types.ts index 8f85987c275b2..198602b836c1a 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_charts/types.ts +++ b/x-pack/plugins/ml/public/embeddables/anomaly_charts/types.ts @@ -16,6 +16,7 @@ export interface AnomalyChartsFieldSelectionApi { entityFields: PublishingSubject; } -export type AnomalyChartsEmbeddableApi = HasType & - MlEmbeddableBaseApi & - AnomalyChartsFieldSelectionApi; +export interface AnomalyChartsEmbeddableApi + extends HasType, + MlEmbeddableBaseApi, + AnomalyChartsFieldSelectionApi {} diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts index e5c765abaf3ce..618f61fe73c89 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts @@ -28,10 +28,11 @@ export interface AnomalySwimLaneComponentApi { updateUserInput: (input: AnomalySwimlaneEmbeddableUserInput) => void; } -export type AnomalySwimLaneEmbeddableApi = HasType & - PublishesWritablePanelTitle & - MlEmbeddableBaseApi & - AnomalySwimLaneComponentApi; +export interface AnomalySwimLaneEmbeddableApi + extends HasType, + PublishesWritablePanelTitle, + MlEmbeddableBaseApi, + AnomalySwimLaneComponentApi {} export interface AnomalySwimLaneActionContext { embeddable: AnomalySwimLaneEmbeddableApi; From 89cc3dc2106b660b6f21a322989a2a5a546b5c90 Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Fri, 22 Mar 2024 10:23:04 +0100 Subject: [PATCH 9/9] fix types, refactor type guards --- .../embeddables/anomaly_swimlane/types.ts | 2 ++ x-pack/plugins/ml/public/embeddables/types.ts | 6 +----- .../apply_influencer_filters_action.tsx | 4 ++-- .../ui_actions/apply_time_range_action.tsx | 8 ++------ .../plugins/ml/public/ui_actions/triggers.ts | 18 ++++++++++++++++++ 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts index 618f61fe73c89..bb9548f78f61a 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/types.ts @@ -17,6 +17,7 @@ import type { JobId } from '../../shared'; import type { AnomalySwimLaneEmbeddableType } from '../constants'; import { ANOMALY_SWIMLANE_EMBEDDABLE_TYPE } from '../constants'; import type { AnomalySwimlaneEmbeddableUserInput, MlEmbeddableBaseApi } from '../types'; +import type { AppStateSelectedCells } from '../../application/explorer/explorer_utils'; export interface AnomalySwimLaneComponentApi { jobIds: PublishingSubject; @@ -36,6 +37,7 @@ export interface AnomalySwimLaneEmbeddableApi export interface AnomalySwimLaneActionContext { embeddable: AnomalySwimLaneEmbeddableApi; + data?: AppStateSelectedCells; } export function isSwimLaneEmbeddableContext(arg: unknown): arg is AnomalySwimLaneActionContext { diff --git a/x-pack/plugins/ml/public/embeddables/types.ts b/x-pack/plugins/ml/public/embeddables/types.ts index 8c8359c6a812e..14ee0e7c6d444 100644 --- a/x-pack/plugins/ml/public/embeddables/types.ts +++ b/x-pack/plugins/ml/public/embeddables/types.ts @@ -15,7 +15,6 @@ import type { EmbeddableApiContext, HasParentApi, HasType, - PublishesPanelTitle, PublishesUnifiedSearch, PublishesViewMode, } from '@kbn/presentation-publishing'; @@ -39,10 +38,7 @@ import type { } from './constants'; export type MlEmbeddableBaseApi = Partial< - HasParentApi & - PublishesViewMode & - PublishesUnifiedSearch & - PublishesPanelTitle + HasParentApi & PublishesViewMode & PublishesUnifiedSearch >; /** Manual input by the user */ diff --git a/x-pack/plugins/ml/public/ui_actions/apply_influencer_filters_action.tsx b/x-pack/plugins/ml/public/ui_actions/apply_influencer_filters_action.tsx index 6a05d6c4b30cf..b2d785bf6dab3 100644 --- a/x-pack/plugins/ml/public/ui_actions/apply_influencer_filters_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/apply_influencer_filters_action.tsx @@ -12,7 +12,7 @@ import { i18n } from '@kbn/i18n'; import type { EmbeddableApiContext } from '@kbn/presentation-publishing'; import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public'; import { firstValueFrom } from 'rxjs'; -import { isSwimLaneEmbeddableContext } from '../embeddables/anomaly_swimlane/types'; +import { isAnomalySwimlaneSelectionTriggerContext } from './triggers'; import { SWIMLANE_TYPE, VIEW_BY_JOB_LABEL } from '../application/explorer/explorer_constants'; import type { SwimLaneDrilldownContext } from '../embeddables'; import type { MlCoreSetup } from '../plugin'; @@ -81,7 +81,7 @@ export function createApplyInfluencerFiltersAction( // Only compatible with view by influencer swim lanes and single selection return ( supportedApps.includes(appId!) && - isSwimLaneEmbeddableContext(context) && + isAnomalySwimlaneSelectionTriggerContext(context) && context.data !== undefined && context.data.type === SWIMLANE_TYPE.VIEW_BY && context.data.viewByFieldName !== VIEW_BY_JOB_LABEL && diff --git a/x-pack/plugins/ml/public/ui_actions/apply_time_range_action.tsx b/x-pack/plugins/ml/public/ui_actions/apply_time_range_action.tsx index 08d3cf23e59b5..30dc1b0d54c73 100644 --- a/x-pack/plugins/ml/public/ui_actions/apply_time_range_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/apply_time_range_action.tsx @@ -11,10 +11,10 @@ import type { EmbeddableApiContext } from '@kbn/presentation-publishing'; import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public'; import moment from 'moment'; import { firstValueFrom } from 'rxjs'; +import { isAnomalySwimlaneSelectionTriggerContext } from './triggers'; import type { AppStateSelectedCells } from '../application/explorer/explorer_utils'; import type { AnomalySwimLaneEmbeddableApi } from '../embeddables/anomaly_swimlane/types'; import type { MlCoreSetup } from '../plugin'; -import { isSwimLaneEmbeddableContext } from '../embeddables/anomaly_swimlane/types'; export const APPLY_TIME_RANGE_SELECTION_ACTION = 'applyTimeRangeSelectionAction'; @@ -66,11 +66,7 @@ export function createApplyTimeRangeSelectionAction( async isCompatible(context) { const [{ application }] = await getStartServices(); const appId = await firstValueFrom(application.currentAppId$); - return ( - isSwimLaneEmbeddableContext(context) && - context.data !== undefined && - supportedApps.includes(appId!) - ); + return isAnomalySwimlaneSelectionTriggerContext(context) && supportedApps.includes(appId!); }, }; } diff --git a/x-pack/plugins/ml/public/ui_actions/triggers.ts b/x-pack/plugins/ml/public/ui_actions/triggers.ts index d13af630388e3..049f8544f0e95 100644 --- a/x-pack/plugins/ml/public/ui_actions/triggers.ts +++ b/x-pack/plugins/ml/public/ui_actions/triggers.ts @@ -6,6 +6,10 @@ */ import type { Trigger } from '@kbn/ui-actions-plugin/public'; +import type { EmbeddableApiContext } from '@kbn/presentation-publishing'; +import type { AppStateSelectedCells } from '../application/explorer/explorer_utils'; +import type { AnomalySwimLaneEmbeddableApi } from '../embeddables/anomaly_swimlane/types'; +import { isSwimLaneEmbeddableContext } from '../embeddables/anomaly_swimlane/types'; export const SWIM_LANE_SELECTION_TRIGGER = 'SWIM_LANE_SELECTION_TRIGGER'; @@ -25,3 +29,17 @@ export const entityFieldSelectionTrigger: Trigger = { title: '', description: 'Entity field selection triggered', }; + +export interface AnomalySwimLaneSelectionTriggerContext extends EmbeddableApiContext { + embeddable: AnomalySwimLaneEmbeddableApi; + /** + * Data provided by swim lane selection + */ + data: AppStateSelectedCells; +} + +export const isAnomalySwimlaneSelectionTriggerContext = ( + context: unknown +): context is AnomalySwimLaneSelectionTriggerContext => { + return isSwimLaneEmbeddableContext(context) && context.data !== undefined; +};