mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[ML] Add Create Data Frame Analytics card to Data Visualizer (#91011)
This commit is contained in:
parent
3e234d074f
commit
13740f1cd3
15 changed files with 128 additions and 81 deletions
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }) => {
|
||||
|
@ -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}
|
||||
|
|
|
@ -5,4 +5,4 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export { CreateJobLinkCard } from './create_job_link_card';
|
||||
export { LinkCard } from './link_card';
|
|
@ -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,
|
|
@ -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';
|
||||
|
@ -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;
|
||||
|
@ -95,6 +92,7 @@ export const ActionsPanel: FC<Props> = ({ indexPattern, searchString, searchQuer
|
|||
setDiscoverLink(discoverUrl);
|
||||
}
|
||||
};
|
||||
|
||||
getDiscoverUrl();
|
||||
return () => {
|
||||
unmounted = true;
|
||||
|
@ -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>
|
||||
|
@ -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" />
|
||||
</>
|
||||
)}
|
||||
|
@ -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>
|
||||
|
|
|
@ -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';
|
||||
|
@ -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}
|
||||
|
@ -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',
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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 () => {
|
||||
|
|
|
@ -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 () => {
|
||||
|
|
|
@ -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');
|
||||
},
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 () => {
|
||||
|
|
|
@ -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 () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue