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 f12eb4af4d1e1..1bacf9679cdaa 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 @@ -7,105 +7,49 @@ import React from 'react'; import { CoreStart } from 'kibana/public'; -import moment from 'moment'; -import { takeUntil } from 'rxjs/operators'; -import { from } from 'rxjs'; import { VIEW_BY_JOB_LABEL } from '../../application/explorer/explorer_constants'; -import { - KibanaContextProvider, - toMountPoint, -} from '../../../../../../src/plugins/kibana_react/public'; +import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public'; import { AnomalySwimlaneInitializer } from './anomaly_swimlane_initializer'; -import { JobSelectorFlyoutContent } from '../../application/components/job_selector/job_selector_flyout'; import { AnomalyDetectorService } from '../../application/services/anomaly_detector_service'; -import { getInitialGroupsMap } from '../../application/components/job_selector/job_selector'; import { getDefaultPanelTitle } from './anomaly_swimlane_embeddable'; -import { getMlGlobalServices } from '../../application/app'; import { HttpService } from '../../application/services/http_service'; -import { DashboardConstants } from '../../../../../../src/plugins/dashboard/public'; import { AnomalySwimlaneEmbeddableInput } from '..'; +import { resolveJobSelection } from '../common/resolve_job_selection'; export async function resolveAnomalySwimlaneUserInput( coreStart: CoreStart, input?: AnomalySwimlaneEmbeddableInput ): Promise> { - const { - http, - uiSettings, - overlays, - application: { currentAppId$ }, - } = coreStart; + const { http, overlays } = coreStart; const anomalyDetectorService = new AnomalyDetectorService(new HttpService(http)); return new Promise(async (resolve, reject) => { - const maps = { - groupsMap: getInitialGroupsMap([]), - jobsMap: {}, - }; + const { jobIds } = await resolveJobSelection(coreStart, input?.jobIds); - const tzConfig = uiSettings.get('dateFormat:tz'); - const dateFormatTz = tzConfig !== 'Browser' ? tzConfig : moment.tz.guess(); + const title = input?.title ?? getDefaultPanelTitle(jobIds); - const selectedIds = input?.jobIds; + const jobs = await anomalyDetectorService.getJobs$(jobIds).toPromise(); - const flyoutSession = coreStart.overlays.openFlyout( - toMountPoint( - - { - flyoutSession.close(); - reject(); - }} - onSelectionConfirmed={async ({ jobIds, groups }) => { - const title = input?.title ?? getDefaultPanelTitle(jobIds); - - const jobs = await anomalyDetectorService.getJobs$(jobIds).toPromise(); - - const influencers = anomalyDetectorService.extractInfluencers(jobs); - influencers.push(VIEW_BY_JOB_LABEL); + const influencers = anomalyDetectorService.extractInfluencers(jobs); + influencers.push(VIEW_BY_JOB_LABEL); - await flyoutSession.close(); - - const modalSession = overlays.openModal( - toMountPoint( - { - modalSession.close(); - resolve({ jobIds, title: panelTitle, swimlaneType, viewBy }); - }} - onCancel={() => { - modalSession.close(); - reject(); - }} - /> - ) - ); - }} - maps={maps} - /> - - ), - { - 'data-test-subj': 'mlFlyoutJobSelector', - ownFocus: true, - closeButtonAriaLabel: 'jobSelectorFlyout', - } + const modalSession = overlays.openModal( + toMountPoint( + { + modalSession.close(); + resolve({ jobIds, title: panelTitle, swimlaneType, viewBy }); + }} + onCancel={() => { + modalSession.close(); + reject(); + }} + /> + ) ); - - // Close the flyout when user navigates out of the dashboard plugin - currentAppId$.pipe(takeUntil(from(flyoutSession.onClose))).subscribe((appId) => { - if (appId !== DashboardConstants.DASHBOARDS_ID) { - flyoutSession.close(); - } - }); }); } diff --git a/x-pack/plugins/ml/public/embeddables/common/resolve_job_selection.tsx b/x-pack/plugins/ml/public/embeddables/common/resolve_job_selection.tsx new file mode 100644 index 0000000000000..8499ab624f790 --- /dev/null +++ b/x-pack/plugins/ml/public/embeddables/common/resolve_job_selection.tsx @@ -0,0 +1,85 @@ +/* + * 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 { CoreStart } from 'kibana/public'; +import moment from 'moment'; +import { takeUntil } from 'rxjs/operators'; +import { from } from 'rxjs'; +import React from 'react'; +import { getInitialGroupsMap } from '../../application/components/job_selector/job_selector'; +import { + KibanaContextProvider, + toMountPoint, +} from '../../../../../../src/plugins/kibana_react/public'; +import { getMlGlobalServices } from '../../application/app'; +import { JobSelectorFlyoutContent } from '../../application/components/job_selector/job_selector_flyout'; +import { DashboardConstants } from '../../../../../../src/plugins/dashboard/public'; +import { JobId } from '../../../common/types/anomaly_detection_jobs'; + +/** + * Handles Anomaly detection jobs selection by a user. + * Intended to use independently of the ML app context, + * for instance on the dashboard for embeddables initialization. + * + * @param coreStart + * @param selectedJobIds + */ +export async function resolveJobSelection( + coreStart: CoreStart, + selectedJobIds?: JobId[] +): Promise<{ jobIds: string[]; groups: Array<{ groupId: string; jobIds: string[] }> }> { + const { + http, + uiSettings, + application: { currentAppId$ }, + } = coreStart; + + return new Promise(async (resolve, reject) => { + const maps = { + groupsMap: getInitialGroupsMap([]), + jobsMap: {}, + }; + + const tzConfig = uiSettings.get('dateFormat:tz'); + const dateFormatTz = tzConfig !== 'Browser' ? tzConfig : moment.tz.guess(); + + const flyoutSession = coreStart.overlays.openFlyout( + toMountPoint( + + { + flyoutSession.close(); + reject(); + }} + onSelectionConfirmed={async ({ jobIds, groups }) => { + await flyoutSession.close(); + resolve({ jobIds, groups }); + }} + maps={maps} + /> + + ), + { + 'data-test-subj': 'mlFlyoutJobSelector', + ownFocus: true, + closeButtonAriaLabel: 'jobSelectorFlyout', + } + ); + + // Close the flyout when user navigates out of the dashboard plugin + currentAppId$.pipe(takeUntil(from(flyoutSession.onClose))).subscribe((appId) => { + if (appId !== DashboardConstants.DASHBOARDS_ID) { + flyoutSession.close(); + } + }); + }); +}