Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Add category field to edit model configuration page (#310)
Browse files Browse the repository at this point in the history
  • Loading branch information
ohltyler committed Oct 14, 2020
1 parent fd28abd commit 6237716
Show file tree
Hide file tree
Showing 10 changed files with 1,089 additions and 48 deletions.
1 change: 1 addition & 0 deletions public/models/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export type Detector = {
curState: DETECTOR_STATE;
stateError: string;
initProgress?: InitProgress;
categoryField?: string[];
};

export type DetectorListItem = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

import React from 'react';
import { get } from 'lodash';
import { EuiBasicTable } from '@elastic/eui';
import ContentPanel from '../../../../components/ContentPanel/ContentPanel';

interface AdditionalSettingsProps {
shingleSize: number;
categoryField: string[];
}

export function AdditionalSettings(props: AdditionalSettingsProps) {
const tableItems = [
{
categoryField: get(props.categoryField, 0, '-'),
windowSize: props.shingleSize,
},
];
const tableColumns = [
{ name: 'Category field', field: 'categoryField' },
{ name: 'Window size', field: 'windowSize' },
];
return (
<ContentPanel title="Additional settings" titleSize="s">
<EuiBasicTable
className="header-single-value-euiBasicTable"
items={tableItems}
columns={tableColumns}
/>
</ContentPanel>
);
}
26 changes: 10 additions & 16 deletions public/pages/DetectorConfig/containers/Features.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { PLUGIN_NAME, SHINGLE_SIZE } from '../../../utils/constants';
import ContentPanel from '../../../components/ContentPanel/ContentPanel';
import { CodeModal } from '../components/CodeModal/CodeModal';
import { getTitleWithCount } from '../../../utils/utils';
import { AdditionalSettings } from '../components/AdditionalSettings/AdditionalSettings';

interface FeaturesProps {
detectorId: string;
Expand Down Expand Up @@ -186,10 +187,10 @@ export class Features extends Component<FeaturesProps, FeaturesState> {

const setParamsText = `Set the index fields that you want to find anomalies for by defining
the model features. You can also set other model parameters such as
window size.`
window size.`;

const previewText = `After you set the model features and other optional parameters, you can
preview your anomalies from a sample feature output.`
preview your anomalies from a sample feature output.`;

return (
<ContentPanel
Expand Down Expand Up @@ -223,8 +224,8 @@ export class Features extends Component<FeaturesProps, FeaturesState> {
body={
<EuiText className="emptyFeatureBody">
{setParamsText}
<br/>
<br/>
<br />
<br />
{previewText}
</EuiText>
}
Expand Down Expand Up @@ -252,18 +253,11 @@ export class Features extends Component<FeaturesProps, FeaturesState> {
onChange={this.handleTableChange}
/>
</ContentPanel>
<EuiSpacer size="m"/>
<ContentPanel
title="Additional settings"
titleSize="s"
>
<EuiBasicTable
className="header-single-value-euiBasicTable"
items={[{ windowSize: shingleSize }]}
columns={[{ field: 'windowSize', name: 'Window size'}]}
cellProps={getCellProps}
/>
</ContentPanel>
<EuiSpacer size="m" />
<AdditionalSettings
shingleSize={shingleSize}
categoryField={get(this.props.detector, 'categoryField', [])}
/>
</div>
)}
</ContentPanel>
Expand Down
161 changes: 161 additions & 0 deletions public/pages/EditFeatures/components/CategoryField/CategoryField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

import {
EuiFlexItem,
EuiFlexGroup,
EuiText,
EuiLink,
EuiIcon,
EuiFormRow,
EuiPage,
EuiPageBody,
EuiComboBox,
EuiCheckbox,
EuiTitle,
EuiCallOut,
EuiSpacer,
} from '@elastic/eui';
import { Field, FieldProps } from 'formik';
import { get, isEmpty } from 'lodash';
import React, { useState, useEffect } from 'react';
import ContentPanel from '../../../../components/ContentPanel/ContentPanel';
// @ts-ignore
import { toastNotifications } from 'ui/notify';
import {
isInvalid,
getError,
validateCategoryField,
} from '../../../../utils/utils';
//@ts-ignore
import chrome from 'ui/chrome';

interface CategoryFieldProps {
isHCDetector: boolean;
categoryFieldOptions: string[];
setIsHCDetector(isHCDetector: boolean): void;
isLoading: boolean;
}

export function CategoryField(props: CategoryFieldProps) {
const [enabled, setEnabled] = useState<boolean>(props.isHCDetector);
const noCategoryFields = isEmpty(props.categoryFieldOptions);
const convertedOptions = props.categoryFieldOptions.map((option: string) => {
return {
label: option,
};
});

useEffect(() => {
setEnabled(props.isHCDetector);
}, [props.isHCDetector]);

return (
<EuiPage>
<EuiPageBody>
<ContentPanel
title={
<EuiTitle size="s">
<h2>Category field </h2>
</EuiTitle>
}
subTitle={
<EuiText className="content-panel-subTitle">
Categorize anomalies based on unique partitions. For example, with
clickstream data you can categorize anomalies into a given day,
week, or month.{' '}
<EuiLink
href="https://opendistro.github.io/for-elasticsearch-docs/docs/ad/"
target="_blank"
>
Learn more <EuiIcon size="s" type="popout" />
</EuiLink>
</EuiText>
}
>
{noCategoryFields && !props.isLoading ? (
<EuiCallOut
data-test-subj="noCategoryFieldsCallout"
title="There are no available category fields for the selected index"
color="warning"
iconType="alert"
></EuiCallOut>
) : null}
{noCategoryFields ? <EuiSpacer size="m" /> : null}
<Field
name="categoryField"
validate={enabled ? validateCategoryField : null}
>
{({ field, form }: FieldProps) => (
<EuiFlexGroup direction="column">
<EuiFlexItem>
<EuiCheckbox
id={'categoryFieldCheckbox'}
label="Enable category field"
checked={enabled}
disabled={noCategoryFields}
onChange={() => {
if (!enabled) {
props.setIsHCDetector(true);
}
if (enabled) {
props.setIsHCDetector(false);
form.setFieldValue('categoryField', []);
}
setEnabled(!enabled);
}}
/>
</EuiFlexItem>
{enabled && !noCategoryFields ? (
<EuiFlexItem>
<EuiFormRow
label="Field"
isInvalid={isInvalid(field.name, form)}
error={getError(field.name, form)}
helpText={`You can only apply the category field to the 'ip' and 'keyword' Elasticsearch data types.`}
>
<EuiComboBox
data-test-subj="categoryFieldComboBox"
id="categoryField"
placeholder="Select your category field"
options={convertedOptions}
onBlur={() => {
form.setFieldTouched('categoryField', true);
}}
onChange={(options) => {
const selection = get(options, '0.label');
if (selection) {
form.setFieldValue('categoryField', [selection]);
} else {
form.setFieldValue('categoryField', []);
}
}}
selectedOptions={
(field.value[0] && [{ label: field.value[0] }]) || []
}
singleSelection={true}
isClearable={true}
/>
</EuiFormRow>
</EuiFlexItem>
) : null}
</EuiFlexGroup>
)}
</Field>
</ContentPanel>
</EuiPageBody>
</EuiPage>
);
}
Loading

0 comments on commit 6237716

Please sign in to comment.