Skip to content

Commit

Permalink
[ML] Anomaly swim lane embeddable navigation and filter actions (#71082)
Browse files Browse the repository at this point in the history
* [ML] dragSelect as part of ExplorerSwimlane component

* [ML] use wrapper ref

* [ML] rename callback

* [ML] WIP open in anomaly explorer

* [ML] MlUrlGenerator unit tests

* [ML] WIP actions

* [ML] restore pagination

* [ML] fix fromPage on initial load

* [ML] fix cell selection, filter and time range actions

* [ML] update url generator params

* [ML] prevent label text selection on drag select

* [ML] fix types and unit tests

* [ML] fix embeddable init

* [ML] fix swim lane unit tests

* [ML] change action label, use filter action only for single cell click

* [ML] fix time range bounds

* [ML] fix TS issues

* [ML] fix pagination persistence

* [ML] use viewByFrom the embeddable input
  • Loading branch information
darnautov authored Jul 14, 2020
1 parent 0090de0 commit 50f8db7
Show file tree
Hide file tree
Showing 31 changed files with 879 additions and 368 deletions.
2 changes: 1 addition & 1 deletion x-pack/plugins/ml/public/application/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { MlRouter } from './routing';
import { mlApiServicesProvider } from './services/ml_api_service';
import { HttpService } from './services/http_service';

type MlDependencies = MlSetupDependencies & MlStartDependencies;
export type MlDependencies = Omit<MlSetupDependencies, 'share'> & MlStartDependencies;

interface AppProps {
coreStart: CoreStart;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ export const JobSelectorFlyout: FC<JobSelectorFlyoutProps> = ({
ref={flyoutEl}
onClose={onFlyoutClose}
aria-labelledby="jobSelectorFlyout"
size="l"
data-test-subj="mlFlyoutJobSelector"
>
<EuiFlyoutHeader hasBorder>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
*/

import { difference } from 'lodash';
import { useEffect } from 'react';
import { useEffect, useMemo } from 'react';

import { i18n } from '@kbn/i18n';

import { getToastNotifications } from '../../util/dependency_cache';
import { MlJobWithTimeRange } from '../../../../common/types/anomaly_detection_jobs';

import { useUrlState } from '../../util/url_state';

import { getTimeRangeFromSelection } from './job_select_service_utils';
import { useNotifications } from '../../contexts/kibana';

// check that the ids read from the url exist by comparing them to the
// jobs loaded via mlJobsService.
Expand All @@ -25,49 +25,53 @@ function getInvalidJobIds(jobs: MlJobWithTimeRange[], ids: string[]) {
});
}

function warnAboutInvalidJobIds(invalidIds: string[]) {
if (invalidIds.length > 0) {
const toastNotifications = getToastNotifications();
toastNotifications.addWarning(
i18n.translate('xpack.ml.jobSelect.requestedJobsDoesNotExistWarningMessage', {
defaultMessage: `Requested
{invalidIdsLength, plural, one {job {invalidIds} does not exist} other {jobs {invalidIds} do not exist}}`,
values: {
invalidIdsLength: invalidIds.length,
invalidIds: invalidIds.join(),
},
})
);
}
}

export interface JobSelection {
jobIds: string[];
selectedGroups: string[];
}

export const useJobSelection = (jobs: MlJobWithTimeRange[], dateFormatTz: string) => {
export const useJobSelection = (jobs: MlJobWithTimeRange[]) => {
const [globalState, setGlobalState] = useUrlState('_g');
const { toasts: toastNotifications } = useNotifications();

const jobSelection: JobSelection = { jobIds: [], selectedGroups: [] };
const tmpIds = useMemo(() => {
const ids = globalState?.ml?.jobIds || [];
return (typeof ids === 'string' ? [ids] : ids).map((id: string) => String(id));
}, [globalState?.ml?.jobIds]);

const ids = globalState?.ml?.jobIds || [];
const tmpIds = (typeof ids === 'string' ? [ids] : ids).map((id: string) => String(id));
const invalidIds = getInvalidJobIds(jobs, tmpIds);
const validIds = difference(tmpIds, invalidIds);
validIds.sort();
const invalidIds = useMemo(() => {
return getInvalidJobIds(jobs, tmpIds);
}, [tmpIds]);

jobSelection.jobIds = validIds;
jobSelection.selectedGroups = globalState?.ml?.groups ?? [];
const validIds = useMemo(() => {
const res = difference(tmpIds, invalidIds);
res.sort();
return res;
}, [tmpIds, invalidIds]);

const jobSelection: JobSelection = useMemo(() => {
const selectedGroups = globalState?.ml?.groups ?? [];
return { jobIds: validIds, selectedGroups };
}, [validIds, globalState?.ml?.groups]);

useEffect(() => {
warnAboutInvalidJobIds(invalidIds);
if (invalidIds.length > 0) {
toastNotifications.addWarning(
i18n.translate('xpack.ml.jobSelect.requestedJobsDoesNotExistWarningMessage', {
defaultMessage: `Requested
{invalidIdsLength, plural, one {job {invalidIds} does not exist} other {jobs {invalidIds} do not exist}}`,
values: {
invalidIdsLength: invalidIds.length,
invalidIds: invalidIds.join(),
},
})
);
}
}, [invalidIds]);

useEffect(() => {
// if there are no valid ids, warn and then select the first job
if (validIds.length === 0 && jobs.length > 0) {
const toastNotifications = getToastNotifications();
toastNotifications.addWarning(
i18n.translate('xpack.ml.jobSelect.noJobsSelectedWarningMessage', {
defaultMessage: 'No jobs selected, auto selecting first job',
Expand Down

Large diffs are not rendered by default.

Loading

0 comments on commit 50f8db7

Please sign in to comment.