Skip to content

Commit

Permalink
Register AD as dashboard context menu option (#482)
Browse files Browse the repository at this point in the history
* Register AD as dashboard context menu option

Signed-off-by: Jackie Han <jkhanjob@gmail.com>

* addressing comments

Signed-off-by: Jackie Han <jkhanjob@gmail.com>

* add getActions props

Signed-off-by: Jackie Han <jkhanjob@gmail.com>

* add EmbeddableStart

Signed-off-by: Jackie Han <jkhanjob@gmail.com>

* remove spread operator

Signed-off-by: Jackie Han <jkhanjob@gmail.com>

* clenaup

Signed-off-by: Jackie Han <jkhanjob@gmail.com>

* add overlay getter and setter

Signed-off-by: Jackie Han <jkhanjob@gmail.com>

---------

Signed-off-by: Jackie Han <jkhanjob@gmail.com>
  • Loading branch information
jackiehanyang committed May 19, 2023
1 parent 23c8142 commit efef2e2
Show file tree
Hide file tree
Showing 10 changed files with 325 additions and 49 deletions.
9 changes: 8 additions & 1 deletion opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@
"opensearchDashboardsUtils",
"expressions",
"data",
"visAugmenter"
"visAugmenter",
"uiActions",
"dashboard",
"embeddable",
"opensearchDashboardsReact",
"savedObjects",
"visAugmenter",
"opensearchDashboardsUtils"
],
"server": true,
"ui": true
Expand Down
78 changes: 78 additions & 0 deletions public/action/ad_dashboard_action.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import { IEmbeddable } from '../../../../src/plugins/dashboard/public/embeddable_plugin';
import {
DASHBOARD_CONTAINER_TYPE,
DashboardContainer,
} from '../../../../src/plugins/dashboard/public';
import {
IncompatibleActionError,
createAction,
Action,
} from '../../../../src/plugins/ui_actions/public';
import { isReferenceOrValueEmbeddable } from '../../../../src/plugins/embeddable/public';
import { EuiIconType } from '@elastic/eui/src/components/icon/icon';

export const ACTION_AD = 'ad';

function isDashboard(
embeddable: IEmbeddable
): embeddable is DashboardContainer {
return embeddable.type === DASHBOARD_CONTAINER_TYPE;
}

export interface ActionContext {
embeddable: IEmbeddable;
}

export interface CreateOptions {
grouping: Action['grouping'];
title: string;
icon: EuiIconType;
id: string;
order: number;
onClick: Function;
}

export const createADAction = ({
grouping,
title,
icon,
id,
order,
onClick,
}: CreateOptions) =>
createAction({
id,
order,
getDisplayName: ({ embeddable }: ActionContext) => {
if (!embeddable.parent || !isDashboard(embeddable.parent)) {
throw new IncompatibleActionError();
}
return title;
},
getIconType: () => icon,
type: ACTION_AD,
grouping,
isCompatible: async ({ embeddable }: ActionContext) => {
const paramsType = embeddable.vis?.params?.type;
const seriesParams = embeddable.vis?.params?.seriesParams || [];
const series = embeddable.vis?.params?.series || [];
const isLineGraph =
seriesParams.find((item) => item.type === 'line') ||
series.find((item) => item.chart_type === 'line');
const isValidVis = isLineGraph && paramsType !== 'table';
return Boolean(
embeddable.parent && isDashboard(embeddable.parent) && isValidVis
);
},
execute: async ({ embeddable }: ActionContext) => {
if (!isReferenceOrValueEmbeddable(embeddable)) {
throw new IncompatibleActionError();
}

onClick({ embeddable });
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import React, { useState } from 'react';
import { get } from 'lodash';
import AddAnomalyDetector from '../CreateAnomalyDetector';
import { getEmbeddable } from '../../../../public/services';

const AnywhereParentFlyout = ({ startingFlyout, ...props }) => {
const embeddable = getEmbeddable().getEmbeddableFactory;
const indices: { label: string }[] = [
{ label: get(embeddable, 'vis.data.indexPattern.title', '') },
];

const [mode, setMode] = useState(startingFlyout);
const [selectedDetectorId, setSelectedDetectorId] = useState();

const AnywhereFlyout = {
create: AddAnomalyDetector,
}[mode];

return (
<AnywhereFlyout
{...{
...props,
setMode,
mode,
indices,
selectedDetectorId,
setSelectedDetectorId,
}}
/>
);
};

export default AnywhereParentFlyout;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import AnywhereParentFlyout from './AnywhereParentFlyout';

export default AnywhereParentFlyout;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { EuiIcon, EuiFlexItem, EuiFlexGroup } from '@elastic/eui';
import { i18n } from '@osd/i18n';

const DocumentationTitle = () => (
<EuiFlexGroup>
<EuiFlexItem>
<span data-ui="documentation-title-text">
{i18n.translate(
'dashboard.actions.adMenuItem.documentation.displayName',
{
defaultMessage: 'Documentation',
}
)}
</span>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiIcon type="popout" />
</EuiFlexItem>
</EuiFlexGroup>
);

export default DocumentationTitle;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import DocumentationTitle from './containers/DocumentationTitle';

export default DocumentationTitle;
109 changes: 62 additions & 47 deletions public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,58 +14,73 @@ import {
CoreSetup,
CoreStart,
Plugin,
PluginInitializerContext,
} from '../../../src/core/public';
import {
AnomalyDetectionOpenSearchDashboardsPluginSetup,
AnomalyDetectionOpenSearchDashboardsPluginStart,
} from '.';
import { CONTEXT_MENU_TRIGGER, EmbeddableSetup, EmbeddableStart } from '../../../src/plugins/embeddable/public';
import { ACTION_AD } from './action/ad_dashboard_action';
import { PLUGIN_NAME } from './utils/constants';
import { getActions } from './utils/contextMenu/getActions';
import { overlayAnomaliesFunction } from './expressions/overlay_anomalies';
import { setClient } from './services';
import { setClient, setEmbeddable, setOverlays } from './services';
import { AnomalyDetectionOpenSearchDashboardsPluginStart } from 'public';
import { createStartServicesGetter } from '../../../src/plugins/opensearch_dashboards_utils/public';

export class AnomalyDetectionOpenSearchDashboardsPlugin
implements
Plugin<
AnomalyDetectionOpenSearchDashboardsPluginSetup,
AnomalyDetectionOpenSearchDashboardsPluginStart
>
{
constructor(private readonly initializerContext: PluginInitializerContext) {
// can retrieve config from initializerContext
declare module '../../../src/plugins/ui_actions/public' {
export interface ActionContextMapping {
[ACTION_AD]: {};
}
}

public setup(
core: CoreSetup,
plugins
): AnomalyDetectionOpenSearchDashboardsPluginSetup {
core.application.register({
id: 'anomaly-detection-dashboards',
title: 'Anomaly Detection',
category: {
id: 'opensearch',
label: 'OpenSearch Plugins',
order: 2000,
},
order: 5000,
mount: async (params: AppMountParameters) => {
const { renderApp } = await import('./anomaly_detection_app');
const [coreStart, depsStart] = await core.getStartServices();
return renderApp(coreStart, params);
},
});
export interface AnomalyDetectionSetupDeps {
embeddable: EmbeddableSetup;
}

// Set the HTTP client so it can be pulled into expression fns to make
// direct server-side calls
setClient(core.http);
export interface AnomalyDetectionStartDeps {
embeddable: EmbeddableStart;
}

// registers the expression function used to render anomalies on an Augmented Visualization
plugins.expressions.registerFunction(overlayAnomaliesFunction);
return {};
}
export class AnomalyDetectionOpenSearchDashboardsPlugin implements
Plugin<AnomalyDetectionSetupDeps, AnomalyDetectionStartDeps> {

public setup(core: CoreSetup, plugins: any) {
core.application.register({
id: PLUGIN_NAME,
title: 'Anomaly Detection',
category: {
id: 'opensearch',
label: 'OpenSearch Plugins',
order: 2000,
},
order: 5000,
mount: async (params: AppMountParameters) => {
const { renderApp } = await import('./anomaly_detection_app');
const [coreStart] = await core.getStartServices();
return renderApp(coreStart, params);
},
});

public start(
core: CoreStart
): AnomalyDetectionOpenSearchDashboardsPluginStart {
return {};
}
}
// Set the HTTP client so it can be pulled into expression fns to make
// direct server-side calls
setClient(core.http);

// Create context menu actions. Pass core, to access service for flyouts.
const actions = getActions();

// Add actions to uiActions
actions.forEach((action) => {
plugins.uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, action);
});

// registers the expression function used to render anomalies on an Augmented Visualization
plugins.expressions.registerFunction(overlayAnomaliesFunction);
return {};
}

public start(
core: CoreStart,
{embeddable }: AnomalyDetectionStartDeps
): AnomalyDetectionOpenSearchDashboardsPluginStart {
setEmbeddable(embeddable);
setOverlays(core.overlays);
return {};
}
}
9 changes: 8 additions & 1 deletion public/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { CoreStart } from '../../../src/core/public';
import { CoreStart, OverlayStart } from '../../../src/core/public';
import { EmbeddableStart } from '../../../src/plugins/embeddable/public';
import { createGetterSetter } from '../../../src/plugins/opensearch_dashboards_utils/public';
import { SavedObjectLoader } from '../../../src/plugins/saved_objects/public';

Expand All @@ -12,3 +13,9 @@ export const [getSavedFeatureAnywhereLoader, setSavedFeatureAnywhereLoader] =

export const [getClient, setClient] =
createGetterSetter<CoreStart['http']>('http');

export const [getEmbeddable, setEmbeddable] =
createGetterSetter<EmbeddableStart>('Embeddable');

export const [getOverlays, setOverlays] =
createGetterSetter<OverlayStart>('Overlays');
4 changes: 4 additions & 0 deletions public/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export const ANOMALY_RESULT_INDEX = '.opendistro-anomaly-results';

export const BASE_DOCS_LINK = 'https://opensearch.org/docs/monitoring-plugins';

export const AD_DOCS_LINK = 'https://opensearch.org/docs/latest/observing-your-data/ad/index/';

export const MAX_DETECTORS = 1000;

export const MAX_ANOMALIES = 10000;
Expand Down Expand Up @@ -87,3 +89,5 @@ export enum MISSING_FEATURE_DATA_SEVERITY {
}

export const SPACE_STR = ' ';

export const APM_TRACE = 'apmTrace';
Loading

0 comments on commit efef2e2

Please sign in to comment.