mirror of
https://github.com/elastic/kibana.git
synced 2025-04-25 02:09:32 -04:00
[Security-Solution] Adds warning message for selected ML jobs not running, adds tooltip to combobox (#97764)
* [Security-Solution] Adds warning message for selected ML jobs not running, adds tooltip to combobox * updates i18n * update strings * updates strings * fixes i18n error
This commit is contained in:
parent
15ae3c0cd6
commit
e39b8c6d36
6 changed files with 115 additions and 59 deletions
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||||
|
* 2.0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
import { HelpText } from './help_text';
|
||||||
|
|
||||||
|
describe('MlJobSelect help text', () => {
|
||||||
|
it('does not show warning if all jobs are running', () => {
|
||||||
|
const wrapper = shallow(<HelpText href={'https://test.com'} notRunningJobIds={[]} />);
|
||||||
|
expect(wrapper.find('[data-test-subj="ml-warning-not-running-jobs"]')).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows warning if there are jobs not running', () => {
|
||||||
|
const wrapper = shallow(<HelpText href={'https://test.com'} notRunningJobIds={['id']} />);
|
||||||
|
expect(wrapper.find('[data-test-subj="ml-warning-not-running-jobs"]')).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||||
|
* 2.0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { EuiIcon, EuiLink, EuiText } from '@elastic/eui';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
import { FormattedMessage } from '@kbn/i18n/react';
|
||||||
|
|
||||||
|
const HelpTextWarningContainer = styled.div`
|
||||||
|
margin-top: 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const HelpTextComponent: React.FC<{ href: string; notRunningJobIds: string[] }> = ({
|
||||||
|
href,
|
||||||
|
notRunningJobIds,
|
||||||
|
}) => (
|
||||||
|
<>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.securitySolution.detectionEngine.createRule.stepDefineRule.machineLearningJobIdHelpText"
|
||||||
|
defaultMessage="We've provided a few common jobs to get you started. To add your own custom jobs, assign a group of 'security' to those jobs in the {machineLearning} application to make them appear here."
|
||||||
|
values={{
|
||||||
|
machineLearning: (
|
||||||
|
<EuiLink href={href} target="_blank">
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.securitySolution.components.mlJobSelect.machineLearningLink"
|
||||||
|
defaultMessage="Machine Learning"
|
||||||
|
/>
|
||||||
|
</EuiLink>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{notRunningJobIds.length > 0 && (
|
||||||
|
<HelpTextWarningContainer data-test-subj="ml-warning-not-running-jobs">
|
||||||
|
<EuiText size="xs" color="warning">
|
||||||
|
<EuiIcon type="alert" />
|
||||||
|
<span>
|
||||||
|
{notRunningJobIds.length === 1 ? (
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.securitySolution.detectionEngine.createRule.stepDefineRule.mlEnableJobSingle"
|
||||||
|
defaultMessage="The selected ML job, {jobName}, is not currently running. Please set {jobName} to run via 'ML job settings' before activating this rule."
|
||||||
|
values={{
|
||||||
|
jobName: notRunningJobIds[0],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.securitySolution.detectionEngine.createRule.stepDefineRule.mlEnableJobMulti"
|
||||||
|
defaultMessage="The selected ML jobs, {jobNames}, are not currently running. Please set all of these jobs to run via 'ML job settings' before activating this rule."
|
||||||
|
values={{
|
||||||
|
jobNames: notRunningJobIds.reduce(
|
||||||
|
(acc, value, i, array) => acc + (i < array.length - 1 ? ', ' : ', and ') + value
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</EuiText>
|
||||||
|
</HelpTextWarningContainer>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const HelpText = React.memo(HelpTextComponent);
|
|
@ -6,15 +6,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useCallback, useMemo } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
import { FormattedMessage } from '@kbn/i18n/react';
|
|
||||||
import {
|
import {
|
||||||
EuiComboBox,
|
EuiComboBox,
|
||||||
EuiComboBoxOptionOption,
|
EuiComboBoxOptionOption,
|
||||||
EuiFlexGroup,
|
EuiFlexGroup,
|
||||||
EuiFlexItem,
|
EuiFlexItem,
|
||||||
EuiFormRow,
|
EuiFormRow,
|
||||||
EuiIcon,
|
EuiToolTip,
|
||||||
EuiLink,
|
|
||||||
EuiText,
|
EuiText,
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
|
|
||||||
|
@ -23,63 +21,36 @@ import { isJobStarted } from '../../../../../common/machine_learning/helpers';
|
||||||
import { FieldHook, getFieldValidityAndErrorMessage } from '../../../../shared_imports';
|
import { FieldHook, getFieldValidityAndErrorMessage } from '../../../../shared_imports';
|
||||||
import { useSecurityJobs } from '../../../../common/components/ml_popover/hooks/use_security_jobs';
|
import { useSecurityJobs } from '../../../../common/components/ml_popover/hooks/use_security_jobs';
|
||||||
import { useKibana } from '../../../../common/lib/kibana';
|
import { useKibana } from '../../../../common/lib/kibana';
|
||||||
import {
|
import { ML_JOB_SELECT_PLACEHOLDER_TEXT } from '../step_define_rule/translations';
|
||||||
ML_JOB_SELECT_PLACEHOLDER_TEXT,
|
import { HelpText } from './help_text';
|
||||||
ENABLE_ML_JOB_WARNING,
|
|
||||||
} from '../step_define_rule/translations';
|
|
||||||
|
|
||||||
interface MlJobValue {
|
interface MlJobValue {
|
||||||
id: string;
|
id: string;
|
||||||
description: string;
|
description: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type MlJobOption = EuiComboBoxOptionOption<MlJobValue>;
|
const JobDisplayContainer = styled.div`
|
||||||
|
width: 100%;
|
||||||
const HelpTextWarningContainer = styled.div`
|
height: 100%;
|
||||||
margin-top: 10px;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
type MlJobOption = EuiComboBoxOptionOption<MlJobValue>;
|
||||||
|
|
||||||
const MlJobSelectEuiFlexGroup = styled(EuiFlexGroup)`
|
const MlJobSelectEuiFlexGroup = styled(EuiFlexGroup)`
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const HelpText: React.FC<{ href: string; showEnableWarning: boolean }> = ({
|
|
||||||
href,
|
|
||||||
showEnableWarning = false,
|
|
||||||
}) => (
|
|
||||||
<>
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.securitySolution.detectionEngine.createRule.stepDefineRule.machineLearningJobIdHelpText"
|
|
||||||
defaultMessage="We've provided a few common jobs to get you started. To add your own custom jobs, assign a group of “security” to those jobs in the {machineLearning} application to make them appear here."
|
|
||||||
values={{
|
|
||||||
machineLearning: (
|
|
||||||
<EuiLink href={href} target="_blank">
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.securitySolution.components.mlJobSelect.machineLearningLink"
|
|
||||||
defaultMessage="Machine Learning"
|
|
||||||
/>
|
|
||||||
</EuiLink>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{showEnableWarning && (
|
|
||||||
<HelpTextWarningContainer>
|
|
||||||
<EuiText size="xs" color="warning">
|
|
||||||
<EuiIcon type="alert" />
|
|
||||||
<span>{ENABLE_ML_JOB_WARNING}</span>
|
|
||||||
</EuiText>
|
|
||||||
</HelpTextWarningContainer>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
const JobDisplay: React.FC<MlJobValue> = ({ id, description }) => (
|
const JobDisplay: React.FC<MlJobValue> = ({ id, description }) => (
|
||||||
<>
|
<JobDisplayContainer>
|
||||||
<strong>{id}</strong>
|
<strong>{id}</strong>
|
||||||
|
<EuiToolTip content={description}>
|
||||||
<EuiText size="xs" color="subdued">
|
<EuiText size="xs" color="subdued">
|
||||||
<p>{description}</p>
|
<p>{description}</p>
|
||||||
</EuiText>
|
</EuiText>
|
||||||
</>
|
</EuiToolTip>
|
||||||
|
</JobDisplayContainer>
|
||||||
);
|
);
|
||||||
|
|
||||||
interface MlJobSelectProps {
|
interface MlJobSelectProps {
|
||||||
|
@ -114,9 +85,14 @@ export const MlJobSelect: React.FC<MlJobSelectProps> = ({ describedByIds = [], f
|
||||||
|
|
||||||
const selectedJobOptions = jobOptions.filter((option) => jobIds.includes(option.value.id));
|
const selectedJobOptions = jobOptions.filter((option) => jobIds.includes(option.value.id));
|
||||||
|
|
||||||
const allJobsRunning = useMemo(() => {
|
const notRunningJobIds = useMemo<string[]>(() => {
|
||||||
const selectedJobs = jobs.filter(({ id }) => jobIds.includes(id));
|
const selectedJobs = jobs.filter(({ id }) => jobIds.includes(id));
|
||||||
return selectedJobs.every((job) => isJobStarted(job.jobState, job.datafeedState));
|
return selectedJobs.reduce((acc, job) => {
|
||||||
|
if (!isJobStarted(job.jobState, job.datafeedState)) {
|
||||||
|
acc.push(job.id);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, [] as string[]);
|
||||||
}, [jobs, jobIds]);
|
}, [jobs, jobIds]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -124,7 +100,7 @@ export const MlJobSelect: React.FC<MlJobSelectProps> = ({ describedByIds = [], f
|
||||||
<EuiFlexItem>
|
<EuiFlexItem>
|
||||||
<EuiFormRow
|
<EuiFormRow
|
||||||
label={field.label}
|
label={field.label}
|
||||||
helpText={<HelpText href={mlUrl} showEnableWarning={!allJobsRunning} />}
|
helpText={<HelpText href={mlUrl} notRunningJobIds={notRunningJobIds} />}
|
||||||
isInvalid={isInvalid}
|
isInvalid={isInvalid}
|
||||||
error={errorMessage}
|
error={errorMessage}
|
||||||
data-test-subj="mlJobSelect"
|
data-test-subj="mlJobSelect"
|
||||||
|
|
|
@ -64,14 +64,6 @@ export const ML_JOB_SELECT_PLACEHOLDER_TEXT = i18n.translate(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const ENABLE_ML_JOB_WARNING = i18n.translate(
|
|
||||||
'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.mlEnableJobWarningTitle',
|
|
||||||
{
|
|
||||||
defaultMessage:
|
|
||||||
'One or more selected ML jobs are not currently running. Please set these job(s) to run via "ML job settings" before activating this rule.',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const QUERY_BAR_LABEL = i18n.translate(
|
export const QUERY_BAR_LABEL = i18n.translate(
|
||||||
'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.fieldQuerBarLabel',
|
'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.fieldQuerBarLabel',
|
||||||
{
|
{
|
||||||
|
|
|
@ -18327,7 +18327,6 @@
|
||||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.indicesHelperDescription": "このルールを実行するElasticsearchインデックスのパターンを入力します。デフォルトでは、セキュリティソリューション詳細設定で定義されたインデックスパターンが含まれます。",
|
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.indicesHelperDescription": "このルールを実行するElasticsearchインデックスのパターンを入力します。デフォルトでは、セキュリティソリューション詳細設定で定義されたインデックスパターンが含まれます。",
|
||||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.machineLearningJobIdHelpText": "手始めに使えるように、一般的なジョブがいくつか提供されています。独自のカスタムジョブを追加するには、{machineLearning} アプリケーションでジョブに「security」のグループを割り当て、ここに表示されるようにします。",
|
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.machineLearningJobIdHelpText": "手始めに使えるように、一般的なジョブがいくつか提供されています。独自のカスタムジョブを追加するには、{machineLearning} アプリケーションでジョブに「security」のグループを割り当て、ここに表示されるようにします。",
|
||||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.machineLearningJobIdRequired": "機械学習ジョブが必要です。",
|
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.machineLearningJobIdRequired": "機械学習ジョブが必要です。",
|
||||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.mlEnableJobWarningTitle": "このMLジョブは現在実行されていません。このルールを有効にする前に、このジョブを「MLジョブ設定」で実行するように設定してください。",
|
|
||||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.mlJobSelectPlaceholderText": "ジョブを選択してください",
|
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.mlJobSelectPlaceholderText": "ジョブを選択してください",
|
||||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.outputIndiceNameFieldRequiredError": "インデックスパターンが最低1つ必要です。",
|
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.outputIndiceNameFieldRequiredError": "インデックスパターンが最低1つ必要です。",
|
||||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.referencesUrlInvalidError": "URLの形式が無効です",
|
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.referencesUrlInvalidError": "URLの形式が無効です",
|
||||||
|
|
|
@ -18596,7 +18596,6 @@
|
||||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.indicesHelperDescription": "输入要运行此规则的 Elasticsearch 索引的模式。默认情况下,将包括 Security Solution 高级设置中定义的索引模式。",
|
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.indicesHelperDescription": "输入要运行此规则的 Elasticsearch 索引的模式。默认情况下,将包括 Security Solution 高级设置中定义的索引模式。",
|
||||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.machineLearningJobIdHelpText": "我们提供了一些常见作业来帮助您入门。要添加自己的定制规则,请在 {machineLearning} 应用程序中将一组“security”分配给这些作业,以使其显示在此处。",
|
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.machineLearningJobIdHelpText": "我们提供了一些常见作业来帮助您入门。要添加自己的定制规则,请在 {machineLearning} 应用程序中将一组“security”分配给这些作业,以使其显示在此处。",
|
||||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.machineLearningJobIdRequired": "Machine Learning 作业必填。",
|
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.machineLearningJobIdRequired": "Machine Learning 作业必填。",
|
||||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.mlEnableJobWarningTitle": "此 ML 作业当前未运行。在激活此规则之前请通过“ML 作业设置”设置此作业以使其运行。",
|
|
||||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.mlJobSelectPlaceholderText": "选择作业",
|
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.mlJobSelectPlaceholderText": "选择作业",
|
||||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.outputIndiceNameFieldRequiredError": "至少需要一个索引模式。",
|
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.outputIndiceNameFieldRequiredError": "至少需要一个索引模式。",
|
||||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.referencesUrlInvalidError": "Url 的格式无效",
|
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.referencesUrlInvalidError": "Url 的格式无效",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue