Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ML] Decouple open-in-anomaly-explorer action #178729

Merged
1 change: 0 additions & 1 deletion x-pack/plugins/ml/public/ui_actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ export function registerMlUiActions(

// Register actions
uiActions.registerAction(editSwimlanePanelAction);
uiActions.registerAction(openInExplorerAction);
uiActions.registerAction(applyInfluencerFiltersAction);
uiActions.registerAction(applyEntityFieldFilterAction);
uiActions.registerAction(applyTimeRangeSelectionAction);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,41 @@
*/

import { i18n } from '@kbn/i18n';
import type { SerializableRecord } from '@kbn/utility-types';
import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public';
import { ML_ENTITY_FIELD_OPERATIONS } from '@kbn/ml-anomaly-utils';
import type { MlCoreSetup } from '../plugin';
import type { EmbeddableApiContext, HasParentApi, HasType } from '@kbn/presentation-publishing';
import { apiIsOfType } from '@kbn/presentation-publishing';
import { apiHasType } from '@kbn/presentation-publishing';
import { createAction } from '@kbn/ui-actions-plugin/public';
import type { SerializableRecord } from '@kbn/utility-types';
import { ML_APP_LOCATOR } from '../../common/constants/locator';
import type { AnomalyChartsFieldSelectionContext, SwimLaneDrilldownContext } from '../embeddables';
import type { ExplorerAppState } from '../../common/types/locator';
import type {
AnomalyExplorerChartsEmbeddableType,
AnomalySwimLaneEmbeddableType,
} from '../embeddables';
import {
ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE,
ANOMALY_SWIMLANE_EMBEDDABLE_TYPE,
isAnomalyExplorerEmbeddable,
isSwimLaneEmbeddable,
} from '../embeddables';
import type { ExplorerAppState } from '../../common/types/locator';
import type { MlCoreSetup } from '../plugin';

export type OpenInAnomalyExplorerActionApi = HasType<
AnomalySwimLaneEmbeddableType | AnomalyExplorerChartsEmbeddableType
> &
Partial<HasParentApi<HasType>>;

export const OPEN_IN_ANOMALY_EXPLORER_ACTION = 'openInAnomalyExplorerAction';

export function createOpenInExplorerAction(
getStartServices: MlCoreSetup['getStartServices']
): UiActionsActionDefinition<SwimLaneDrilldownContext | AnomalyChartsFieldSelectionContext> {
return {
export const isApiCompatible = (api: unknown | null): api is OpenInAnomalyExplorerActionApi =>
Boolean(apiHasType(api));

export function createOpenInExplorerAction(getStartServices: MlCoreSetup['getStartServices']) {
return createAction<EmbeddableApiContext>({
id: 'open-in-anomaly-explorer',
type: OPEN_IN_ANOMALY_EXPLORER_ACTION,
getIconType(context): string {
getIconType(): string {
return 'visTable';
},
getDisplayName() {
Expand Down Expand Up @@ -122,13 +134,12 @@ export function createOpenInExplorerAction(
await application.navigateToUrl(anomalyExplorerUrl!);
}
},
async isCompatible({
embeddable,
}: SwimLaneDrilldownContext | AnomalyChartsFieldSelectionContext) {
async isCompatible({ embeddable }: EmbeddableApiContext) {
if (!isApiCompatible(embeddable)) return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Here, wouldn't it be simpler to call your more specific type guards like:

return isSwimLaneEmbeddableContext(context) || isAnomalyChartsEmbeddableContext(context)? That way you wouldn't need to have the separate isApiCompatible method which checks the same things?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I first wrote this isCompatible method looking at the example and added custom type guards later. Updated in dfaef99

return (
embeddable.type === ANOMALY_SWIMLANE_EMBEDDABLE_TYPE ||
embeddable.type === ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE
apiIsOfType(embeddable, ANOMALY_SWIMLANE_EMBEDDABLE_TYPE) ||
apiIsOfType(embeddable, ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE)
);
},
};
});
}