fix to update panel component when data view changes

This commit is contained in:
Walter Rafelsberger 2024-10-10 14:37:30 +02:00
parent 75ca4cac37
commit 2b58567771
3 changed files with 61 additions and 33 deletions

View file

@ -28,7 +28,7 @@ import { cloneDeep } from 'lodash';
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import useObservable from 'react-use/lib/useObservable'; import useObservable from 'react-use/lib/useObservable';
import { BehaviorSubject, distinctUntilChanged, map, skipWhile } from 'rxjs'; import { BehaviorSubject, distinctUntilChanged, map, skipWhile } from 'rxjs';
import { getLogRateAnalysisComponent } from '../../shared_components'; import { getLogRateAnalysisEmbeddableWrapperComponent } from '../../shared_components';
import type { AiopsPluginStart, AiopsPluginStartDeps } from '../../types'; import type { AiopsPluginStart, AiopsPluginStartDeps } from '../../types';
import { initializeLogRateAnalysisControls } from './initialize_log_rate_analysis_analysis_controls'; import { initializeLogRateAnalysisControls } from './initialize_log_rate_analysis_analysis_controls';
import type { import type {
@ -162,7 +162,10 @@ export const getLogRateAnalysisEmbeddableFactory = (
} }
); );
const LogRateAnalysisComponent = getLogRateAnalysisComponent(coreStart, pluginStart); const LogRateAnalysisEmbeddableWrapper = getLogRateAnalysisEmbeddableWrapperComponent(
coreStart,
pluginStart
);
const onLoading = (v: boolean) => dataLoading.next(v); const onLoading = (v: boolean) => dataLoading.next(v);
const onRenderComplete = () => dataLoading.next(false); const onRenderComplete = () => dataLoading.next(false);
@ -203,7 +206,7 @@ export const getLogRateAnalysisEmbeddableFactory = (
: undefined; : undefined;
return ( return (
<LogRateAnalysisComponent <LogRateAnalysisEmbeddableWrapper
dataViewId={dataViewId} dataViewId={dataViewId}
timeRange={timeRange} timeRange={timeRange}
onLoading={onLoading} onLoading={onLoading}

View file

@ -11,7 +11,7 @@ import type { CoreStart } from '@kbn/core-lifecycle-browser';
import type { AiopsPluginStartDeps } from '../types'; import type { AiopsPluginStartDeps } from '../types';
import type { ChangePointDetectionSharedComponent } from './change_point_detection'; import type { ChangePointDetectionSharedComponent } from './change_point_detection';
import type { PatternAnalysisSharedComponent } from './pattern_analysis'; import type { PatternAnalysisSharedComponent } from './pattern_analysis';
import type { LogRateAnalysisSharedComponent } from './log_rate_analysis'; import type { LogRateAnalysisEmbeddableWrapper } from './log_rate_analysis_embeddable_wrapper';
const ChangePointDetectionLazy = dynamic(async () => import('./change_point_detection')); const ChangePointDetectionLazy = dynamic(async () => import('./change_point_detection'));
@ -39,15 +39,23 @@ export const getPatternAnalysisComponent = (
export type { PatternAnalysisSharedComponent } from './pattern_analysis'; export type { PatternAnalysisSharedComponent } from './pattern_analysis';
const LogRateAnalysisLazy = dynamic(async () => import('./log_rate_analysis')); const LogRateAnalysisEmbeddableWrapperLazy = dynamic(
async () => import('./log_rate_analysis_embeddable_wrapper')
);
export const getLogRateAnalysisComponent = ( export const getLogRateAnalysisEmbeddableWrapperComponent = (
coreStart: CoreStart, coreStart: CoreStart,
pluginStart: AiopsPluginStartDeps pluginStart: AiopsPluginStartDeps
): LogRateAnalysisSharedComponent => { ): LogRateAnalysisEmbeddableWrapper => {
return React.memo((props) => { return React.memo((props) => {
return <LogRateAnalysisLazy coreStart={coreStart} pluginStart={pluginStart} {...props} />; return (
<LogRateAnalysisEmbeddableWrapperLazy
coreStart={coreStart}
pluginStart={pluginStart}
{...props}
/>
);
}); });
}; };
export type { LogRateAnalysisSharedComponent } from './log_rate_analysis'; export type { LogRateAnalysisEmbeddableWrapper } from './log_rate_analysis_embeddable_wrapper';

View file

@ -7,6 +7,7 @@
import { pick } from 'lodash'; import { pick } from 'lodash';
import React, { useEffect, useMemo, useState, type FC } from 'react'; import React, { useEffect, useMemo, useState, type FC } from 'react';
import usePrevious from 'react-use/lib/usePrevious';
import type { Observable } from 'rxjs'; import type { Observable } from 'rxjs';
import { BehaviorSubject, combineLatest, distinctUntilChanged, map } from 'rxjs'; import { BehaviorSubject, combineLatest, distinctUntilChanged, map } from 'rxjs';
import { createBrowserHistory } from 'history'; import { createBrowserHistory } from 'history';
@ -34,14 +35,14 @@ import { LogRateAnalysisContent } from '../components/log_rate_analysis/log_rate
/** /**
* Only used to initialize internally * Only used to initialize internally
*/ */
export type LogRateAnalysisPropsWithDeps = LogRateAnalysisProps & { export type LogRateAnalysisPropsWithDeps = LogRateAnalysisEmbeddableWrapperProps & {
coreStart: CoreStart; coreStart: CoreStart;
pluginStart: AiopsPluginStartDeps; pluginStart: AiopsPluginStartDeps;
}; };
export type LogRateAnalysisSharedComponent = FC<LogRateAnalysisProps>; export type LogRateAnalysisEmbeddableWrapper = FC<LogRateAnalysisEmbeddableWrapperProps>;
export interface LogRateAnalysisProps { export interface LogRateAnalysisEmbeddableWrapperProps {
dataViewId: string; dataViewId: string;
timeRange: TimeRange; timeRange: TimeRange;
/** /**
@ -63,7 +64,7 @@ export interface LogRateAnalysisProps {
onError: (error: Error) => void; onError: (error: Error) => void;
} }
const LogRateAnalysisWrapper: FC<LogRateAnalysisPropsWithDeps> = ({ const LogRateAnalysisEmbeddableWrapperWithDeps: FC<LogRateAnalysisPropsWithDeps> = ({
// Component dependencies // Component dependencies
coreStart, coreStart,
pluginStart, pluginStart,
@ -132,6 +133,20 @@ const LogRateAnalysisWrapper: FC<LogRateAnalysisPropsWithDeps> = ({
} }
}, [timeRange]); }, [timeRange]);
// We use the following pattern to track changes of dataViewId, and if there's
// a change, we unmount and remount the complete inner component. This makes
// sure the component is reinitialized correctly when the options of the
// dashboard panel are used to change the data view. This is a bit of a
// workaround since originally log rate analysis was developed as a standalone
// page with the expectation that the data view is set once and never changes.
const prevDataViewId = usePrevious(dataViewId);
const [_, setRerenderFlag] = useState(false);
useEffect(() => {
if (prevDataViewId && prevDataViewId !== dataViewId) {
setRerenderFlag((prev) => !prev);
}
}, [dataViewId, prevDataViewId]);
// TODO: Remove data-shared-item as part of https://github.com/elastic/kibana/issues/179376> // TODO: Remove data-shared-item as part of https://github.com/elastic/kibana/issues/179376>
return ( return (
<div <div
@ -144,28 +159,30 @@ const LogRateAnalysisWrapper: FC<LogRateAnalysisPropsWithDeps> = ({
padding: '10px', padding: '10px',
}} }}
> >
<Router history={history}> {prevDataViewId === dataViewId && (
<ReloadContextProvider reload$={resultObservable$}> <Router history={history}>
<AiopsAppContext.Provider value={aiopsAppContextValue}> <ReloadContextProvider reload$={resultObservable$}>
<UrlStateProvider> <AiopsAppContext.Provider value={aiopsAppContextValue}>
<DataSourceContextProvider <UrlStateProvider>
dataViews={pluginStart.data.dataViews} <DataSourceContextProvider
dataViewId={dataViewId} dataViews={pluginStart.data.dataViews}
> dataViewId={dataViewId}
<LogRateAnalysisReduxProvider> >
<DatePickerContextProvider {...datePickerDeps}> <LogRateAnalysisReduxProvider>
<LogRateAnalysisDocumentCountChartData timeRange={timeRangeParsed} /> <DatePickerContextProvider {...datePickerDeps}>
<LogRateAnalysisContent /> <LogRateAnalysisDocumentCountChartData timeRange={timeRangeParsed} />
</DatePickerContextProvider> <LogRateAnalysisContent />
</LogRateAnalysisReduxProvider> </DatePickerContextProvider>
</DataSourceContextProvider> </LogRateAnalysisReduxProvider>
</UrlStateProvider> </DataSourceContextProvider>
</AiopsAppContext.Provider> </UrlStateProvider>
</ReloadContextProvider> </AiopsAppContext.Provider>
</Router> </ReloadContextProvider>
</Router>
)}
</div> </div>
); );
}; };
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
export default LogRateAnalysisWrapper; export default LogRateAnalysisEmbeddableWrapperWithDeps;