diff --git a/opensearch_dashboards.json b/opensearch_dashboards.json
index 551bd678..5aa5d906 100644
--- a/opensearch_dashboards.json
+++ b/opensearch_dashboards.json
@@ -8,7 +8,7 @@
"optionalPlugins": [
"dataSource",
"dataSourceManagement",
- "dataExplorer"
+ "assistantDashboards"
],
"requiredPlugins": [
"opensearchDashboardsUtils",
diff --git a/public/components/DiscoverAction/SuggestAnomalyDetector.test.tsx b/public/components/DiscoverAction/SuggestAnomalyDetector.test.tsx
index cca54108..4a320382 100644
--- a/public/components/DiscoverAction/SuggestAnomalyDetector.test.tsx
+++ b/public/components/DiscoverAction/SuggestAnomalyDetector.test.tsx
@@ -16,50 +16,13 @@ import {
import { Provider } from 'react-redux';
import configureStore from '../../redux/configureStore';
-import GenerateAnomalyDetector from './SuggestAnomalyDetector';
-import { DiscoverActionContext } from '../../../../../src/plugins/data_explorer/public';
+import SuggestAnomalyDetector from './SuggestAnomalyDetector';
import { fieldFormatsMock } from '../../../../../src/plugins/data/common/field_formats/mocks';
import { IndexPattern } from '../../../../../src/plugins/data/common';
import userEvent from '@testing-library/user-event';
import { HttpFetchOptionsWithPath } from '../../../../../src/core/public';
import { BASE_NODE_API_PATH } from '../../../utils/constants';
-
-const notifications = {
- toasts: {
- addDanger: jest.fn().mockName('addDanger'),
- addSuccess: jest.fn().mockName('addSuccess'),
- }
-};
-
-const getNotifications = () => {
- return notifications;
-}
-
-jest.mock('../../services', () => ({
- ...jest.requireActual('../../services'),
- getNotifications: getNotifications,
-}));
-
-const renderWithRouter = (context: DiscoverActionContext) => ({
- ...render(
-
-
-
- (
-
-
-
- )}
- />
-
-
-
- ),
-});
+import { getQueryService } from '../../services';
export function shouldReadFieldFromDocValues(aggregatable: boolean, opensearchType: string) {
return (
@@ -69,7 +32,6 @@ export function shouldReadFieldFromDocValues(aggregatable: boolean, opensearchTy
);
}
-
function stubbedSampleFields() {
return [
['bytes', 'long', true, true, { count: 10 }],
@@ -141,89 +103,92 @@ function createIndexPattern(id: string): IndexPattern {
};
}
-const expectedAnomalyDetector = {
- name: "test-pattern_anomaly_detector",
- description: "Created based on the OpenSearch Assistant",
- indices: ["test-pattern"],
- filterQuery: {
- match_all: {}
- },
- uiMetadata: {
- features: {
- feature_responseLatency: {
- featureType: "simple_aggs",
- aggregationBy: "avg",
- aggregationOf: "responseLatency"
- },
- feature_response: {
- featureType: "simple_aggs",
- aggregationBy: "sum",
- aggregationOf: "response"
- }
- },
- filters: []
- },
- featureAttributes: [
- {
- featureName: "feature_responseLatency",
- featureEnabled: true,
- importance: 1,
- aggregationQuery: {
- feature_response_latency: {
- avg: {
- field: "responseLatency"
- }
- }
- }
- },
- {
- featureName: "feature_response",
- featureEnabled: true,
- importance: 1,
- aggregationQuery: {
- feature_response: {
- sum: {
- field: "response"
- }
- }
- }
- }
- ],
- timeField: "timestamp",
- detectionInterval: {
- period: {
- interval: 10,
- unit: "Minutes"
- }
- },
- windowDelay: {
- period: {
- interval: 1,
- unit: "Minutes"
- }
- },
- shingleSize: 8,
- categoryField: ["ip"]
+const mockedIndexPattern = createIndexPattern('test-pattern');
+
+const notifications = {
+ toasts: {
+ addDanger: jest.fn().mockName('addDanger'),
+ addSuccess: jest.fn().mockName('addSuccess'),
+ }
};
+const getNotifications = () => {
+ return notifications;
+}
+
+jest.mock('../../services', () => ({
+ ...jest.requireActual('../../services'),
+ getNotifications: getNotifications,
+ getQueryService: jest.fn().mockReturnValue({
+ queryString: {
+ getQuery: jest.fn(),
+ },
+ }),
+ getIndexPatternService: () => ({
+ get: () => (mockedIndexPattern)
+ })
+}));
+
+const renderWithRouter = () => ({
+ ...render(
+
+
+
+ (
+
+
+
+ )}
+ />
+
+
+
+ ),
+});
+
describe('GenerateAnomalyDetector spec', () => {
- describe('Renders loading component', () => {
+ describe('Renders failed', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('renders with invalid dataset type', async () => {
+ const queryService = getQueryService();
+ queryService.queryString.getQuery.mockReturnValue({
+ dataset: {
+ id: undefined,
+ title: undefined,
+ type: 'INDEX'
+ },
+ });
+
+
+ const { queryByText } = renderWithRouter();
+ expect(queryByText('Suggested anomaly detector')).toBeNull();
+
+ await waitFor(() => {
+ expect(getNotifications().toasts.addDanger).toHaveBeenCalledTimes(1);
+ expect(getNotifications().toasts.addDanger).toHaveBeenCalledWith(
+ 'Unsupported dataset type'
+ );
+ });
+ });
+
it('renders empty component', async () => {
- httpClientMock.post = jest.fn().mockResolvedValue({
- ok: true,
- generatedParameters: {
- categoryField: '',
- aggregationField: '',
- aggregationMethod: '',
- dateFields: '',
+ const queryService = getQueryService();
+ queryService.queryString.getQuery.mockReturnValue({
+ dataset: {
+ id: undefined,
+ title: undefined,
+ type: 'INDEX_PATTERN'
},
});
- const context = {
- indexPattern: createIndexPattern(''),
- };
- const { queryByText } = renderWithRouter(context);
- expect(queryByText('Suggest anomaly detector')).toBeNull();
+ const { queryByText } = renderWithRouter();
+ expect(queryByText('Suggested anomaly detector')).toBeNull();
await waitFor(() => {
expect(getNotifications().toasts.addDanger).toHaveBeenCalledTimes(1);
@@ -232,17 +197,29 @@ describe('GenerateAnomalyDetector spec', () => {
);
});
});
+ });
+
+ describe('Renders loading component', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ const queryService = getQueryService();
+ queryService.queryString.getQuery.mockReturnValue({
+ dataset: {
+ id: 'test-pattern',
+ title: 'test-pattern',
+ type: 'INDEX_PATTERN',
+ timeFieldName: '@timestamp',
+ },
+ });
+ });
it('renders with empty generated parameters', async () => {
httpClientMock.post = jest.fn().mockResolvedValue({
ok: true,
});
- const context = {
- indexPattern: createIndexPattern('test-pattern'),
- }
- const { queryByText } = renderWithRouter(context);
- expect(queryByText('Suggest anomaly detector')).not.toBeNull();
+ const { queryByText } = renderWithRouter();
+ expect(queryByText('Suggested anomaly detector')).not.toBeNull();
await waitFor(() => {
expect(getNotifications().toasts.addDanger).toHaveBeenCalledTimes(1);
@@ -263,11 +240,8 @@ describe('GenerateAnomalyDetector spec', () => {
},
});
- const context = {
- indexPattern: createIndexPattern('test-pattern'),
- }
- const { queryByText } = renderWithRouter(context);
- expect(queryByText('Suggest anomaly detector')).not.toBeNull();
+ const { queryByText } = renderWithRouter();
+ expect(queryByText('Suggested anomaly detector')).not.toBeNull();
await waitFor(() => {
expect(getNotifications().toasts.addDanger).toHaveBeenCalledTimes(1);
@@ -288,11 +262,8 @@ describe('GenerateAnomalyDetector spec', () => {
},
});
- const context = {
- indexPattern: createIndexPattern('test-pattern'),
- }
- const { queryByText } = renderWithRouter(context);
- expect(queryByText('Suggest anomaly detector')).not.toBeNull();
+ const { queryByText } = renderWithRouter();
+ expect(queryByText('Suggested anomaly detector')).not.toBeNull();
await waitFor(() => {
expect(getNotifications().toasts.addDanger).toHaveBeenCalledTimes(1);
@@ -313,11 +284,8 @@ describe('GenerateAnomalyDetector spec', () => {
},
});
- const context = {
- indexPattern: createIndexPattern('test-pattern'),
- }
- const { queryByText } = renderWithRouter(context);
- expect(queryByText('Suggest anomaly detector')).not.toBeNull();
+ const { queryByText } = renderWithRouter();
+ expect(queryByText('Suggested anomaly detector')).not.toBeNull();
await waitFor(() => {
expect(getNotifications().toasts.addDanger).toHaveBeenCalledTimes(1);
@@ -338,11 +306,8 @@ describe('GenerateAnomalyDetector spec', () => {
},
});
- const context = {
- indexPattern: createIndexPattern('test-pattern'),
- }
- const { queryByText } = renderWithRouter(context);
- expect(queryByText('Suggest anomaly detector')).not.toBeNull();
+ const { queryByText } = renderWithRouter();
+ expect(queryByText('Suggested anomaly detector')).not.toBeNull();
await waitFor(() => {
expect(queryByText('Create detector')).not.toBeNull();
@@ -354,8 +319,20 @@ describe('GenerateAnomalyDetector spec', () => {
});
-
describe('Test API calls', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ const queryService = getQueryService();
+ queryService.queryString.getQuery.mockReturnValue({
+ dataset: {
+ id: 'test-pattern',
+ title: 'test-pattern',
+ type: 'INDEX_PATTERN',
+ timeFieldName: '@timestamp',
+ },
+ });
+ });
+
it('All API calls execute successfully', async () => {
httpClientMock.post = jest.fn((pathOrOptions: string | HttpFetchOptionsWithPath) => {
const url = typeof pathOrOptions === 'string' ? pathOrOptions : pathOrOptions.path;
@@ -384,11 +361,8 @@ describe('GenerateAnomalyDetector spec', () => {
}
});
- const context = {
- indexPattern: createIndexPattern('test-pattern'),
- }
- const { queryByText, getByTestId } = renderWithRouter(context);
- expect(queryByText('Suggest anomaly detector')).not.toBeNull();
+ const { queryByText, getByTestId } = renderWithRouter();
+ expect(queryByText('Suggested anomaly detector')).not.toBeNull();
await waitFor(() => {
expect(queryByText('Generating parameters...')).toBeNull();
expect(queryByText('Create detector')).not.toBeNull();
@@ -407,15 +381,6 @@ describe('GenerateAnomalyDetector spec', () => {
body: JSON.stringify({ index: 'test-pattern' }),
}
);
- expect(httpClientMock.post).toHaveBeenCalledWith(
- `${BASE_NODE_API_PATH}/detectors`,
- {
- body: JSON.stringify(expectedAnomalyDetector),
- }
- );
- expect(httpClientMock.post).toHaveBeenCalledWith(
- `${BASE_NODE_API_PATH}/detectors/test/start`
- );
expect(getNotifications().toasts.addSuccess).toHaveBeenCalledTimes(1);
});
});
@@ -426,11 +391,8 @@ describe('GenerateAnomalyDetector spec', () => {
error: 'Generate parameters failed'
});
- const context = {
- indexPattern: createIndexPattern('test-pattern'),
- }
- const { queryByText } = renderWithRouter(context);
- expect(queryByText('Suggest anomaly detector')).not.toBeNull();
+ const { queryByText } = renderWithRouter();
+ expect(queryByText('Suggested anomaly detector')).not.toBeNull();
await waitFor(() => {
expect(getNotifications().toasts.addDanger).toHaveBeenCalledTimes(1);
expect(getNotifications().toasts.addDanger).toHaveBeenCalledWith(
@@ -472,12 +434,8 @@ describe('GenerateAnomalyDetector spec', () => {
},
});
-
- const context = {
- indexPattern: createIndexPattern('test-pattern'),
- }
- const { queryByText, getByTestId } = renderWithRouter(context);
- expect(queryByText('Suggest anomaly detector')).not.toBeNull();
+ const { queryByText, getByTestId } = renderWithRouter();
+ expect(queryByText('Suggested anomaly detector')).not.toBeNull();
await waitFor(() => {
expect(queryByText('Generating parameters...')).toBeNull();
@@ -539,11 +497,8 @@ describe('GenerateAnomalyDetector spec', () => {
});
- const context = {
- indexPattern: createIndexPattern('test-pattern'),
- }
- const { queryByText, getByTestId } = renderWithRouter(context);
- expect(queryByText('Suggest anomaly detector')).not.toBeNull();
+ const { queryByText, getByTestId } = renderWithRouter();
+ expect(queryByText('Suggested anomaly detector')).not.toBeNull();
await waitFor(() => {
expect(queryByText('Generating parameters...')).toBeNull();
diff --git a/public/components/DiscoverAction/SuggestAnomalyDetector.tsx b/public/components/DiscoverAction/SuggestAnomalyDetector.tsx
index a5ec1a59..58fa7033 100644
--- a/public/components/DiscoverAction/SuggestAnomalyDetector.tsx
+++ b/public/components/DiscoverAction/SuggestAnomalyDetector.tsx
@@ -61,7 +61,7 @@ import { formikToDetector } from '../../pages/ReviewAndCreate/utils/helpers';
import { FormattedFormRow } from '../FormattedFormRow/FormattedFormRow';
import { FeatureAccordion } from '../../pages/ConfigureModel/components/FeatureAccordion';
import { AD_DOCS_LINK, DEFAULT_SHINGLE_SIZE, MAX_FEATURE_NUM, PLUGIN_NAME } from '../../utils/constants';
-import { getNotifications } from '../../services';
+import { getIndexPatternService, getNotifications, getQueryService } from '../../services';
import { prettifyErrorMessage } from '../../../server/utils/helpers';
import EnhancedAccordion from '../FeatureAnywhereContextMenu/EnhancedAccordion';
import MinimalAccordion from '../FeatureAnywhereContextMenu/MinimalAccordion';
@@ -69,10 +69,10 @@ import { DataFilterList } from '../../pages/DefineDetector/components/DataFilter
import { generateParameters } from '../../redux/reducers/assistant';
import { FEATURE_TYPE } from '../../models/interfaces';
import { FeaturesFormikValues } from '../../pages/ConfigureModel/models/interfaces';
-import { DiscoverActionContext } from '../../../../../src/plugins/data_explorer/public/types';
import { getMappings } from '../../redux/reducers/opensearch';
import { mountReactNode } from '../../../../../src/core/public/utils';
import { formikToDetectorName } from '../FeatureAnywhereContextMenu/CreateAnomalyDetector/helpers';
+import { DEFAULT_DATA } from '../../../../../src/plugins/data/common';
export interface GeneratedParameters {
categoryField: string;
@@ -80,41 +80,35 @@ export interface GeneratedParameters {
dateFields: string[];
}
-function GenerateAnomalyDetector({
+function SuggestAnomalyDetector({
closeFlyout,
- context,
}: {
closeFlyout: any;
- context: DiscoverActionContext;
}) {
const dispatch = useDispatch();
const notifications = getNotifications();
- const indexPatternId = context.indexPattern?.id;
- const indexPatternName = context.indexPattern?.title;
- if (!indexPatternId || !indexPatternName) {
+ const queryString = getQueryService().queryString;
+ const dataset = queryString.getQuery().dataset || queryString.getDefaultQuery().dataset;
+ if (dataset.type != DEFAULT_DATA.SET_TYPES.INDEX_PATTERN) {
notifications.toasts.addDanger(
- 'Cannot extract index pattern from the context'
+ 'Unsupported dataset type'
);
return <>>;
}
- const dataSourceId = context.indexPattern?.dataSourceRef?.id;
- const timeFieldFromIndexPattern = context.indexPattern?.timeFieldName;
- const fieldsFromContext = context.indexPattern?.fields || [];
- const [categoricalFields, dateFields] = fieldsFromContext.reduce(
- ([cFields, dFields], indexPatternField) => {
- const esType = indexPatternField.spec.esTypes?.[0];
- const name = indexPatternField.spec.name;
- if (esType === 'keyword' || esType === 'ip') {
- cFields.push(name);
- } else if (esType === 'date') {
- dFields.push(name);
- }
- return [cFields, dFields];
- },
- [[], []] as [string[], string[]]
- ) || [[], []];
+ const indexPatternId = dataset.id;
+ const indexPatternName = dataset.title;
+ const timeFieldFromIndexPattern = dataset.timeFieldName;
+ if (!indexPatternId || !indexPatternName || !timeFieldFromIndexPattern) {
+ notifications.toasts.addDanger(
+ 'Cannot extract index pattern from the context'
+ );
+ return <>>;
+ }
+ const [dataSourceId, setDataSourceId] = useState(undefined);
+ const [categoricalFields, setCategoricalFields] = useState([]);
+ const [dateFields, setDateFields] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [buttonName, setButtonName] = useState(
'Generating parameters...'
@@ -130,6 +124,37 @@ function GenerateAnomalyDetector({
formikToDetectorName(indexPatternName.substring(0, 40))
);
+ async function getIndexPatternDetails() {
+ try {
+ const indexPatternService = getIndexPatternService();
+ const indexPatternDetail = await indexPatternService.get(indexPatternId);
+
+ setDataSourceId(indexPatternDetail?.dataSourceId);
+
+ const fieldsFromContext = indexPatternDetail?.fields || [];
+ const [categoricalFieldsFromContext, dateFieldsFromContext] = fieldsFromContext.reduce(
+ ([cFields, dFields], indexPatternField) => {
+ const esType = indexPatternField.spec.esTypes?.[0];
+ const name = indexPatternField.spec.name;
+ if (esType === 'keyword' || esType === 'ip') {
+ cFields.push(name);
+ } else if (esType === 'date') {
+ dFields.push(name);
+ }
+ return [cFields, dFields];
+ },
+ [[], []] as [string[], string[]]
+ ) || [[], []];
+
+ setCategoricalFields(categoricalFieldsFromContext);
+ setDateFields(dateFieldsFromContext);
+ } catch (error) {
+ notifications.toasts.addDanger(
+ 'Get index pattern details failed, reason: ' + error
+ );
+ }
+ }
+
// let LLM to generate parameters for creating anomaly detector
async function getParameters() {
try {
@@ -207,6 +232,7 @@ function GenerateAnomalyDetector({
useEffect(() => {
async function fetchData() {
+ await getIndexPatternDetails();
await getParameters();
const getMappingDispatchCall = dispatch(
getMappings(indexPatternName, dataSourceId)
@@ -382,7 +408,7 @@ function GenerateAnomalyDetector({
- Suggest anomaly detector
+ Suggested anomaly detector
@@ -857,4 +883,4 @@ function GenerateAnomalyDetector({
);
}
-export default GenerateAnomalyDetector;
+export default SuggestAnomalyDetector;
diff --git a/public/plugin.ts b/public/plugin.ts
index 68eedfcf..b53ebc59 100644
--- a/public/plugin.ts
+++ b/public/plugin.ts
@@ -27,7 +27,7 @@ import {
} from '../../../src/plugins/embeddable/public';
import { ACTION_AD } from './action/ad_dashboard_action';
import { APP_PATH, DASHBOARD_PAGE_NAV_ID, DETECTORS_PAGE_NAV_ID, OVERVIEW_PAGE_NAV_ID, PLUGIN_NAME } from './utils/constants';
-import { getActions } from './utils/contextMenu/getActions';
+import { ACTION_SUGGEST_AD, getActions, getSuggestAnomalyDetectorAction } from './utils/contextMenu/getActions';
import { overlayAnomaliesFunction } from './expressions/overlay_anomalies';
import {
setClient,
@@ -42,7 +42,8 @@ import {
setDataSourceManagementPlugin,
setDataSourceEnabled,
setNavigationUI,
- setApplication
+ setApplication,
+ setIndexPatternService
} from './services';
import { AnomalyDetectionOpenSearchDashboardsPluginStart } from 'public';
import {
@@ -50,16 +51,16 @@ import {
VisAugmenterStart,
} from '../../../src/plugins/vis_augmenter/public';
import { UiActionsStart } from '../../../src/plugins/ui_actions/public';
-import { DataPublicPluginStart } from '../../../src/plugins/data/public';
+import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../src/plugins/data/public';
import { DataSourceManagementPluginSetup } from '../../../src/plugins/data_source_management/public';
import { DataSourcePluginSetup } from '../../../src/plugins/data_source/public';
import { NavigationPublicPluginStart } from '../../../src/plugins/navigation/public';
-import { getDiscoverAction } from './utils/discoverAction';
-import { DataExplorerPluginSetup } from '../../../src/plugins/data_explorer/public';
+import { AssistantSetup } from '../../../plugins/dashboards-assistant/public';
declare module '../../../src/plugins/ui_actions/public' {
export interface ActionContextMapping {
[ACTION_AD]: {};
+ [ACTION_SUGGEST_AD]: {}
}
}
@@ -70,7 +71,7 @@ export interface AnomalyDetectionSetupDeps {
visAugmenter: VisAugmenterSetup;
dataSourceManagement: DataSourceManagementPluginSetup;
dataSource: DataSourcePluginSetup;
- dataExplorer: DataExplorerPluginSetup;
+ data: DataPublicPluginSetup;
}
export interface AnomalyDetectionStartDeps {
@@ -192,9 +193,9 @@ export class AnomalyDetectionOpenSearchDashboardsPlugin
plugins.uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, action);
});
- // Add action to Discover
- const discoverAction = getDiscoverAction();
- plugins.dataExplorer.registerDiscoverAction(discoverAction);
+ // Add suggest anomaly detector action to the uiActions in Discover
+ const suggestAnomalyDetectorAction = getSuggestAnomalyDetectorAction();
+ plugins.uiActions.addTriggerAction(plugins.assistantDashboards.assistantTriggers.AI_ASSISTANT_TRIGGER, suggestAnomalyDetectorAction);
// registers the expression function used to render anomalies on an Augmented Visualization
plugins.expressions.registerFunction(overlayAnomaliesFunction);
@@ -212,6 +213,7 @@ export class AnomalyDetectionOpenSearchDashboardsPlugin
setNotifications(core.notifications);
setUiActions(uiActions);
setQueryService(data.query);
+ setIndexPatternService(data.indexPatterns);
setSavedObjectsClient(core.savedObjects.client);
setNavigationUI(navigation.ui);
setApplication(core.application);
diff --git a/public/services.ts b/public/services.ts
index 0c3d45dd..f7f4d935 100644
--- a/public/services.ts
+++ b/public/services.ts
@@ -45,6 +45,9 @@ export const [getUISettings, setUISettings] =
export const [getQueryService, setQueryService] =
createGetterSetter('Query');
+export const [getIndexPatternService, setIndexPatternService] =
+ createGetterSetter('IndexPatterns');
+
export const [getSavedObjectsClient, setSavedObjectsClient] =
createGetterSetter('SavedObjectsClient');
@@ -54,10 +57,10 @@ export const [getDataSourceManagementPlugin, setDataSourceManagementPlugin] =
export const [getDataSourceEnabled, setDataSourceEnabled] =
createGetterSetter('DataSourceEnabled');
-export const [getNavigationUI, setNavigationUI] =
+export const [getNavigationUI, setNavigationUI] =
createGetterSetter('navigation');
-export const [getApplication, setApplication] =
+export const [getApplication, setApplication] =
createGetterSetter('application');
// This is primarily used for mocking this module and each of its fns in tests.
diff --git a/public/utils/contextMenu/getActions.tsx b/public/utils/contextMenu/getActions.tsx
index f58a7a9e..30ae041e 100644
--- a/public/utils/contextMenu/getActions.tsx
+++ b/public/utils/contextMenu/getActions.tsx
@@ -7,7 +7,7 @@ import React from 'react';
import { i18n } from '@osd/i18n';
import { EuiIconType } from '@elastic/eui';
import { toMountPoint } from '../../../../../src/plugins/opensearch_dashboards_react/public';
-import { Action } from '../../../../../src/plugins/ui_actions/public';
+import { Action, createAction } from '../../../../../src/plugins/ui_actions/public';
import { createADAction } from '../../action/ad_dashboard_action';
import AnywhereParentFlyout from '../../components/FeatureAnywhereContextMenu/AnywhereParentFlyout';
import { Provider } from 'react-redux';
@@ -16,6 +16,9 @@ import DocumentationTitle from '../../components/FeatureAnywhereContextMenu/Docu
import { AD_FEATURE_ANYWHERE_LINK, ANOMALY_DETECTION_ICON } from '../constants';
import { getClient, getOverlays } from '../../../public/services';
import { FLYOUT_MODES } from '../../../public/components/FeatureAnywhereContextMenu/AnywhereParentFlyout/constants';
+import SuggestAnomalyDetector from '../../../public/components/DiscoverAction/SuggestAnomalyDetector';
+
+export const ACTION_SUGGEST_AD = 'suggestAnomalyDetector';
// This is used to create all actions in the same context menu
const grouping: Action['grouping'] = [
@@ -31,23 +34,23 @@ const grouping: Action['grouping'] = [
export const getActions = () => {
const getOnClick =
(startingFlyout) =>
- async ({ embeddable }) => {
- const overlayService = getOverlays();
- const openFlyout = overlayService.openFlyout;
- const store = configureStore(getClient());
- const overlay = openFlyout(
- toMountPoint(
-
- overlay.close()}
- />
-
- ),
- { size: 'm', className: 'context-menu__flyout' }
- );
- };
+ async ({ embeddable }) => {
+ const overlayService = getOverlays();
+ const openFlyout = overlayService.openFlyout;
+ const store = configureStore(getClient());
+ const overlay = openFlyout(
+ toMountPoint(
+
+ overlay.close()}
+ />
+
+ ),
+ { size: 'm', className: 'context-menu__flyout' }
+ );
+ };
return [
{
@@ -87,3 +90,31 @@ export const getActions = () => {
},
].map((options) => createADAction({ ...options, grouping }));
};
+
+export const getSuggestAnomalyDetectorAction = () => {
+ const onClick = async function () {
+ const overlayService = getOverlays();
+ const openFlyout = overlayService.openFlyout;
+ const store = configureStore(getClient());
+ const overlay = openFlyout(
+ toMountPoint(
+
+ overlay.close()}
+ />
+
+ )
+ );
+ }
+
+ return createAction({
+ id: 'suggestAnomalyDetector',
+ order: 100,
+ type: ACTION_SUGGEST_AD,
+ getDisplayName: () => 'Suggest anomaly detector',
+ getIconType: () => ANOMALY_DETECTION_ICON,
+ execute: async () => {
+ onClick();
+ },
+ });
+}
diff --git a/public/utils/discoverAction.tsx b/public/utils/discoverAction.tsx
deleted file mode 100644
index 9b345ee8..00000000
--- a/public/utils/discoverAction.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright OpenSearch Contributors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import React from 'react'
-import { ANOMALY_DETECTION_ICON } from "./constants";
-import GenerateAnomalyDetector from "../components/DiscoverAction/SuggestAnomalyDetector";
-import { getClient, getOverlays } from '../../public/services';
-import { toMountPoint } from "../../../../src/plugins/opensearch_dashboards_react/public";
-import { Provider } from "react-redux";
-import configureStore from '../redux/configureStore';
-import { DiscoverAction, DiscoverActionContext } from "../../../../src/plugins/data_explorer/public/types";
-
-export const getDiscoverAction = (): DiscoverAction => {
- const onClick = function (context: DiscoverActionContext) {
- const overlayService = getOverlays();
- const openFlyout = overlayService.openFlyout;
- const store = configureStore(getClient());
- const overlay = openFlyout(
- toMountPoint(
-
- overlay.close()}
- context={context}
- />
-
- )
- );
- }
-
- return {
- order: 0,
- name: 'Suggest anomaly detector',
- iconType: ANOMALY_DETECTION_ICON,
- onClick: onClick,
- }
-};
diff --git a/server/routes/assistant.ts b/server/routes/assistant.ts
index 6669b9c3..5c1a0cd0 100644
--- a/server/routes/assistant.ts
+++ b/server/routes/assistant.ts
@@ -56,16 +56,14 @@ export default class AssistantService {
});
if (
- !getAgentResponse ||
- !getAgentResponse['configuration'] ||
- !getAgentResponse['configuration']['agent_id']
+ !getAgentResponse || !(getAgentResponse.ml_configuration?.agent_id || getAgentResponse.configuration?.agent_id)
) {
throw new Error(
'Cannot get flow agent id for generating anomaly detector'
);
}
- const agentId = getAgentResponse['configuration']['agent_id'];
+ const agentId = getAgentResponse.ml_configuration?.agent_id || getAgentResponse.configuration?.agent_id;
const executeAgentResponse = await callWithRequest('ml.executeAgent', {
agentId: agentId,
diff --git a/server/utils/constants.ts b/server/utils/constants.ts
index 8c071556..1a756187 100644
--- a/server/utils/constants.ts
+++ b/server/utils/constants.ts
@@ -133,4 +133,4 @@ export const HISTORICAL_TASK_TYPES = [
export const CUSTOM_AD_RESULT_INDEX_PREFIX = 'opensearch-ad-plugin-result-';
-export const SUGGEST_ANOMALY_DETECTOR_CONFIG_ID = 'suggest_anomaly_detector';
+export const SUGGEST_ANOMALY_DETECTOR_CONFIG_ID = 'os_suggest_ad';