mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[ML] DF Analytics: adds prompt for destination index pattern creation (#70651)
* add warning if create index not selected * create indexPrompt component and set needsDestIndexPattern * translation for prompt text and link * create indexPattern text to warning color
This commit is contained in:
parent
31abd6dc28
commit
93bae2284c
7 changed files with 111 additions and 12 deletions
|
@ -24,6 +24,7 @@ export const useResultsViewConfig = (jobId: string) => {
|
|||
const mlContext = useMlContext();
|
||||
const [indexPattern, setIndexPattern] = useState<IndexPattern | undefined>(undefined);
|
||||
const [isInitialized, setIsInitialized] = useState<boolean>(false);
|
||||
const [needsDestIndexPattern, setNeedsDestIndexPattern] = useState<boolean>(false);
|
||||
const [isLoadingJobConfig, setIsLoadingJobConfig] = useState<boolean>(false);
|
||||
const [jobConfig, setJobConfig] = useState<DataFrameAnalyticsConfig | undefined>(undefined);
|
||||
const [jobCapsServiceErrorMessage, setJobCapsServiceErrorMessage] = useState<undefined | string>(
|
||||
|
@ -68,6 +69,7 @@ export const useResultsViewConfig = (jobId: string) => {
|
|||
}
|
||||
|
||||
if (indexP === undefined) {
|
||||
setNeedsDestIndexPattern(true);
|
||||
const sourceIndex = jobConfigUpdate.source.index[0];
|
||||
const sourceIndexPatternId = getIndexPatternIdFromName(sourceIndex) || sourceIndex;
|
||||
indexP = await mlContext.indexPatterns.get(sourceIndexPatternId);
|
||||
|
@ -100,5 +102,6 @@ export const useResultsViewConfig = (jobId: string) => {
|
|||
jobConfig,
|
||||
jobConfigErrorMessage,
|
||||
jobStatus,
|
||||
needsDestIndexPattern,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -5,7 +5,15 @@
|
|||
*/
|
||||
|
||||
import React, { FC, Fragment, useRef } from 'react';
|
||||
import { EuiFieldText, EuiFormRow, EuiLink, EuiSpacer, EuiSwitch, EuiTextArea } from '@elastic/eui';
|
||||
import {
|
||||
EuiFieldText,
|
||||
EuiFormRow,
|
||||
EuiLink,
|
||||
EuiSpacer,
|
||||
EuiSwitch,
|
||||
EuiText,
|
||||
EuiTextArea,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { useMlKibana } from '../../../../../contexts/kibana';
|
||||
|
@ -188,15 +196,32 @@ export const DetailsStepForm: FC<CreateAnalyticsStepProps> = ({
|
|||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
isInvalid={createIndexPattern && destinationIndexPatternTitleExists}
|
||||
error={
|
||||
createIndexPattern &&
|
||||
destinationIndexPatternTitleExists && [
|
||||
i18n.translate('xpack.ml.dataframe.analytics.create.indexPatternExistsError', {
|
||||
defaultMessage: 'An index pattern with this title already exists.',
|
||||
}),
|
||||
]
|
||||
fullWidth
|
||||
isInvalid={
|
||||
(createIndexPattern && destinationIndexPatternTitleExists) || !createIndexPattern
|
||||
}
|
||||
error={[
|
||||
...(createIndexPattern && destinationIndexPatternTitleExists
|
||||
? [
|
||||
i18n.translate('xpack.ml.dataframe.analytics.create.indexPatternExistsError', {
|
||||
defaultMessage: 'An index pattern with this title already exists.',
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
...(!createIndexPattern
|
||||
? [
|
||||
<EuiText size="xs" color="warning">
|
||||
{i18n.translate(
|
||||
'xpack.ml.dataframe.analytics.create.shouldCreateIndexPatternMessage',
|
||||
{
|
||||
defaultMessage:
|
||||
'You may not be able to view job results if an index pattern is not created for the destination index.',
|
||||
}
|
||||
)}
|
||||
</EuiText>,
|
||||
]
|
||||
: []),
|
||||
]}
|
||||
>
|
||||
<EuiSwitch
|
||||
disabled={isJobCreated}
|
||||
|
|
|
@ -38,6 +38,7 @@ export const ExplorationPageWrapper: FC<Props> = ({ jobId, title, EvaluatePanel
|
|||
jobConfig,
|
||||
jobConfigErrorMessage,
|
||||
jobStatus,
|
||||
needsDestIndexPattern,
|
||||
} = useResultsViewConfig(jobId);
|
||||
const [searchQuery, setSearchQuery] = useState<ResultsSearchQuery>(defaultSearchQuery);
|
||||
|
||||
|
@ -64,9 +65,10 @@ export const ExplorationPageWrapper: FC<Props> = ({ jobId, title, EvaluatePanel
|
|||
indexPattern !== undefined &&
|
||||
isInitialized === true && (
|
||||
<ExplorationResultsTable
|
||||
jobConfig={jobConfig}
|
||||
indexPattern={indexPattern}
|
||||
jobConfig={jobConfig}
|
||||
jobStatus={jobStatus}
|
||||
needsDestIndexPattern={needsDestIndexPattern}
|
||||
setEvaluateSearchQuery={setSearchQuery}
|
||||
title={title}
|
||||
/>
|
||||
|
|
|
@ -33,6 +33,7 @@ import { getTaskStateBadge } from '../../../analytics_management/components/anal
|
|||
import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common';
|
||||
import { ExplorationTitle } from '../exploration_title';
|
||||
import { ExplorationQueryBar } from '../exploration_query_bar';
|
||||
import { IndexPatternPrompt } from '../index_pattern_prompt';
|
||||
|
||||
import { useExplorationResults } from './use_exploration_results';
|
||||
|
||||
|
@ -55,12 +56,20 @@ interface Props {
|
|||
indexPattern: IndexPattern;
|
||||
jobConfig: DataFrameAnalyticsConfig;
|
||||
jobStatus?: DATA_FRAME_TASK_STATE;
|
||||
needsDestIndexPattern: boolean;
|
||||
setEvaluateSearchQuery: React.Dispatch<React.SetStateAction<object>>;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export const ExplorationResultsTable: FC<Props> = React.memo(
|
||||
({ indexPattern, jobConfig, jobStatus, setEvaluateSearchQuery, title }) => {
|
||||
({
|
||||
indexPattern,
|
||||
jobConfig,
|
||||
jobStatus,
|
||||
needsDestIndexPattern,
|
||||
setEvaluateSearchQuery,
|
||||
title,
|
||||
}) => {
|
||||
const [searchQuery, setSearchQuery] = useState<SavedSearchQuery>(defaultSearchQuery);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -119,6 +128,7 @@ export const ExplorationResultsTable: FC<Props> = React.memo(
|
|||
id="mlDataFrameAnalyticsTableResultsPanel"
|
||||
data-test-subj="mlDFAnalyticsExplorationTablePanel"
|
||||
>
|
||||
{needsDestIndexPattern && <IndexPatternPrompt destIndex={jobConfig.dest.index} />}
|
||||
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween" responsive={false}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { IndexPatternPrompt } from './index_pattern_prompt';
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { FC } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { EuiLink, EuiSpacer, EuiText } from '@elastic/eui';
|
||||
import { useMlKibana } from '../../../../../contexts/kibana';
|
||||
|
||||
interface Props {
|
||||
destIndex: string;
|
||||
}
|
||||
|
||||
export const IndexPatternPrompt: FC<Props> = ({ destIndex }) => {
|
||||
const {
|
||||
services: {
|
||||
http: { basePath },
|
||||
},
|
||||
} = useMlKibana();
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiText size="xs" color="warning">
|
||||
<FormattedMessage
|
||||
id="xpack.ml.dataframe.analytics.indexPatternPromptMessage"
|
||||
defaultMessage="No index pattern exists for index {destIndex}. {linkToIndexPatternManagement} for {destIndex}."
|
||||
values={{
|
||||
destIndex,
|
||||
linkToIndexPatternManagement: (
|
||||
<EuiLink
|
||||
href={`${basePath.get()}/app/management/kibana/indexPatterns/create`}
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.ml.dataframe.analytics.indexPatternPromptLinkText"
|
||||
defaultMessage="Create an index pattern"
|
||||
/>
|
||||
</EuiLink>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</EuiText>
|
||||
<EuiSpacer size="m" />
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -33,6 +33,7 @@ import { getTaskStateBadge } from '../../../analytics_management/components/anal
|
|||
|
||||
import { ExplorationQueryBar } from '../exploration_query_bar';
|
||||
import { ExplorationTitle } from '../exploration_title';
|
||||
import { IndexPatternPrompt } from '../index_pattern_prompt';
|
||||
|
||||
import { getFeatureCount } from './common';
|
||||
import { useOutlierData } from './use_outlier_data';
|
||||
|
@ -49,7 +50,7 @@ export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) =
|
|||
values: { jobId },
|
||||
});
|
||||
|
||||
const { indexPattern, jobConfig, jobStatus } = useResultsViewConfig(jobId);
|
||||
const { indexPattern, jobConfig, jobStatus, needsDestIndexPattern } = useResultsViewConfig(jobId);
|
||||
const [searchQuery, setSearchQuery] = useState<SavedSearchQuery>(defaultSearchQuery);
|
||||
const outlierData = useOutlierData(indexPattern, jobConfig, searchQuery);
|
||||
|
||||
|
@ -82,6 +83,9 @@ export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) =
|
|||
|
||||
return (
|
||||
<EuiPanel data-test-subj="mlDFAnalyticsOutlierExplorationTablePanel">
|
||||
{jobConfig !== undefined && needsDestIndexPattern && (
|
||||
<IndexPatternPrompt destIndex={jobConfig.dest.index} />
|
||||
)}
|
||||
<EuiFlexGroup
|
||||
alignItems="center"
|
||||
justifyContent="spaceBetween"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue