forked from elastic/kibana
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ML] Anomaly Detection: Add 'Add to dashboard' action for Single Metr…
…ic Viewer (elastic#182538) ## Summary Adds an action to add the Single Metric Viewer to new or existing dashboards. Related meta issue: elastic#181272 https://github.com/elastic/kibana/assets/6446462/a95cc114-fcb4-4dd3-8f9c-68f50d7749dd ### Checklist Delete any items that are not applicable to this PR. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --------- Co-authored-by: Kibana Machine <[email protected]>
- Loading branch information
1 parent
7e49f2d
commit e2807c3
Showing
6 changed files
with
262 additions
and
52 deletions.
There are no files selected for viewing
8 changes: 8 additions & 0 deletions
8
.../ml/public/application/timeseriesexplorer/components/timeseriesexplorer_controls/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
export { TimeSeriesExplorerControls } from './timeseriesexplorer_controls'; |
230 changes: 230 additions & 0 deletions
230
...timeseriesexplorer/components/timeseriesexplorer_controls/timeseriesexplorer_controls.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import type { FC } from 'react'; | ||
import React, { useCallback, useState } from 'react'; | ||
import type { EuiContextMenuPanelDescriptor } from '@elastic/eui'; | ||
import { | ||
EuiButtonIcon, | ||
EuiCheckbox, | ||
EuiContextMenu, | ||
EuiFlexGroup, | ||
EuiFlexItem, | ||
EuiPopover, | ||
htmlIdGenerator, | ||
} from '@elastic/eui'; | ||
import { i18n } from '@kbn/i18n'; | ||
import { FormattedMessage } from '@kbn/i18n-react'; | ||
import type { SaveModalDashboardProps } from '@kbn/presentation-util-plugin/public'; | ||
import { | ||
LazySavedObjectSaveModalDashboard, | ||
withSuspense, | ||
} from '@kbn/presentation-util-plugin/public'; | ||
import type { JobId } from '../../../../../common/types/anomaly_detection_jobs/job'; | ||
import { useMlKibana } from '../../../contexts/kibana'; | ||
import { getDefaultSingleMetricViewerPanelTitle } from '../../../../embeddables/single_metric_viewer/get_default_panel_title'; | ||
import type { MlEntity } from '../../../../embeddables'; | ||
import { ANOMALY_SINGLE_METRIC_VIEWER_EMBEDDABLE_TYPE } from '../../../../embeddables/constants'; | ||
import type { SingleMetricViewerEmbeddableState } from '../../../../embeddables/types'; | ||
|
||
interface Props { | ||
selectedDetectorIndex: number; | ||
selectedEntities?: MlEntity; | ||
selectedJobId: JobId; | ||
showAnnotationsCheckbox: boolean; | ||
showAnnotations: boolean; | ||
showForecastCheckbox: boolean; | ||
showForecast: boolean; | ||
showModelBoundsCheckbox: boolean; | ||
showModelBounds: boolean; | ||
onShowModelBoundsChange: () => void; | ||
onShowAnnotationsChange: () => void; | ||
onShowForecastChange: () => void; | ||
} | ||
|
||
const SavedObjectSaveModalDashboard = withSuspense(LazySavedObjectSaveModalDashboard); | ||
|
||
function getDefaultEmbeddablePanelConfig(jobId: JobId, queryString?: string) { | ||
return { | ||
title: getDefaultSingleMetricViewerPanelTitle(jobId).concat( | ||
queryString ? `- ${queryString}` : '' | ||
), | ||
id: htmlIdGenerator()(), | ||
}; | ||
} | ||
|
||
export const TimeSeriesExplorerControls: FC<Props> = ({ | ||
selectedDetectorIndex, | ||
selectedEntities, | ||
selectedJobId, | ||
showAnnotations, | ||
showAnnotationsCheckbox, | ||
showForecast, | ||
showForecastCheckbox, | ||
showModelBounds, | ||
showModelBoundsCheckbox, | ||
onShowAnnotationsChange, | ||
onShowModelBoundsChange, | ||
onShowForecastChange, | ||
}) => { | ||
const [isMenuOpen, setIsMenuOpen] = useState<boolean>(false); | ||
const [createInDashboard, setCreateInDashboard] = useState<boolean>(false); | ||
|
||
const { | ||
services: { | ||
application: { capabilities }, | ||
embeddable, | ||
}, | ||
} = useMlKibana(); | ||
|
||
const canEditDashboards = capabilities.dashboard?.createNew ?? false; | ||
|
||
const closePopoverOnAction = useCallback( | ||
(actionCallback: Function) => { | ||
return () => { | ||
setIsMenuOpen(false); | ||
actionCallback(); | ||
}; | ||
}, | ||
[setIsMenuOpen] | ||
); | ||
|
||
const menuPanels: EuiContextMenuPanelDescriptor[] = [ | ||
{ | ||
id: 0, | ||
items: [ | ||
{ | ||
name: ( | ||
<FormattedMessage | ||
id="xpack.ml.timeseriesExplorer.addToDashboardLabel" | ||
defaultMessage="Add to dashboard" | ||
/> | ||
), | ||
onClick: closePopoverOnAction(() => { | ||
setCreateInDashboard(true); | ||
}), | ||
}, | ||
], | ||
}, | ||
]; | ||
|
||
const onSaveCallback: SaveModalDashboardProps['onSave'] = useCallback( | ||
({ dashboardId, newTitle, newDescription }) => { | ||
const stateTransfer = embeddable!.getStateTransfer(); | ||
const config = getDefaultEmbeddablePanelConfig(selectedJobId); | ||
|
||
const embeddableInput: Partial<SingleMetricViewerEmbeddableState> = { | ||
id: config.id, | ||
title: newTitle, | ||
description: newDescription, | ||
jobIds: [selectedJobId], | ||
selectedDetectorIndex, | ||
selectedEntities, | ||
}; | ||
|
||
const state = { | ||
input: embeddableInput, | ||
type: ANOMALY_SINGLE_METRIC_VIEWER_EMBEDDABLE_TYPE, | ||
}; | ||
|
||
const path = dashboardId === 'new' ? '#/create' : `#/view/${dashboardId}`; | ||
|
||
stateTransfer.navigateToWithEmbeddablePackage('dashboards', { | ||
state, | ||
path, | ||
}); | ||
}, | ||
[embeddable, selectedJobId, selectedDetectorIndex, selectedEntities] | ||
); | ||
|
||
return ( | ||
<> | ||
<EuiFlexGroup style={{ float: 'right' }} alignItems="center"> | ||
{showModelBoundsCheckbox && ( | ||
<EuiFlexItem grow={false}> | ||
<EuiCheckbox | ||
id="toggleModelBoundsCheckbox" | ||
label={i18n.translate('xpack.ml.timeSeriesExplorer.showModelBoundsLabel', { | ||
defaultMessage: 'show model bounds', | ||
})} | ||
checked={showModelBounds} | ||
onChange={onShowModelBoundsChange} | ||
/> | ||
</EuiFlexItem> | ||
)} | ||
|
||
{showAnnotationsCheckbox && ( | ||
<EuiFlexItem grow={false}> | ||
<EuiCheckbox | ||
id="toggleAnnotationsCheckbox" | ||
label={i18n.translate('xpack.ml.timeSeriesExplorer.annotationsLabel', { | ||
defaultMessage: 'annotations', | ||
})} | ||
checked={showAnnotations} | ||
onChange={onShowAnnotationsChange} | ||
/> | ||
</EuiFlexItem> | ||
)} | ||
|
||
{showForecastCheckbox && ( | ||
<EuiFlexItem grow={false}> | ||
<EuiCheckbox | ||
id="toggleShowForecastCheckbox" | ||
label={ | ||
<span data-test-subj={'mlForecastCheckbox'}> | ||
{i18n.translate('xpack.ml.timeSeriesExplorer.showForecastLabel', { | ||
defaultMessage: 'show forecast', | ||
})} | ||
</span> | ||
} | ||
checked={showForecast} | ||
onChange={onShowForecastChange} | ||
/> | ||
</EuiFlexItem> | ||
)} | ||
|
||
{canEditDashboards ? ( | ||
<EuiFlexItem grow={false} css={{ marginLeft: 'auto !important', alignSelf: 'baseline' }}> | ||
<EuiPopover | ||
button={ | ||
<EuiButtonIcon | ||
size="s" | ||
aria-label={i18n.translate('xpack.ml.explorer.swimlaneActions', { | ||
defaultMessage: 'Actions', | ||
})} | ||
color="text" | ||
iconType="boxesHorizontal" | ||
onClick={setIsMenuOpen.bind(null, !isMenuOpen)} | ||
data-test-subj="mlAnomalyTimelinePanelMenu" | ||
/> | ||
} | ||
isOpen={isMenuOpen} | ||
closePopover={setIsMenuOpen.bind(null, false)} | ||
panelPaddingSize="none" | ||
anchorPosition="downLeft" | ||
> | ||
<EuiContextMenu initialPanelId={0} panels={menuPanels} /> | ||
</EuiPopover> | ||
</EuiFlexItem> | ||
) : null} | ||
</EuiFlexGroup> | ||
{createInDashboard ? ( | ||
<SavedObjectSaveModalDashboard | ||
canSaveByReference={false} | ||
objectType={i18n.translate('xpack.ml.cases.singleMetricViewer.displayName', { | ||
defaultMessage: 'Single Metric Viewer', | ||
})} | ||
documentInfo={{ | ||
title: getDefaultSingleMetricViewerPanelTitle(selectedJobId), | ||
}} | ||
onClose={() => setCreateInDashboard(false)} | ||
onSave={onSaveCallback} | ||
/> | ||
) : null} | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters