Skip to content

Commit

Permalink
[ML] Extract job selection resolver (#95394)
Browse files Browse the repository at this point in the history
  • Loading branch information
darnautov authored Mar 25, 2021
1 parent e0534e4 commit a8b04d7
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<Partial<AnomalySwimlaneEmbeddableInput>> {
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(
<KibanaContextProvider services={{ ...coreStart, mlServices: getMlGlobalServices(http) }}>
<JobSelectorFlyoutContent
selectedIds={selectedIds}
withTimeRangeSelector={false}
dateFormatTz={dateFormatTz}
singleSelection={false}
timeseriesOnly={true}
onFlyoutClose={() => {
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(
<AnomalySwimlaneInitializer
defaultTitle={title}
influencers={influencers}
initialInput={input}
onCreate={({ panelTitle, viewBy, swimlaneType }) => {
modalSession.close();
resolve({ jobIds, title: panelTitle, swimlaneType, viewBy });
}}
onCancel={() => {
modalSession.close();
reject();
}}
/>
)
);
}}
maps={maps}
/>
</KibanaContextProvider>
),
{
'data-test-subj': 'mlFlyoutJobSelector',
ownFocus: true,
closeButtonAriaLabel: 'jobSelectorFlyout',
}
const modalSession = overlays.openModal(
toMountPoint(
<AnomalySwimlaneInitializer
defaultTitle={title}
influencers={influencers}
initialInput={input}
onCreate={({ panelTitle, viewBy, swimlaneType }) => {
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();
}
});
});
}
Original file line number Diff line number Diff line change
@@ -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(
<KibanaContextProvider services={{ ...coreStart, mlServices: getMlGlobalServices(http) }}>
<JobSelectorFlyoutContent
selectedIds={selectedJobIds}
withTimeRangeSelector={false}
dateFormatTz={dateFormatTz}
singleSelection={false}
timeseriesOnly={true}
onFlyoutClose={() => {
flyoutSession.close();
reject();
}}
onSelectionConfirmed={async ({ jobIds, groups }) => {
await flyoutSession.close();
resolve({ jobIds, groups });
}}
maps={maps}
/>
</KibanaContextProvider>
),
{
'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();
}
});
});
}

0 comments on commit a8b04d7

Please sign in to comment.