diff --git a/x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart_component.tsx b/x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart_component.tsx index d7d1c84cf9f102..034450735cb09a 100644 --- a/x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart_component.tsx +++ b/x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart_component.tsx @@ -18,6 +18,7 @@ import { EuiLoadingChart } from '@elastic/eui'; import { EMBEDDABLE_CHANGE_POINT_CHART_TYPE } from '../../common/constants'; import type { AiopsPluginStartDeps } from '../types'; import type { EmbeddableChangePointChartInput } from './embeddable_change_point_chart'; +import type { ChangePointAnnotation } from '../components/change_point_detection/change_point_detection_context'; export interface EmbeddableChangePointChartProps { dataViewId: string; @@ -27,6 +28,18 @@ export interface EmbeddableChangePointChartProps { splitField?: string; partitions?: string[]; maxSeriesToPlot?: number; + /** + * Component to render if there are no change points found + */ + emptyState?: React.ReactElement; + /** + * Outputs the most recent change point data + */ + onChange?: (changePointData: ChangePointAnnotation[]) => void; + /** + * Last reload request time, can be used for manual reload + */ + lastReloadRequestTime?: number; } export function getEmbeddableChangePointChart(core: CoreStart, plugins: AiopsPluginStartDeps) { diff --git a/x-pack/plugins/aiops/public/embeddable/embeddable_chart_component_wrapper.tsx b/x-pack/plugins/aiops/public/embeddable/embeddable_chart_component_wrapper.tsx index 54ed702eadf63e..2bace3b693853d 100644 --- a/x-pack/plugins/aiops/public/embeddable/embeddable_chart_component_wrapper.tsx +++ b/x-pack/plugins/aiops/public/embeddable/embeddable_chart_component_wrapper.tsx @@ -5,8 +5,9 @@ * 2.0. */ -import { type Observable } from 'rxjs'; -import React, { FC, useEffect, useMemo } from 'react'; +import { BehaviorSubject, type Observable, combineLatest } from 'rxjs'; +import { map, distinctUntilChanged } from 'rxjs/operators'; +import React, { FC, useEffect, useMemo, useState } from 'react'; import { useTimefilter } from '@kbn/ml-date-picker'; import { css } from '@emotion/react'; import useObservable from 'react-use/lib/useObservable'; @@ -55,8 +56,31 @@ export const EmbeddableInputTracker: FC = ({ }) => { const input = useObservable(input$, initialInput); + const [manualReload$] = useState>( + new BehaviorSubject(initialInput.lastReloadRequestTime ?? Date.now()) + ); + + useEffect( + function updateManualReloadSubject() { + if ( + input.lastReloadRequestTime === initialInput.lastReloadRequestTime || + !input.lastReloadRequestTime + ) + return; + manualReload$.next(input.lastReloadRequestTime); + }, + [input.lastReloadRequestTime, initialInput.lastReloadRequestTime, manualReload$] + ); + + const resultObservable$ = useMemo>(() => { + return combineLatest([reload$, manualReload$]).pipe( + map(([reload, manualReload]) => Math.max(reload, manualReload)), + distinctUntilChanged() + ); + }, [manualReload$, reload$]); + return ( - + = ({ onLoading={onLoading} onRenderComplete={onRenderComplete} onError={onError} + onChange={input.onChange} + emptyState={input.emptyState} /> @@ -103,6 +129,8 @@ export const ChartGridEmbeddableWrapper: FC< onError, onLoading, onRenderComplete, + onChange, + emptyState, }) => { const { filters, query, timeRange } = useFilerQueryUpdates(); @@ -189,8 +217,12 @@ export const ChartGridEmbeddableWrapper: FC< resultChangePoints = resultChangePoints.slice(0, maxSeriesToPlot); } + if (onChange) { + onChange(resultChangePoints); + } + return resultChangePoints; - }, [results, maxSeriesToPlot]); + }, [results, maxSeriesToPlot, onChange]); return (
+ ) : emptyState ? ( + emptyState ) : ( )} diff --git a/x-pack/plugins/aiops/public/types.ts b/x-pack/plugins/aiops/public/types.ts index 9c28951c25c991..e0f86c68864bd3 100755 --- a/x-pack/plugins/aiops/public/types.ts +++ b/x-pack/plugins/aiops/public/types.ts @@ -17,8 +17,8 @@ import type { UiActionsStart, UiActionsSetup } from '@kbn/ui-actions-plugin/publ import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import type { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public'; import type { CasesUiSetup } from '@kbn/cases-plugin/public'; -import { LicensingPluginSetup } from '@kbn/licensing-plugin/public'; -import type { EmbeddableChangePointChartProps } from './embeddable'; +import type { LicensingPluginSetup } from '@kbn/licensing-plugin/public'; +import type { EmbeddableChangePointChartInput } from './embeddable/embeddable_change_point_chart'; export interface AiopsPluginSetupDeps { embeddable: EmbeddableSetup; @@ -44,5 +44,5 @@ export interface AiopsPluginStartDeps { export type AiopsPluginSetup = void; export interface AiopsPluginStart { - EmbeddableChangePointChart: React.ComponentType; + EmbeddableChangePointChart: React.ComponentType; } diff --git a/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section.tsx b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section.tsx index ecb31f4a49b4b7..cf728d73aef4e0 100644 --- a/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section.tsx +++ b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section.tsx @@ -213,19 +213,19 @@ export default function AlertDetailsAppSection({ {ruleParams.criteria.map((criterion, criterionIndex) => - criterion.metrics?.map( - (metric, metricIndex) => - dataView && - dataView.id && ( - - ) - ) + criterion.metrics?.map((metric, metricIndex) => { + const id = `embeddableChart-criterion${criterionIndex}-metric${metricIndex}`; + return dataView?.id ? ( + + ) : null; + }) )}