Skip to content

Commit

Permalink
[ML] Persisted URL state for the "Anomaly detection jobs" page (#83149)…
Browse files Browse the repository at this point in the history
… (#83285)

* [ML] table config in the URL state

* [ML] fix job list on the management page

* [ML] store query filter in the URL

* [ML] fix context for the management page

* [ML] update module_list_card.tsx in Logs UI

* [ML] fix unit tests

* [ML] fix unit tests

* [ML] fix unit tests

* [ML] move utils functions

* [ML] url generator to support both job and group ids
  • Loading branch information
darnautov committed Nov 12, 2020
1 parent 801e3c5 commit 8ce70da
Show file tree
Hide file tree
Showing 19 changed files with 391 additions and 325 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ test('MLLink produces the correct URL', async () => {
);

expect(href).toMatchInlineSnapshot(
`"/app/ml/jobs?mlManagement=(groupIds:!(apm),jobId:!(something))&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-5h,to:now-2h))"`
`"/app/ml/jobs?_a=(queryText:'id:(something)%20groups:(apm)')&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-5h,to:now-2h))"`
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@

import { EuiCard, EuiIcon, EuiButtonEmpty, EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import React from 'react';
import React, { useEffect, useState } from 'react';
import { SetupStatus } from '../../../../../common/log_analysis';
import { CreateJobButton, RecreateJobButton } from '../../log_analysis_setup/create_job_button';
import { useLinkProps } from '../../../../hooks/use_link_props';
import { useKibanaContextForPlugin } from '../../../../hooks/use_kibana';
import { mountReactNode } from '../../../../../../../../src/core/public/utils';

export const LogAnalysisModuleListCard: React.FC<{
jobId: string;
Expand All @@ -26,19 +27,46 @@ export const LogAnalysisModuleListCard: React.FC<{
moduleStatus,
onViewSetup,
}) => {
const {
services: {
ml,
application: { navigateToUrl },
notifications: { toasts },
},
} = useKibanaContextForPlugin();

const [viewInMlLink, setViewInMlLink] = useState<string>('');

const getMlUrl = async () => {
if (!ml.urlGenerator) {
toasts.addWarning({
title: mountReactNode(
<FormattedMessage
id="xpack.infra.logs.analysis.mlNotAvailable"
defaultMessage="ML plugin is not available"
/>
),
});
return;
}
setViewInMlLink(await ml.urlGenerator.createUrl({ page: 'jobs', pageState: { jobId } }));
};

useEffect(() => {
getMlUrl();
});

const navigateToMlApp = async () => {
await navigateToUrl(viewInMlLink);
};

const moduleIcon =
moduleStatus.type === 'required' ? (
<EuiIcon size="xxl" type="machineLearningApp" />
) : (
<EuiIcon color="secondary" size="xxl" type="check" />
);

const viewInMlLinkProps = useLinkProps({
app: 'ml',
pathname: '/jobs',
search: { mlManagement: `(jobId:${jobId})` },
});

const moduleSetupButton =
moduleStatus.type === 'required' ? (
<CreateJobButton hasSetupCapabilities={hasSetupCapabilities} onClick={onViewSetup}>
Expand All @@ -50,13 +78,17 @@ export const LogAnalysisModuleListCard: React.FC<{
) : (
<>
<RecreateJobButton hasSetupCapabilities={hasSetupCapabilities} onClick={onViewSetup} />
<EuiSpacer size="xs" />
<EuiButtonEmpty {...viewInMlLinkProps}>
<FormattedMessage
id="xpack.infra.logs.analysis.viewInMlButtonLabel"
defaultMessage="View in Machine Learning"
/>
</EuiButtonEmpty>
{viewInMlLink ? (
<>
<EuiSpacer size="xs" />
<EuiButtonEmpty onClick={navigateToMlApp}>
<FormattedMessage
id="xpack.infra.logs.analysis.viewInMlButtonLabel"
defaultMessage="View in Machine Learning"
/>
</EuiButtonEmpty>
</>
) : null}
</>
);

Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/infra/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type {
ObservabilityPluginStart,
} from '../../observability/public';
import type { SpacesPluginStart } from '../../spaces/public';
import { MlPluginStart } from '../../ml/public';

// Our own setup and start contract values
export type InfraClientSetupExports = void;
Expand All @@ -38,6 +39,7 @@ export interface InfraClientStartDeps {
spaces: SpacesPluginStart;
triggersActionsUi: TriggersAndActionsUIPublicPluginSetup;
usageCollection: UsageCollectionStart;
ml: MlPluginStart;
}

export type InfraClientCoreSetup = CoreSetup<InfraClientStartDeps, InfraClientStartExports>;
Expand Down
22 changes: 21 additions & 1 deletion x-pack/plugins/ml/common/util/string_utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { renderTemplate, getMedianStringLength, stringHash } from './string_utils';
import {
renderTemplate,
getMedianStringLength,
stringHash,
getGroupQueryText,
} from './string_utils';

const strings: string[] = [
'foo',
Expand Down Expand Up @@ -54,4 +59,19 @@ describe('ML - string utils', () => {
expect(hash1).not.toBe(hash2);
});
});

describe('getGroupQueryText', () => {
const groupIdOne = 'test_group_id_1';
const groupIdTwo = 'test_group_id_2';

it('should get query string for selected group ids', () => {
const actual = getGroupQueryText([groupIdOne, groupIdTwo]);
expect(actual).toBe(`groups:(${groupIdOne} or ${groupIdTwo})`);
});

it('should get query string for selected group id', () => {
const actual = getGroupQueryText([groupIdOne]);
expect(actual).toBe(`groups:(${groupIdOne})`);
});
});
});
8 changes: 8 additions & 0 deletions x-pack/plugins/ml/common/util/string_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,11 @@ export function stringHash(str: string): number {
}
return hash < 0 ? hash * -2 : hash;
}

export function getGroupQueryText(groupIds: string[]): string {
return `groups:(${groupIds.join(' or ')})`;
}

export function getJobQueryText(jobIds: string | string[]): string {
return Array.isArray(jobIds) ? `id:(${jobIds.join(' OR ')})` : jobIds;
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,13 @@ import { getTaskStateBadge, getJobTypeBadge, useColumns } from './use_columns';
import { ExpandedRow } from './expanded_row';
import { AnalyticStatsBarStats, StatsBar } from '../../../../../components/stats_bar';
import { CreateAnalyticsButton } from '../create_analytics_button';
import {
getSelectedIdFromUrl,
getGroupQueryText,
} from '../../../../../jobs/jobs_list/components/utils';
import { getSelectedIdFromUrl } from '../../../../../jobs/jobs_list/components/utils';
import { SourceSelection } from '../source_selection';
import { filterAnalytics } from '../../../../common/search_bar_filters';
import { AnalyticsEmptyPrompt } from './empty_prompt';
import { useTableSettings } from './use_table_settings';
import { RefreshAnalyticsListButton } from '../refresh_analytics_list_button';
import { getGroupQueryText } from '../../../../../../../common/util/string_utils';

const filters: EuiSearchBarProps['filters'] = [
{
Expand Down

This file was deleted.

Loading

0 comments on commit 8ce70da

Please sign in to comment.