mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[User Experience App] Improve initial loading time of the app (#136612)
* Use local storage * use local context * add error boundary * test * fix test
This commit is contained in:
parent
ad8ec922a6
commit
d16a4d8bd9
7 changed files with 108 additions and 61 deletions
|
@ -31,6 +31,7 @@ import {
|
|||
InspectorContextProvider,
|
||||
useBreadcrumbs,
|
||||
} from '@kbn/observability-plugin/public';
|
||||
import { CsmSharedContextProvider } from '../components/app/rum_dashboard/csm_shared_context';
|
||||
import {
|
||||
DASHBOARD_LABEL,
|
||||
RumHome,
|
||||
|
@ -125,6 +126,8 @@ export function UXAppRoot({
|
|||
const i18nCore = core.i18n;
|
||||
const plugins = { ...deps, maps };
|
||||
|
||||
createCallApmApi(core);
|
||||
|
||||
return (
|
||||
<RedirectAppLinks
|
||||
className={APP_WRAPPER_CLASS}
|
||||
|
@ -148,7 +151,9 @@ export function UXAppRoot({
|
|||
<InspectorContextProvider>
|
||||
<UrlParamsProvider>
|
||||
<EuiErrorBoundary>
|
||||
<UxApp />
|
||||
<CsmSharedContextProvider>
|
||||
<UxApp />
|
||||
</CsmSharedContextProvider>
|
||||
</EuiErrorBoundary>
|
||||
<UXActionMenu appMountParameters={appMountParameters} />
|
||||
</UrlParamsProvider>
|
||||
|
|
|
@ -45,6 +45,10 @@ export function PageLoadDistChart({ onPercentileChange, breakdown }: Props) {
|
|||
},
|
||||
];
|
||||
|
||||
if (!dataViewTitle) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ExploratoryViewEmbeddable
|
||||
customHeight={'300px'}
|
||||
|
|
|
@ -65,6 +65,10 @@ export function PageViewsChart({ breakdown }: Props) {
|
|||
});
|
||||
};
|
||||
|
||||
if (!dataViewTitle) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ExploratoryViewEmbeddable
|
||||
customHeight="300px"
|
||||
|
|
|
@ -5,18 +5,26 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { createContext, useMemo, useState } from 'react';
|
||||
import React, { createContext, useEffect, useMemo, useState } from 'react';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import {
|
||||
DataView,
|
||||
DataViewsPublicPluginStart,
|
||||
} from '@kbn/data-views-plugin/public';
|
||||
import { useDynamicDataViewFetcher } from '../../../../hooks/use_dynamic_data_view';
|
||||
import { useFetcher } from '../../../../hooks/use_fetcher';
|
||||
|
||||
interface SharedData {
|
||||
totalPageViews: number;
|
||||
}
|
||||
|
||||
interface Index {
|
||||
interface ContextType {
|
||||
dataView?: DataView;
|
||||
sharedData: SharedData;
|
||||
setSharedData: (data: SharedData) => void;
|
||||
}
|
||||
|
||||
const defaultContext: Index = {
|
||||
const defaultContext: ContextType = {
|
||||
sharedData: { totalPageViews: 0 },
|
||||
setSharedData: (d) => {
|
||||
throw new Error(
|
||||
|
@ -33,14 +41,33 @@ export function CsmSharedContextProvider({
|
|||
children: JSX.Element;
|
||||
}) {
|
||||
const [newData, setNewData] = useState<SharedData>({ totalPageViews: 0 });
|
||||
const [dataView, setDataView] = useState<DataView>();
|
||||
|
||||
const setSharedData = React.useCallback((data: SharedData) => {
|
||||
setNewData(data);
|
||||
}, []);
|
||||
|
||||
const {
|
||||
services: { dataViews },
|
||||
} = useKibana<{ dataViews: DataViewsPublicPluginStart }>();
|
||||
|
||||
const { dataView: uxDataView } = useDynamicDataViewFetcher();
|
||||
|
||||
const { data } = useFetcher<Promise<DataView | undefined>>(async () => {
|
||||
if (uxDataView?.title) {
|
||||
return dataViews.create({
|
||||
title: uxDataView?.title,
|
||||
});
|
||||
}
|
||||
}, [uxDataView?.title, dataViews]);
|
||||
|
||||
useEffect(() => {
|
||||
setDataView(data);
|
||||
}, [data]);
|
||||
|
||||
const value = useMemo(() => {
|
||||
return { sharedData: newData, setSharedData };
|
||||
}, [newData, setSharedData]);
|
||||
return { sharedData: newData, setSharedData, dataView };
|
||||
}, [newData, setSharedData, dataView]);
|
||||
|
||||
return <CsmSharedContext.Provider value={value} children={children} />;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
|
||||
import { useEsSearch } from '@kbn/observability-plugin/public';
|
||||
import useLocalStorage from 'react-use/lib/useLocalStorage';
|
||||
import { useEffect } from 'react';
|
||||
import {
|
||||
formatHasRumResult,
|
||||
hasRumDataQuery,
|
||||
|
@ -13,7 +15,10 @@ import {
|
|||
import { useDataView } from '../local_uifilters/use_data_view';
|
||||
|
||||
export function useHasRumData() {
|
||||
const [hasData, setHasData] = useLocalStorage('uxAppHasDataBoolean', false);
|
||||
|
||||
const { dataViewTitle } = useDataView();
|
||||
|
||||
const { data: response, loading } = useEsSearch(
|
||||
{
|
||||
index: dataViewTitle,
|
||||
|
@ -25,8 +30,17 @@ export function useHasRumData() {
|
|||
}
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (response) {
|
||||
const { hasData: hasDataN } = formatHasRumResult(response, dataViewTitle);
|
||||
setHasData(hasDataN);
|
||||
}
|
||||
}, [dataViewTitle, response, setHasData]);
|
||||
|
||||
if (!response) return { loading, hasData };
|
||||
|
||||
return {
|
||||
data: formatHasRumResult(response, dataViewTitle),
|
||||
hasData: formatHasRumResult(response, dataViewTitle).hasData,
|
||||
loading,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,26 +5,23 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { DataView } from '@kbn/data-views-plugin/common';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
|
||||
import { useFetcher } from '../../../../hooks/use_fetcher';
|
||||
import { useDynamicDataViewFetcher } from '../../../../hooks/use_dynamic_data_view';
|
||||
import { useContext, useEffect } from 'react';
|
||||
import useLocalStorage from 'react-use/lib/useLocalStorage';
|
||||
import { CsmSharedContext } from '../csm_shared_context';
|
||||
|
||||
export function useDataView() {
|
||||
const { dataView } = useDynamicDataViewFetcher();
|
||||
const { dataView } = useContext(CsmSharedContext);
|
||||
|
||||
const {
|
||||
services: { dataViews },
|
||||
} = useKibana<{ dataViews: DataViewsPublicPluginStart }>();
|
||||
const [dataViewTitle, setDataViewTitle] = useLocalStorage(
|
||||
'uxAppDataViewTitle',
|
||||
''
|
||||
);
|
||||
|
||||
const { data } = useFetcher<Promise<DataView | undefined>>(async () => {
|
||||
if (dataView?.title) {
|
||||
return dataViews.create({
|
||||
title: dataView?.title,
|
||||
});
|
||||
}
|
||||
}, [dataView?.title, dataViews]);
|
||||
const updatedDataViewTitle = dataView?.title;
|
||||
|
||||
return { dataViewTitle: dataView?.title, dataView: data };
|
||||
useEffect(() => {
|
||||
setDataViewTitle(updatedDataViewTitle);
|
||||
}, [setDataViewTitle, updatedDataViewTitle]);
|
||||
|
||||
return { dataViewTitle, dataView };
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import React, { Fragment } from 'react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiFlexGroup, EuiTitle, EuiFlexItem } from '@elastic/eui';
|
||||
import { KibanaPageTemplateProps } from '@kbn/shared-ux-components';
|
||||
import { CsmSharedContextProvider } from './csm_shared_context';
|
||||
import { WebApplicationSelect } from './panels/web_application_select';
|
||||
import { UserPercentile } from './user_percentile';
|
||||
import { useBreakpoints } from '../../../hooks/use_breakpoints';
|
||||
|
@ -29,47 +28,44 @@ export function RumHome() {
|
|||
|
||||
const PageTemplateComponent = observability.navigation.PageTemplate;
|
||||
|
||||
const { data: rumHasData, loading: isLoading } = useHasRumData();
|
||||
const { hasData, loading: isLoading } = useHasRumData();
|
||||
|
||||
const noDataConfig: KibanaPageTemplateProps['noDataConfig'] =
|
||||
!rumHasData?.hasData
|
||||
? {
|
||||
solution: i18n.translate('xpack.ux.overview.solutionName', {
|
||||
defaultMessage: 'Observability',
|
||||
}),
|
||||
action: {
|
||||
elasticAgent: {
|
||||
title: i18n.translate('xpack.ux.overview.beatsCard.title', {
|
||||
defaultMessage: 'Add RUM data',
|
||||
}),
|
||||
description: i18n.translate(
|
||||
'xpack.ux.overview.beatsCard.description',
|
||||
{
|
||||
defaultMessage:
|
||||
'Enable RUM with the APM agent to collect user experience data.',
|
||||
}
|
||||
),
|
||||
href: http.basePath.prepend(`/app/home#/tutorial/apm`),
|
||||
},
|
||||
const noDataConfig: KibanaPageTemplateProps['noDataConfig'] = !hasData
|
||||
? {
|
||||
solution: i18n.translate('xpack.ux.overview.solutionName', {
|
||||
defaultMessage: 'Observability',
|
||||
}),
|
||||
action: {
|
||||
elasticAgent: {
|
||||
title: i18n.translate('xpack.ux.overview.beatsCard.title', {
|
||||
defaultMessage: 'Add RUM data',
|
||||
}),
|
||||
description: i18n.translate(
|
||||
'xpack.ux.overview.beatsCard.description',
|
||||
{
|
||||
defaultMessage:
|
||||
'Enable RUM with the APM agent to collect user experience data.',
|
||||
}
|
||||
),
|
||||
href: http.basePath.prepend(`/app/home#/tutorial/apm`),
|
||||
},
|
||||
docsLink: docLinks.links.observability.guide,
|
||||
}
|
||||
: undefined;
|
||||
},
|
||||
docsLink: docLinks.links.observability.guide,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<CsmSharedContextProvider>
|
||||
<PageTemplateComponent
|
||||
noDataConfig={isLoading ? undefined : noDataConfig}
|
||||
pageHeader={{ children: <PageHeader /> }}
|
||||
isPageDataLoaded={isLoading === false}
|
||||
>
|
||||
{isLoading && <EmptyStateLoading />}
|
||||
<div style={{ visibility: isLoading ? 'hidden' : 'initial' }}>
|
||||
<RumOverview />
|
||||
</div>
|
||||
</PageTemplateComponent>
|
||||
</CsmSharedContextProvider>
|
||||
<PageTemplateComponent
|
||||
noDataConfig={isLoading ? undefined : noDataConfig}
|
||||
pageHeader={{ children: <PageHeader /> }}
|
||||
isPageDataLoaded={isLoading === false}
|
||||
>
|
||||
{isLoading && <EmptyStateLoading />}
|
||||
<div style={{ visibility: isLoading ? 'hidden' : 'initial' }}>
|
||||
<RumOverview />
|
||||
</div>
|
||||
</PageTemplateComponent>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue