/* * SPDX-License-Identifier: Apache-2.0 * * The OpenSearch Contributors require contributions made to * this file be licensed under the Apache-2.0 license or a * compatible open source license. * * Modifications Copyright OpenSearch Contributors. See * GitHub history for details. */ import React, { useState } from 'react'; import { EuiBasicTable, EuiText, EuiLink, EuiIcon, EuiButton, EuiEmptyPrompt, EuiSpacer, } from '@elastic/eui'; import { Detector, FEATURE_TYPE, FeatureAttributes, } from '../../../models/interfaces'; import { get, isEmpty, sortBy } from 'lodash'; import { PLUGIN_NAME, BASE_DOCS_LINK } 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'; import { getShingleSizeFromObject } from '../../ConfigureModel/utils/helpers'; interface FeaturesProps { detectorId: string; detector: Detector; onEditFeatures(): void; } interface FeaturesState { showCodeModel: boolean[]; sortField: string; sortDirection: 'asc' | 'desc'; } export const Features = (props: FeaturesProps) => { const [featuresState, setFeaturesState] = useState({ showCodeModel: get(props.detector, 'featureAttributes', []).map( () => false ), sortField: 'name', sortDirection: 'asc', }); const closeModal = (index: number) => { const cloneShowCodeModal = [...featuresState.showCodeModel]; cloneShowCodeModal[index] = false; setFeaturesState({ ...featuresState, showCodeModel: cloneShowCodeModal, }); }; const showModal = (index: number) => { const cloneShowCodeModal = [...featuresState.showCodeModel]; cloneShowCodeModal[index] = true; setFeaturesState({ ...featuresState, showCodeModel: cloneShowCodeModal, }); }; const getModalVisibilityChange = (index: number) => { return featuresState.showCodeModel[index]; }; const handleTableChange = (props: any) => { setFeaturesState({ ...featuresState, sortField: props.sort.field, sortDirection: props.sort.direction, }); }; const getSortedItems = (items: Array) => { let sorted = sortBy(items, featuresState.sortField); if (featuresState.sortDirection == 'desc') { sorted = sorted.reverse(); } return sorted; }; const featureAttributes = get(props.detector, 'featureAttributes', []); const shingleSize = getShingleSizeFromObject(props.detector); const sorting = { sort: { field: featuresState.sortField, direction: featuresState.sortDirection, }, }; const items = featureAttributes.map( (feature: FeatureAttributes, index: number) => ({ name: feature.featureName, definition: index, state: feature.featureEnabled ? 'Enabled' : 'Disabled', }) ); const sortedItems = getSortedItems(items); const columns = [ { field: 'name', name: 'Feature name', sortable: true, }, { field: 'definition', name: 'Feature definition', render: (featureIndex: number) => { const feature = featureAttributes[featureIndex]; const metaData = get( props.detector, `uiMetadata.features.${feature.featureName}`, {} ); if ( Object.keys(metaData).length === 0 || metaData.featureType == FEATURE_TYPE.CUSTOM ) { return (

Custom expression:{' '} showModal(featureIndex)} > View code

{!getModalVisibilityChange(featureIndex) ? null : ( closeModal(featureIndex)} getModalVisibilityChange={() => getModalVisibilityChange(featureIndex) } /> )}
); } else { return (

Field: {metaData.aggregationOf || ''}

Aggregation method: {metaData.aggregationBy || ''}

); } }, }, { field: 'state', name: 'Feature state', }, ]; const getCellProps = () => { return { textOnly: true, }; }; const featureNum = Object.keys(featureAttributes).length; 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 shingle size.`; const previewText = `After you set the model features and other optional parameters, you can preview your anomalies from a sample feature output.`; return ( Edit , ]} > {featureNum == 0 ? ( Model parameters are required to run a detector } body={ {setParamsText}

{previewText}
} actions={[ Configure model , ]} /> ) : (
)}
); };