diff --git a/public/pages/Detectors/components/DetectorBasicDetailsView/DetectorBasicDetailsView.tsx b/public/pages/Detectors/components/DetectorBasicDetailsView/DetectorBasicDetailsView.tsx index dbc1df966..dd8c84c36 100644 --- a/public/pages/Detectors/components/DetectorBasicDetailsView/DetectorBasicDetailsView.tsx +++ b/public/pages/Detectors/components/DetectorBasicDetailsView/DetectorBasicDetailsView.tsx @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { EuiButton, EuiSpacer, EuiLink } from '@elastic/eui'; +import { EuiButton, EuiSpacer, EuiLink, EuiIcon } from '@elastic/eui'; import React from 'react'; import { ContentPanel } from '../../../../components/ContentPanel'; import { createTextDetailsGroup, parseSchedule } from '../../../../utils/helpers'; @@ -39,18 +39,18 @@ export const DetectorBasicDetailsView: React.FC = { label: 'Detector name', content: name }, { label: 'Log type', content: detector_type.toLowerCase() }, { label: 'Data source', content: inputs[0].detector_input.indices[0] }, - ]; - - if (dashboardId) { - firstTextDetailsGroupEntries.push({ + { label: 'Detector dashboard', - content: ( - window.open(`dashboards#/view/${dashboardId}`, '_self')}> - {} + content: (dashboardId ? ( + window.open(`dashboards#/view/${dashboardId}`, '_blank')}> + {`${name} summary`} + - ) as any, - }); - } + ) : ( + 'Not available for this log type' + )) as any, + }, + ]; return ( +
+
+
+ +
+
+
+ Not available for this log type +
+
+
+
+
+
+
+ +
+
+
+ Not available for this log type +
+
+
+
{ detectorService: DetectorsService; notifications: NotificationsStart; + savedObjectsService: ISavedObjectsService; } export interface DetectorDetailsState { @@ -156,13 +163,39 @@ export class DetectorDetails extends React.Component { - if (savedObject && savedObject.ok) this.setState({ dashboardId: savedObject.response.id }); - }); } async componentDidMount() { this.getDetector(); + + const pendingDashboardCreationPromise = pendingDashboardCreations[this.state.detectorId]; + if (pendingDashboardCreationPromise) { + pendingDashboardCreationPromise.then((savedObject) => { + if (savedObject && savedObject.ok) { + this.setState({ dashboardId: savedObject.response.id }); + this.getTabs(); + } + delete pendingDashboardCreations[this.state.detectorId]; + }); + } else { + const dashboards = await this.props.savedObjectsService.getDashboards(); + let detectorDashboardId; + dashboards.some((dashboard) => { + if ( + dashboard.references.findIndex((reference) => reference.id === this.state.detectorId) > -1 + ) { + detectorDashboardId = dashboard.id; + return true; + } + + return false; + }); + + if (detectorDashboardId) { + this.setState({ dashboardId: detectorDashboardId }); + this.getTabs(); + } + } } getDetector = async () => { @@ -253,15 +286,8 @@ export class DetectorDetails extends React.Component ( - {action.name} - )), { - this.closeActionsPopover(); - this.onDelete(); - }} - data-test-subj={'editButton'} + onClick={this.onViewAlertsClick} + data-test-subj={'viewAlertsButton'} > - Delete + View Alerts , + + View Findings + , + <> + {this.state.dashboardId ? ( + + window.open(`dashboards#/view/${this.state.dashboardId}`, '_blank') + } + data-test-subj={'viewDashboard'} + > + View detector dashboard + + ) : null} + , + , {`${this.detectorHit._source.enabled ? 'Stop' : 'Start'} detector`} , + { + this.closeActionsPopover(); + this.onDelete(); + }} + data-test-subj={'editButton'} + > + Delete + , ]} /> , diff --git a/public/pages/Detectors/containers/Detector/__snapshots__/DetectorDetails.test.tsx.snap b/public/pages/Detectors/containers/Detector/__snapshots__/DetectorDetails.test.tsx.snap index 31eef5401..6eb956b33 100644 --- a/public/pages/Detectors/containers/Detector/__snapshots__/DetectorDetails.test.tsx.snap +++ b/public/pages/Detectors/containers/Detector/__snapshots__/DetectorDetails.test.tsx.snap @@ -320,112 +320,6 @@ exports[` spec renders the component 1`] = ` -
- - - - - -
-
- -
- - - - - -
-
-
spec renders the component 1`] = `
+ +
+ + Detector dashboard + + } + labelType="label" + > +
+
+ + + +
+
+ +
+ Not available for this log type +
+
+
+
+
+
+
spec renders the component 1`] = ` + +
+ + Detector dashboard + + } + labelType="label" + > +
+
+ + + +
+
+ +
+ Not available for this log type +
+
+
+
+
+
+
View surrounding documents + diff --git a/public/pages/Main/Main.tsx b/public/pages/Main/Main.tsx index 734240fe5..6029454de 100644 --- a/public/pages/Main/Main.tsx +++ b/public/pages/Main/Main.tsx @@ -363,6 +363,7 @@ export default class Main extends Component { render={(props: RouteComponentProps<{}, any, any>) => ( diff --git a/public/services/SavedObjectService.ts b/public/services/SavedObjectService.ts index f414aa62b..efa7d7dd2 100644 --- a/public/services/SavedObjectService.ts +++ b/public/services/SavedObjectService.ts @@ -3,7 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { SavedObjectsClientContract, SimpleSavedObject } from 'opensearch-dashboards/public'; +import { + SavedObjectReference, + SavedObjectsClientContract, + SimpleSavedObject, +} from 'opensearch-dashboards/public'; import { ISavedObjectsService, ServerResponse } from '../../types'; import { getSavedObjectConfigs } from '../store/savedObjectsConfig'; import { logTypesWithDashboards } from '../utils/constants'; @@ -90,4 +94,18 @@ export default class SavedObjectService implements ISavedObjectsService { return Promise.reject('Log type not yet supported'); } + + public getDashboards = async (): Promise< + SimpleSavedObject<{ references: SavedObjectReference[]; id?: string }>[] + > => { + const dashboards = await this.savedObjectsClient + .find<{ references: SavedObjectReference[]; id?: string }>({ + type: 'dashboard', + fields: ['references', 'id'], + perPage: 10000, + }) + .then((response) => response.savedObjects); + + return Promise.resolve(dashboards); + }; } diff --git a/types/services/ISavedObjectsService.ts b/types/services/ISavedObjectsService.ts index 357a5ab1e..bc0d27a53 100644 --- a/types/services/ISavedObjectsService.ts +++ b/types/services/ISavedObjectsService.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { SimpleSavedObject } from 'opensearch-dashboards/public'; +import { SavedObjectReference, SimpleSavedObject } from 'opensearch-dashboards/public'; import { ServerResponse } from './ServerResponse'; export interface ISavedObjectsService { @@ -12,4 +12,7 @@ export interface ISavedObjectsService { logType: string, detectorId: string ): Promise>; + getDashboards(): Promise< + SimpleSavedObject<{ references: SavedObjectReference[]; id?: string }>[] + >; }