Skip to content

Commit

Permalink
[7.x] [ML] Add Create Data Frame Analytics card to Data Visualizer (#…
Browse files Browse the repository at this point in the history
…91011) (#91202)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
qn895 and kibanamachine authored Feb 14, 2021
1 parent 04d2d39 commit 9a20358
Show file tree
Hide file tree
Showing 15 changed files with 128 additions and 81 deletions.
1 change: 1 addition & 0 deletions x-pack/plugins/ml/common/constants/ml_url_generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const ML_PAGES = {
*/
DATA_VISUALIZER_INDEX_VIEWER: 'jobs/new_job/datavisualizer',
ANOMALY_DETECTION_CREATE_JOB: `jobs/new_job`,
ANOMALY_DETECTION_CREATE_JOB_ADVANCED: `jobs/new_job/advanced`,
ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE: `jobs/new_job/step/job_type`,
ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX: `jobs/new_job/step/index_or_search`,
SETTINGS: 'settings',
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/ml/common/types/ml_url_generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export interface DataVisualizerFileBasedAppState extends Omit<ListingPageUrlStat
export type MlGenericUrlState = MLPageState<
| typeof ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX
| typeof ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import React from 'react';
import PropTypes from 'prop-types';

import { EuiIcon, EuiFlexItem } from '@elastic/eui';
import { CreateJobLinkCard } from '../create_job_link_card';
import { LinkCard } from '../link_card';
import { useMlKibana } from '../../contexts/kibana';

export const RecognizedResult = ({ config, indexPattern, savedSearch }) => {
Expand All @@ -34,7 +34,7 @@ export const RecognizedResult = ({ config, indexPattern, savedSearch }) => {

return (
<EuiFlexItem>
<CreateJobLinkCard
<LinkCard
data-test-subj={`mlRecognizerCard ${config.id}`}
href={href}
title={config.title}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
* 2.0.
*/

export { CreateJobLinkCard } from './create_job_link_card';
export { LinkCard } from './link_card';
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ interface Props {

// Component for rendering a card which links to the Create Job page, displaying an
// icon, card title, description and link.
export const CreateJobLinkCard: FC<Props> = ({
export const LinkCard: FC<Props> = ({
icon,
iconAreaLabel,
title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,15 @@ import React, { FC, useState, useEffect } from 'react';

import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import {
EuiSpacer,
EuiText,
EuiTitle,
EuiFlexGroup,
EuiFlexItem,
EuiCard,
EuiIcon,
} from '@elastic/eui';
import { Link } from 'react-router-dom';
import { CreateJobLinkCard } from '../../../../components/create_job_link_card';
import { EuiSpacer, EuiText, EuiTitle, EuiFlexGroup } from '@elastic/eui';
import { LinkCard } from '../../../../components/link_card';
import { DataRecognizer } from '../../../../components/data_recognizer';
import { ML_PAGES } from '../../../../../../common/constants/ml_url_generator';
import {
DISCOVER_APP_URL_GENERATOR,
DiscoverUrlGeneratorState,
} from '../../../../../../../../../src/plugins/discover/public';
import { useMlKibana } from '../../../../contexts/kibana';
import { useMlKibana, useMlLink } from '../../../../contexts/kibana';
import { isFullLicense } from '../../../../license';
import { checkPermission } from '../../../../capabilities/check_capabilities';
import { mlNodesAvailable } from '../../../../ml_nodes_check';
Expand Down Expand Up @@ -57,12 +48,18 @@ export const ActionsPanel: FC<Props> = ({ indexPattern, searchString, searchQuer
setRecognizerResultsCount(recognizerResults.count);
},
};
const showCreateJob =
isFullLicense() &&
checkPermission('canCreateJob') &&
mlNodesAvailable() &&
indexPattern.timeFieldName !== undefined;
const createJobLink = `/${ML_PAGES.ANOMALY_DETECTION_CREATE_JOB}/advanced?index=${indexPattern.id}`;
const mlAvailable = isFullLicense() && checkPermission('canCreateJob') && mlNodesAvailable();
const showCreateAnomalyDetectionJob = mlAvailable && indexPattern.timeFieldName !== undefined;

const createJobLink = useMlLink({
page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED,
pageState: { index: indexPattern.id },
});

const createDataFrameAnalyticsLink = useMlLink({
page: ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB,
pageState: { index: indexPattern.id },
});

useEffect(() => {
let unmounted = false;
Expand Down Expand Up @@ -95,6 +92,7 @@ export const ActionsPanel: FC<Props> = ({ indexPattern, searchString, searchQuer
setDiscoverLink(discoverUrl);
}
};

getDiscoverUrl();
return () => {
unmounted = true;
Expand All @@ -106,7 +104,7 @@ export const ActionsPanel: FC<Props> = ({ indexPattern, searchString, searchQuer
// controls whether the recognizer section is ultimately displayed.
return (
<div data-test-subj="mlDataVisualizerActionsPanel">
{showCreateJob && (
{mlAvailable && (
<>
<EuiTitle size="s">
<h2>
Expand All @@ -117,50 +115,84 @@ export const ActionsPanel: FC<Props> = ({ indexPattern, searchString, searchQuer
</h2>
</EuiTitle>
<EuiSpacer size="s" />
<div hidden={recognizerResultsCount === 0}>
<EuiText size="s" color="subdued">
<p>
<FormattedMessage
id="xpack.ml.datavisualizer.actionsPanel.selectKnownConfigurationDescription"
defaultMessage="Select known configurations for recognized data:"
/>
</p>
</EuiText>
<EuiSpacer size="m" />
<EuiFlexGroup gutterSize="l" responsive={true} wrap={true}>
<DataRecognizer
indexPattern={indexPattern}
savedSearch={null}
results={recognizerResults}
{showCreateAnomalyDetectionJob && (
<>
<div hidden={recognizerResultsCount === 0}>
<EuiText size="s" color="subdued">
<p>
<FormattedMessage
id="xpack.ml.datavisualizer.actionsPanel.selectKnownConfigurationDescription"
defaultMessage="Select known configurations for recognized data:"
/>
</p>
</EuiText>
<EuiSpacer size="m" />
<EuiFlexGroup gutterSize="l" responsive={true} wrap={true}>
<DataRecognizer
indexPattern={indexPattern}
savedSearch={null}
results={recognizerResults}
/>
</EuiFlexGroup>
<EuiSpacer size="l" />
</div>
<EuiText size="s" color="subdued">
<p>
<FormattedMessage
id="xpack.ml.datavisualizer.actionsPanel.createJobDescription"
defaultMessage="Use the Advanced job wizard to create a job to find anomalies in this data:"
/>
</p>
</EuiText>
<EuiSpacer size="m" />
<LinkCard
href={createJobLink}
icon="createAdvancedJob"
title={i18n.translate('xpack.ml.datavisualizer.actionsPanel.advancedTitle', {
defaultMessage: 'Advanced',
})}
description={i18n.translate(
'xpack.ml.datavisualizer.actionsPanel.advancedDescription',
{
defaultMessage:
'Create a job with the full range of options for more advanced use cases',
}
)}
data-test-subj="mlDataVisualizerCreateAdvancedJobCard"
/>
</EuiFlexGroup>
<EuiSpacer size="l" />
</div>
<EuiSpacer size="m" />
</>
)}
</>
)}
{mlAvailable && indexPattern.id !== undefined && createDataFrameAnalyticsLink && (
<>
<EuiText size="s" color="subdued">
<p>
<FormattedMessage
id="xpack.ml.datavisualizer.actionsPanel.createJobDescription"
defaultMessage="Use the Advanced job wizard to create a job to find anomalies in this data:"
id="xpack.ml.datavisualizer.actionsPanel.createDataFrameAnalyticsDescription"
defaultMessage="Use the Data Frame Analytics wizard to perform analyses of your data:"
/>
</p>
</EuiText>
<EuiSpacer size="m" />
<Link to={createJobLink}>
<CreateJobLinkCard
icon="createAdvancedJob"
title={i18n.translate('xpack.ml.datavisualizer.actionsPanel.advancedTitle', {
defaultMessage: 'Advanced',
})}
description={i18n.translate(
'xpack.ml.datavisualizer.actionsPanel.advancedDescription',
{
defaultMessage:
'Use the full range of options to create a job for more advanced use cases',
}
)}
data-test-subj="mlDataVisualizerCreateAdvancedJobCard"
/>
</Link>
<LinkCard
href={createDataFrameAnalyticsLink}
icon="classificationJob"
description={i18n.translate(
'xpack.ml.datavisualizer.actionsPanel.dataframeTypesDescription',
{
defaultMessage: 'Create outlier detection, regression, or classification analytics',
}
)}
title={
<FormattedMessage
id="xpack.ml.datavisualizer.actionsPanel.dataframeAnalyticsTitle"
defaultMessage="Data Frame Analytics"
/>
}
data-test-subj="mlDataVisualizerCreateDataFrameAnalyticsCard"
/>
<EuiSpacer size="m" />
</>
)}
Expand All @@ -176,25 +208,23 @@ export const ActionsPanel: FC<Props> = ({ indexPattern, searchString, searchQuer
</h2>
</EuiTitle>
<EuiSpacer size="m" />
<EuiFlexItem>
<EuiCard
data-test-subj="mlDataVisualizerViewInDiscoverCard"
icon={<EuiIcon size="xxl" type={`discoverApp`} />}
description={i18n.translate(
'xpack.ml.datavisualizer.actionsPanel.viewIndexInDiscoverDescription',
{
defaultMessage: 'Explore index in Discover',
}
)}
title={
<FormattedMessage
id="xpack.ml.datavisualizer.actionsPanel.discoverAppTitle"
defaultMessage="Discover"
/>
<LinkCard
href={discoverLink}
icon="discoverApp"
description={i18n.translate(
'xpack.ml.datavisualizer.actionsPanel.viewIndexInDiscoverDescription',
{
defaultMessage: 'Explore index in Discover',
}
href={discoverLink}
/>
</EuiFlexItem>
)}
title={
<FormattedMessage
id="xpack.ml.datavisualizer.actionsPanel.discoverAppTitle"
defaultMessage="Discover"
/>
}
data-test-subj="mlDataVisualizerViewInDiscoverCard"
/>
</>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { isSavedSearchSavedObject } from '../../../../../../common/types/kibana'
import { DataRecognizer } from '../../../../components/data_recognizer';
import { addItemToRecentlyAccessed } from '../../../../util/recently_accessed';
import { timeBasedIndexCheck } from '../../../../util/index_utils';
import { CreateJobLinkCard } from '../../../../components/create_job_link_card';
import { LinkCard } from '../../../../components/link_card';
import { CategorizationIcon } from './categorization_job_icon';
import { ML_PAGES } from '../../../../../../common/constants/ml_url_generator';
import { useCreateAndNavigateToMlLink } from '../../../../contexts/kibana/use_create_url';
Expand Down Expand Up @@ -257,7 +257,7 @@ export const Page: FC = () => {
<EuiFlexGrid gutterSize="l" columns={4}>
{jobTypes.map(({ onClick, icon, title, description, id }) => (
<EuiFlexItem key={id}>
<CreateJobLinkCard
<LinkCard
data-test-subj={id}
onClick={onClick}
icon={icon.type}
Expand Down Expand Up @@ -294,7 +294,7 @@ export const Page: FC = () => {

<EuiFlexGrid gutterSize="l" columns={4}>
<EuiFlexItem>
<CreateJobLinkCard
<LinkCard
icon="dataVisualizer"
iconAreaLabel={i18n.translate(
'xpack.ml.newJob.wizard.jobType.dataVisualizerAriaLabel',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export class MlUrlGenerator implements UrlGeneratorsDefinition<typeof ML_APP_URL
case ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION:
return createDataFrameAnalyticsExplorationUrl(appBasePath, mlUrlGeneratorState.pageState);
case ML_PAGES.ANOMALY_DETECTION_CREATE_JOB:
case ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED:
case ML_PAGES.DATA_VISUALIZER:
case ML_PAGES.DATA_VISUALIZER_FILE:
case ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export default function ({ getService }: FtrProviderContext) {
await ml.testExecution.logTestStep('displays the actions panel with advanced job card');
await ml.dataVisualizerIndexBased.assertActionsPanelExists();
await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardExists();
await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardExists();

// Note the search is not currently passed to the wizard, just the index.
await ml.testExecution.logTestStep('displays the actions panel with advanced job card');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ export default function ({ getService }: FtrProviderContext) {
await ml.testExecution.logTestStep('should display job cards');
await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardExists();
await ml.dataVisualizerIndexBased.assertRecognizerCardExists(ecExpectedModuleId);
await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardExists();
});

it('should display elements on File Data Visualizer page correctly', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ export default function ({ getService }: FtrProviderContext) {
await ml.testExecution.logTestStep('should not display job cards');
await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardNotExists();
await ml.dataVisualizerIndexBased.assertRecognizerCardNotExists(ecExpectedModuleId);
await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardNotExists();
});

it('should display elements on File Data Visualizer page correctly', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,14 @@ export function MachineLearningDataVisualizerIndexBasedProvider({
await testSubjects.clickWhenNotDisabled('mlDataVisualizerCreateAdvancedJobCard');
},

async assertCreateDataFrameAnalyticsCardExists() {
await testSubjects.existOrFail('mlDataVisualizerCreateDataFrameAnalyticsCard');
},

async assertCreateDataFrameAnalyticsCardNotExists() {
await testSubjects.missingOrFail('mlDataVisualizerCreateDataFrameAnalyticsCard');
},

async assertViewInDiscoverCardExists() {
await testSubjects.existOrFail('mlDataVisualizerViewInDiscoverCard');
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ export default function ({ getService }: FtrProviderContext) {
});

it('navigates to Discover page', async () => {
await ml.testExecution.logTestStep('should not display create job card');
await ml.testExecution.logTestStep('should not display create job cards');
await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardNotExists();
await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardNotExists();

await ml.testExecution.logTestStep('displays the actions panel with view in Discover card');
await ml.dataVisualizerIndexBased.assertActionsPanelExists();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export default function ({ getService }: FtrProviderContext) {
await ml.testExecution.logTestStep('should not display job cards');
await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardNotExists();
await ml.dataVisualizerIndexBased.assertRecognizerCardNotExists(ecExpectedModuleId);
await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardNotExists();
});

it('should display elements on File Data Visualizer page correctly', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export default function ({ getService }: FtrProviderContext) {
await ml.testExecution.logTestStep('should not display job cards');
await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardNotExists();
await ml.dataVisualizerIndexBased.assertRecognizerCardNotExists(ecExpectedModuleId);
await ml.dataVisualizerIndexBased.assertCreateDataFrameAnalyticsCardNotExists();
});

it('should display elements on File Data Visualizer page correctly', async () => {
Expand Down

0 comments on commit 9a20358

Please sign in to comment.