mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
* [ML] Adding detector descriptions to advanced wizard * renaming things * reverting accidentally added refactor
This commit is contained in:
parent
bc375cacab
commit
567288216b
7 changed files with 143 additions and 39 deletions
|
@ -12,6 +12,9 @@ import 'uiExports/savedObjectTypes';
|
|||
import 'ui/courier';
|
||||
import 'ui/autoload/all';
|
||||
|
||||
// needed to make syntax highlighting work in ace editors
|
||||
import 'ace';
|
||||
|
||||
import 'plugins/ml/access_denied';
|
||||
import 'plugins/ml/jobs';
|
||||
import 'plugins/ml/overview';
|
||||
|
|
|
@ -23,6 +23,7 @@ export interface RichDetector {
|
|||
overField: SplitField;
|
||||
partitionField: SplitField;
|
||||
excludeFrequent: string | null;
|
||||
description: string | null;
|
||||
}
|
||||
|
||||
export class AdvancedJobCreator extends JobCreator {
|
||||
|
@ -43,7 +44,8 @@ export class AdvancedJobCreator extends JobCreator {
|
|||
byField: SplitField,
|
||||
overField: SplitField,
|
||||
partitionField: SplitField,
|
||||
excludeFrequent: string | null
|
||||
excludeFrequent: string | null,
|
||||
description: string | null
|
||||
) {
|
||||
const { detector, richDetector } = this._createDetector(
|
||||
agg,
|
||||
|
@ -51,7 +53,8 @@ export class AdvancedJobCreator extends JobCreator {
|
|||
byField,
|
||||
overField,
|
||||
partitionField,
|
||||
excludeFrequent
|
||||
excludeFrequent,
|
||||
description
|
||||
);
|
||||
|
||||
this._addDetector(detector, agg, field);
|
||||
|
@ -65,6 +68,7 @@ export class AdvancedJobCreator extends JobCreator {
|
|||
overField: SplitField,
|
||||
partitionField: SplitField,
|
||||
excludeFrequent: string | null,
|
||||
description: string | null,
|
||||
index: number
|
||||
) {
|
||||
const { detector, richDetector } = this._createDetector(
|
||||
|
@ -73,7 +77,8 @@ export class AdvancedJobCreator extends JobCreator {
|
|||
byField,
|
||||
overField,
|
||||
partitionField,
|
||||
excludeFrequent
|
||||
excludeFrequent,
|
||||
description
|
||||
);
|
||||
|
||||
this._editDetector(detector, agg, field, index);
|
||||
|
@ -89,7 +94,8 @@ export class AdvancedJobCreator extends JobCreator {
|
|||
byField: SplitField,
|
||||
overField: SplitField,
|
||||
partitionField: SplitField,
|
||||
excludeFrequent: string | null
|
||||
excludeFrequent: string | null,
|
||||
description: string | null
|
||||
): { detector: Detector; richDetector: RichDetector } {
|
||||
const detector: Detector = createBasicDetector(agg, field);
|
||||
|
||||
|
@ -105,6 +111,9 @@ export class AdvancedJobCreator extends JobCreator {
|
|||
if (excludeFrequent !== null) {
|
||||
detector.exclude_frequent = excludeFrequent;
|
||||
}
|
||||
if (description !== null) {
|
||||
detector.detector_description = description;
|
||||
}
|
||||
|
||||
const richDetector: RichDetector = {
|
||||
agg,
|
||||
|
@ -113,6 +122,7 @@ export class AdvancedJobCreator extends JobCreator {
|
|||
overField,
|
||||
partitionField,
|
||||
excludeFrequent,
|
||||
description,
|
||||
};
|
||||
|
||||
return { detector, richDetector };
|
||||
|
@ -170,7 +180,8 @@ export class AdvancedJobCreator extends JobCreator {
|
|||
dtr.byField,
|
||||
dtr.overField,
|
||||
dtr.partitionField,
|
||||
dtr.excludeFrequent
|
||||
dtr.excludeFrequent,
|
||||
dtr.description
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -32,6 +32,7 @@ export function getRichDetectors(job: Job, datafeed: Datafeed, advanced: boolean
|
|||
? newJobCapsService.getFieldById(d.partition_field_name)
|
||||
: null,
|
||||
excludeFrequent: d.exclude_frequent || null,
|
||||
description: d.detector_description || null,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
EuiFlexGrid,
|
||||
EuiComboBoxOptionProps,
|
||||
EuiHorizontalRule,
|
||||
EuiTextArea,
|
||||
} from '@elastic/eui';
|
||||
import { JobCreatorContext } from '../../../job_creator_context';
|
||||
import { AdvancedJobCreator, JobCreatorType } from '../../../../../common/job_creator';
|
||||
|
@ -24,6 +25,8 @@ import { RichDetector } from '../../../../../common/job_creator/advanced_job_cre
|
|||
import { ES_FIELD_TYPES } from '../../../../../../../../../../../../src/plugins/data/public';
|
||||
import { ModalWrapper } from './modal_wrapper';
|
||||
import { MLCATEGORY } from '../../../../../../../../common/constants/field_types';
|
||||
import { detectorToString } from '../../../../../../../util/string_utils';
|
||||
import { createBasicDetector } from '../../../../../common/job_creator/util/default_configs';
|
||||
|
||||
import {
|
||||
AggDescription,
|
||||
|
@ -32,6 +35,7 @@ import {
|
|||
OverFieldDescription,
|
||||
PartitionFieldDescription,
|
||||
ExcludeFrequentDescription,
|
||||
DescriptionDescription,
|
||||
} from './descriptions';
|
||||
|
||||
interface Props {
|
||||
|
@ -81,8 +85,10 @@ export const AdvancedDetectorModal: FC<Props> = ({
|
|||
const [excludeFrequentOption, setExcludeFrequentOption] = useState(
|
||||
createExcludeFrequentOption(detector.excludeFrequent)
|
||||
);
|
||||
const [descriptionOption, setDescriptionOption] = useState(detector.description || '');
|
||||
const [fieldsEnabled, setFieldsEnabled] = useState(true);
|
||||
const [fieldOptionEnabled, setFieldOptionEnabled] = useState(true);
|
||||
const { descriptionPlaceholder, setDescriptionPlaceholder } = useDetectorPlaceholder(detector);
|
||||
|
||||
const aggOptions: EuiComboBoxOptionProps[] = aggs.map(createAggOption);
|
||||
const fieldOptions: EuiComboBoxOptionProps[] = fields
|
||||
|
@ -132,8 +138,10 @@ export const AdvancedDetectorModal: FC<Props> = ({
|
|||
overField: getField(overFieldOption.label),
|
||||
partitionField: getField(partitionFieldOption.label),
|
||||
excludeFrequent: excludeFrequentOption.label !== '' ? excludeFrequentOption.label : null,
|
||||
description: descriptionOption !== '' ? descriptionOption : null,
|
||||
};
|
||||
setDetector(dtr);
|
||||
setDescriptionPlaceholder(dtr);
|
||||
}, [
|
||||
aggOption,
|
||||
fieldOption,
|
||||
|
@ -141,6 +149,7 @@ export const AdvancedDetectorModal: FC<Props> = ({
|
|||
overFieldOption,
|
||||
partitionFieldOption,
|
||||
excludeFrequentOption,
|
||||
descriptionOption,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -228,9 +237,6 @@ export const AdvancedDetectorModal: FC<Props> = ({
|
|||
/>
|
||||
</PartitionFieldDescription>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGrid>
|
||||
<EuiHorizontalRule margin="l" />
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<ExcludeFrequentDescription>
|
||||
<EuiComboBox
|
||||
|
@ -243,7 +249,19 @@ export const AdvancedDetectorModal: FC<Props> = ({
|
|||
/>
|
||||
</ExcludeFrequentDescription>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem />
|
||||
</EuiFlexGrid>
|
||||
<EuiHorizontalRule margin="l" />
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<DescriptionDescription>
|
||||
<EuiTextArea
|
||||
rows={2}
|
||||
placeholder={descriptionPlaceholder}
|
||||
value={descriptionOption}
|
||||
onChange={e => setDescriptionOption(e.target.value)}
|
||||
/>
|
||||
</DescriptionDescription>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</Fragment>
|
||||
</ModalWrapper>
|
||||
|
@ -291,3 +309,27 @@ function createMlcategoryField(jobCreator: JobCreatorType): EuiComboBoxOptionPro
|
|||
},
|
||||
];
|
||||
}
|
||||
|
||||
function useDetectorPlaceholder(detector: RichDetector) {
|
||||
const [descriptionPlaceholder, setDescriptionPlaceholderString] = useState(
|
||||
createDefaultDescription(detector)
|
||||
);
|
||||
|
||||
function setDescriptionPlaceholder(dtr: RichDetector) {
|
||||
setDescriptionPlaceholderString(createDefaultDescription(dtr));
|
||||
}
|
||||
|
||||
return { descriptionPlaceholder, setDescriptionPlaceholder };
|
||||
}
|
||||
|
||||
function createDefaultDescription(dtr: RichDetector) {
|
||||
if (dtr.agg === null || dtr.field === null) {
|
||||
return '';
|
||||
}
|
||||
const basicDetector = createBasicDetector(dtr.agg, dtr.field);
|
||||
basicDetector.by_field_name = dtr.byField ? dtr.byField.id : undefined;
|
||||
basicDetector.over_field_name = dtr.overField ? dtr.overField.id : undefined;
|
||||
basicDetector.partition_field_name = dtr.partitionField ? dtr.partitionField.id : undefined;
|
||||
basicDetector.exclude_frequent = dtr.excludeFrequent ? dtr.excludeFrequent : undefined;
|
||||
return detectorToString(basicDetector);
|
||||
}
|
||||
|
|
|
@ -158,3 +158,28 @@ export const ExcludeFrequentDescription: FC = memo(({ children }) => {
|
|||
</EuiDescribedFormGroup>
|
||||
);
|
||||
});
|
||||
|
||||
export const DescriptionDescription: FC = memo(({ children }) => {
|
||||
const title = i18n.translate(
|
||||
'xpack.ml.newJob.wizard.pickFieldsStep.advancedDetectorModal.description.title',
|
||||
{
|
||||
defaultMessage: 'Description',
|
||||
}
|
||||
);
|
||||
return (
|
||||
<EuiDescribedFormGroup
|
||||
idAria="description"
|
||||
title={<h3>{title}</h3>}
|
||||
description={
|
||||
<FormattedMessage
|
||||
id="xpack.ml.newJob.wizard.pickFieldsStep.advancedDetectorModal.description.description"
|
||||
defaultMessage="Override the default detector description with a meaningful description of what the detector is analyzing."
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFormRow label={title} describedByIds={['description']}>
|
||||
<>{children}</>
|
||||
</EuiFormRow>
|
||||
</EuiDescribedFormGroup>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
EuiButtonIcon,
|
||||
EuiSpacer,
|
||||
EuiCallOut,
|
||||
EuiHorizontalRule,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { JobCreatorContext } from '../../../job_creator_context';
|
||||
|
@ -37,6 +38,39 @@ export const DetectorList: FC<Props> = ({ onEditJob, onDeleteJob }) => {
|
|||
setDetectors(jobCreator.detectors);
|
||||
}, [jobCreatorUpdated]);
|
||||
|
||||
const Buttons: FC<{ index: number }> = ({ index }) => {
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiButtonIcon
|
||||
color="primary"
|
||||
onClick={() => onEditJob(index)}
|
||||
iconType="pencil"
|
||||
aria-label={i18n.translate(
|
||||
'xpack.ml.newJob.wizard.pickFieldsStep.advancedDetectorList.editButton',
|
||||
{
|
||||
defaultMessage: 'Edit',
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiButtonIcon
|
||||
color="danger"
|
||||
onClick={() => onDeleteJob(index)}
|
||||
iconType="trash"
|
||||
aria-label={i18n.translate(
|
||||
'xpack.ml.newJob.wizard.pickFieldsStep.advancedDetectorList.deleteButton',
|
||||
{
|
||||
defaultMessage: 'Delete',
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiTitle size="xs">
|
||||
|
@ -57,38 +91,23 @@ export const DetectorList: FC<Props> = ({ onEditJob, onDeleteJob }) => {
|
|||
<EuiFlexItem key={i}>
|
||||
<EuiPanel paddingSize="m">
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>{detectorToString(d)}</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
{d.detector_description !== undefined ? (
|
||||
<div style={{ fontWeight: 'bold' }}>{d.detector_description}</div>
|
||||
) : (
|
||||
detectorToString(d)
|
||||
)}
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false} style={{ margin: '8px' }}>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiButtonIcon
|
||||
color="primary"
|
||||
onClick={() => onEditJob(i)}
|
||||
iconType="pencil"
|
||||
aria-label={i18n.translate(
|
||||
'xpack.ml.newJob.wizard.pickFieldsStep.advancedDetectorList.editButton',
|
||||
{
|
||||
defaultMessage: 'Edit',
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiButtonIcon
|
||||
color="danger"
|
||||
onClick={() => onDeleteJob(i)}
|
||||
iconType="trash"
|
||||
aria-label={i18n.translate(
|
||||
'xpack.ml.newJob.wizard.pickFieldsStep.advancedDetectorList.deleteButton',
|
||||
{
|
||||
defaultMessage: 'Delete',
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<Buttons index={i} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
{d.detector_description !== undefined && (
|
||||
<Fragment>
|
||||
<EuiHorizontalRule margin="s" />
|
||||
{detectorToString(d)}
|
||||
</Fragment>
|
||||
)}
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
|
|
|
@ -26,6 +26,7 @@ const emptyRichDetector: RichDetector = {
|
|||
overField: null,
|
||||
partitionField: null,
|
||||
excludeFrequent: null,
|
||||
description: null,
|
||||
};
|
||||
|
||||
export const AdvancedDetectors: FC<Props> = ({ setIsValid }) => {
|
||||
|
@ -47,7 +48,8 @@ export const AdvancedDetectors: FC<Props> = ({ setIsValid }) => {
|
|||
dtr.byField,
|
||||
dtr.overField,
|
||||
dtr.partitionField,
|
||||
dtr.excludeFrequent
|
||||
dtr.excludeFrequent,
|
||||
dtr.description
|
||||
);
|
||||
} else {
|
||||
jobCreator.editDetector(
|
||||
|
@ -57,6 +59,7 @@ export const AdvancedDetectors: FC<Props> = ({ setIsValid }) => {
|
|||
dtr.overField,
|
||||
dtr.partitionField,
|
||||
dtr.excludeFrequent,
|
||||
dtr.description,
|
||||
index
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue