Skip to content

Commit

Permalink
Make remaining route pages dynamic (React.lazy) to reduce app bundle.
Browse files Browse the repository at this point in the history
  • Loading branch information
clintandrewhall committed Apr 5, 2024
1 parent c24493c commit d328894
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 183 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* 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, { useMemo } from 'react';

import { i18n } from '@kbn/i18n';

import { dynamic } from '@kbn/shared-ux-utility';
import { basicResolvers } from '../../resolvers';
import { ML_PAGES } from '../../../../locator';
import type { NavigateToPath } from '../../../contexts/kibana';
import { useMlKibana } from '../../../contexts/kibana';

import type { MlRoute, PageProps } from '../../router';
import { createPath, PageLoader } from '../../router';
import { useRouteResolver } from '../../use_resolver';
import { mlJobService } from '../../../services/job_service';
import { getDateFormatTz } from '../../../explorer/explorer_utils';
import { getBreadcrumbWithUrlForApp } from '../../breadcrumbs';
import { MlAnnotationUpdatesContext } from '../../../contexts/ml/ml_annotation_updates_context';
import { AnnotationUpdatesService } from '../../../services/annotations_service';
import { AnomalyExplorerContextProvider } from '../../../explorer/anomaly_explorer_context';

const ExplorerUrlStateManager = dynamic(async () => ({
default: (await import('./state_manager')).ExplorerUrlStateManager,
}));

export const explorerRouteFactory = (
navigateToPath: NavigateToPath,
basePath: string
): MlRoute => ({
id: 'explorer',
path: createPath(ML_PAGES.ANOMALY_EXPLORER),
title: i18n.translate('xpack.ml.anomalyDetection.anomalyExplorer.docTitle', {
defaultMessage: 'Anomaly Explorer',
}),
render: (props, deps) => <PageWrapper {...props} deps={deps} />,
breadcrumbs: [
getBreadcrumbWithUrlForApp('ML_BREADCRUMB', navigateToPath, basePath),
getBreadcrumbWithUrlForApp('ANOMALY_DETECTION_BREADCRUMB', navigateToPath, basePath),
{
text: i18n.translate('xpack.ml.anomalyDetection.anomalyExplorerLabel', {
defaultMessage: 'Anomaly Explorer',
}),
},
],
enableDatePicker: true,
'data-test-subj': 'mlPageAnomalyExplorer',
});

const PageWrapper: FC<PageProps> = () => {
const {
services: {
mlServices: { mlApiServices },
},
} = useMlKibana();

const { context, results } = useRouteResolver('full', ['canGetJobs'], {
...basicResolvers(),
jobs: mlJobService.loadJobsWrapper,
jobsWithTimeRange: () => mlApiServices.jobs.jobsWithTimerange(getDateFormatTz()),
});

const annotationUpdatesService = useMemo(() => new AnnotationUpdatesService(), []);

return (
<PageLoader context={context}>
<MlAnnotationUpdatesContext.Provider value={annotationUpdatesService}>
<AnomalyExplorerContextProvider>
{results ? (
<ExplorerUrlStateManager jobsWithTimeRange={results.jobsWithTimeRange.jobs} />
) : null}
</AnomalyExplorerContextProvider>
</MlAnnotationUpdatesContext.Provider>
</PageLoader>
);
};
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 { explorerRouteFactory } from './explorer';
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import type { FC } from 'react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import useObservable from 'react-use/lib/useObservable';

import { i18n } from '@kbn/i18n';
Expand All @@ -17,93 +17,29 @@ import { useUrlState } from '@kbn/ml-url-state';
import { useTimefilter } from '@kbn/ml-date-picker';
import { ML_JOB_ID } from '@kbn/ml-anomaly-utils';
import { useTimeBuckets } from '@kbn/ml-time-buckets';
import { basicResolvers } from '../resolvers';
import { ML_PAGES } from '../../../locator';
import type { NavigateToPath } from '../../contexts/kibana';
import { useMlKibana } from '../../contexts/kibana';

import type { MlJobWithTimeRange } from '../../../../common/types/anomaly_detection_jobs';

import type { MlRoute, PageProps } from '../router';
import { createPath, PageLoader } from '../router';
import { useRefresh } from '../use_refresh';
import { useRouteResolver } from '../use_resolver';
import { Explorer } from '../../explorer';
import { mlJobService } from '../../services/job_service';
import { ml } from '../../services/ml_api_service';
import { useExplorerData } from '../../explorer/actions';
import { getDateFormatTz } from '../../explorer/explorer_utils';
import { useJobSelection } from '../../components/job_selector/use_job_selection';
import { useTableInterval } from '../../components/controls/select_interval';
import { useTableSeverity } from '../../components/controls/select_severity';
import { getBreadcrumbWithUrlForApp } from '../breadcrumbs';
import { MlAnnotationUpdatesContext } from '../../contexts/ml/ml_annotation_updates_context';
import { AnnotationUpdatesService } from '../../services/annotations_service';
import { MlPageHeader } from '../../components/page_header';
import { PageTitle } from '../../components/page_title';
import { AnomalyResultsViewSelector } from '../../components/anomaly_results_view_selector';
import { AnomalyDetectionEmptyState } from '../../jobs/jobs_list/components/anomaly_detection_empty_state';
import {
AnomalyExplorerContextProvider,
useAnomalyExplorerContext,
} from '../../explorer/anomaly_explorer_context';

export const explorerRouteFactory = (
navigateToPath: NavigateToPath,
basePath: string
): MlRoute => ({
id: 'explorer',
path: createPath(ML_PAGES.ANOMALY_EXPLORER),
title: i18n.translate('xpack.ml.anomalyDetection.anomalyExplorer.docTitle', {
defaultMessage: 'Anomaly Explorer',
}),
render: (props, deps) => <PageWrapper {...props} deps={deps} />,
breadcrumbs: [
getBreadcrumbWithUrlForApp('ML_BREADCRUMB', navigateToPath, basePath),
getBreadcrumbWithUrlForApp('ANOMALY_DETECTION_BREADCRUMB', navigateToPath, basePath),
{
text: i18n.translate('xpack.ml.anomalyDetection.anomalyExplorerLabel', {
defaultMessage: 'Anomaly Explorer',
}),
},
],
enableDatePicker: true,
'data-test-subj': 'mlPageAnomalyExplorer',
});

const PageWrapper: FC<PageProps> = () => {
const {
services: {
mlServices: { mlApiServices },
},
} = useMlKibana();

const { context, results } = useRouteResolver('full', ['canGetJobs'], {
...basicResolvers(),
jobs: mlJobService.loadJobsWrapper,
jobsWithTimeRange: () => mlApiServices.jobs.jobsWithTimerange(getDateFormatTz()),
});

const annotationUpdatesService = useMemo(() => new AnnotationUpdatesService(), []);

return (
<PageLoader context={context}>
<MlAnnotationUpdatesContext.Provider value={annotationUpdatesService}>
<AnomalyExplorerContextProvider>
{results ? (
<ExplorerUrlStateManager jobsWithTimeRange={results.jobsWithTimeRange.jobs} />
) : null}
</AnomalyExplorerContextProvider>
</MlAnnotationUpdatesContext.Provider>
</PageLoader>
);
};

interface ExplorerUrlStateManagerProps {
import { useMlKibana } from '../../../contexts/kibana';

import type { MlJobWithTimeRange } from '../../../../../common/types/anomaly_detection_jobs';
import { useRefresh } from '../../use_refresh';
import { Explorer } from '../../../explorer';
import { ml } from '../../../services/ml_api_service';
import { useExplorerData } from '../../../explorer/actions';
import { useJobSelection } from '../../../components/job_selector/use_job_selection';
import { useTableInterval } from '../../../components/controls/select_interval';
import { useTableSeverity } from '../../../components/controls/select_severity';
import { MlPageHeader } from '../../../components/page_header';
import { PageTitle } from '../../../components/page_title';
import { AnomalyResultsViewSelector } from '../../../components/anomaly_results_view_selector';
import { AnomalyDetectionEmptyState } from '../../../jobs/jobs_list/components/anomaly_detection_empty_state';
import { useAnomalyExplorerContext } from '../../../explorer/anomaly_explorer_context';

export interface ExplorerUrlStateManagerProps {
jobsWithTimeRange: MlJobWithTimeRange[];
}

const ExplorerUrlStateManager: FC<ExplorerUrlStateManagerProps> = ({ jobsWithTimeRange }) => {
export const ExplorerUrlStateManager: FC<ExplorerUrlStateManagerProps> = ({
jobsWithTimeRange,
}) => {
const {
services: { cases, presentationUtil, uiSettings },
} = useMlKibana();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,22 @@ import {
useRefreshIntervalUpdates,
useTimefilter,
} from '@kbn/ml-date-picker';
import { dynamic } from '@kbn/shared-ux-utility';
import { ML_PAGES } from '../../../locator';
import type { NavigateToPath } from '../../contexts/kibana';
import { DEFAULT_REFRESH_INTERVAL_MS } from '../../../../common/constants/jobs_list';
import type { MlRoute } from '../router';
import { createPath, PageLoader } from '../router';
import { useRouteResolver } from '../use_resolver';
import { JobsPage } from '../../jobs/jobs_list';
import { getBreadcrumbWithUrlForApp } from '../breadcrumbs';
import { AnnotationUpdatesService } from '../../services/annotations_service';
import { MlAnnotationUpdatesContext } from '../../contexts/ml/ml_annotation_updates_context';
import { basicResolvers } from '../resolvers';

const JobsPage = dynamic(async () => ({
default: (await import('../../jobs/jobs_list')).JobsPage,
}));

export const jobListRouteFactory = (navigateToPath: NavigateToPath, basePath: string): MlRoute => ({
id: 'anomaly_detection',
title: i18n.translate('xpack.ml.anomalyDetection.jobs.docTitle', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@
import type { FC } from 'react';
import React from 'react';
import { i18n } from '@kbn/i18n';
import { dynamic } from '@kbn/shared-ux-utility';
import { basicResolvers } from '../resolvers';
import { ML_PAGES } from '../../../locator';
import type { NavigateToPath } from '../../contexts/kibana';
import type { MlRoute } from '../router';
import { createPath, PageLoader } from '../router';
import { useRouteResolver } from '../use_resolver';
import { getBreadcrumbWithUrlForApp } from '../breadcrumbs';
import { MemoryUsagePage } from '../../memory_usage';

const MemoryUsagePage = dynamic(async () => ({
default: (await import('../../memory_usage')).MemoryUsagePage,
}));

export const nodesListRouteFactory = (
navigateToPath: NavigateToPath,
Expand Down
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 { timeSeriesExplorerRouteFactory } from './timeseriesexplorer';
Original file line number Diff line number Diff line change
Expand Up @@ -7,100 +7,37 @@

import { isEqual } from 'lodash';
import type { FC } from 'react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import usePrevious from 'react-use/lib/usePrevious';
import moment from 'moment';
import { i18n } from '@kbn/i18n';
import { useUrlState } from '@kbn/ml-url-state';
import { useTimefilter } from '@kbn/ml-date-picker';
import type { IUiSettingsClient } from '@kbn/core/public';
import type { TimeRangeBounds } from '@kbn/ml-time-buckets';
import { ML_PAGES } from '../../../locator';
import { getViewableDetectors } from '../../timeseriesexplorer/timeseriesexplorer_utils/get_viewable_detectors';
import type { NavigateToPath } from '../../contexts/kibana';
import {
useMlApiContext,
useMlKibana,
useNotifications,
useUiSettings,
} from '../../contexts/kibana';
import type { MlJobWithTimeRange } from '../../../../common/types/anomaly_detection_jobs';
import { isTimeSeriesViewJob } from '../../../../common/util/job_utils';
import { TimeSeriesExplorer } from '../../timeseriesexplorer';
import { getDateFormatTz } from '../../explorer/explorer_utils';
import { mlJobService } from '../../services/job_service';
import { useForecastService } from '../../services/forecast_service';
import { useTimeSeriesExplorerService } from '../../util/time_series_explorer_service';
import { APP_STATE_ACTION } from '../../timeseriesexplorer/timeseriesexplorer_constants';
import { validateJobSelection } from '../../timeseriesexplorer/timeseriesexplorer_utils';
import { TimeSeriesExplorerPage } from '../../timeseriesexplorer/timeseriesexplorer_page';
import { TimeseriesexplorerNoJobsFound } from '../../timeseriesexplorer/components/timeseriesexplorer_no_jobs_found';
import { useTableInterval } from '../../components/controls/select_interval';
import { useTableSeverity } from '../../components/controls/select_severity';
import type { MlRoute, PageProps } from '../router';
import { createPath, PageLoader } from '../router';
import { useRouteResolver } from '../use_resolver';
import { getBreadcrumbWithUrlForApp } from '../breadcrumbs';
import { useToastNotificationService } from '../../services/toast_notification_service';
import { AnnotationUpdatesService } from '../../services/annotations_service';
import { MlAnnotationUpdatesContext } from '../../contexts/ml/ml_annotation_updates_context';
import { useTimeSeriesExplorerUrlState } from '../../timeseriesexplorer/hooks/use_timeseriesexplorer_url_state';
import type { TimeSeriesExplorerAppState } from '../../../../common/types/locator';
import { useJobSelectionFlyout } from '../../contexts/ml/use_job_selection_flyout';
import { useRefresh } from '../use_refresh';
import { TimeseriesexplorerNoChartData } from '../../timeseriesexplorer/components/timeseriesexplorer_no_chart_data';
import { basicResolvers } from '../resolvers';

export const timeSeriesExplorerRouteFactory = (
navigateToPath: NavigateToPath,
basePath: string
): MlRoute => ({
id: 'timeseriesexplorer',
path: createPath(ML_PAGES.SINGLE_METRIC_VIEWER),
title: i18n.translate('xpack.ml.anomalyDetection.singleMetricViewerLabel', {
defaultMessage: 'Single Metric Viewer',
}),
render: (props, deps) => <PageWrapper {...props} deps={deps} />,
breadcrumbs: [
getBreadcrumbWithUrlForApp('ML_BREADCRUMB', navigateToPath, basePath),
getBreadcrumbWithUrlForApp('ANOMALY_DETECTION_BREADCRUMB', navigateToPath, basePath),
{
text: i18n.translate('xpack.ml.anomalyDetection.singleMetricViewerLabel', {
defaultMessage: 'Single Metric Viewer',
}),
},
],
enableDatePicker: true,
});

const PageWrapper: FC<PageProps> = ({ deps }) => {
const mlApi = useMlApiContext();
const uiSettings = useUiSettings();
const { context, results } = useRouteResolver('full', ['canGetJobs'], {
...basicResolvers(),
jobs: mlJobService.loadJobsWrapper,
jobsWithTimeRange: () => mlApi.jobs.jobsWithTimerange(getDateFormatTz()),
});

const annotationUpdatesService = useMemo(() => new AnnotationUpdatesService(), []);

return (
<PageLoader context={context}>
<MlAnnotationUpdatesContext.Provider value={annotationUpdatesService}>
{results ? (
<TimeSeriesExplorerUrlStateManager
config={uiSettings}
jobsWithTimeRange={results.jobsWithTimeRange.jobs}
/>
) : null}
</MlAnnotationUpdatesContext.Provider>
</PageLoader>
);
};
import { getViewableDetectors } from '../../../timeseriesexplorer/timeseriesexplorer_utils/get_viewable_detectors';
import { useMlKibana, useNotifications } from '../../../contexts/kibana';
import type { MlJobWithTimeRange } from '../../../../../common/types/anomaly_detection_jobs';
import { isTimeSeriesViewJob } from '../../../../../common/util/job_utils';
import { TimeSeriesExplorer } from '../../../timeseriesexplorer';
import { mlJobService } from '../../../services/job_service';
import { useForecastService } from '../../../services/forecast_service';
import { useTimeSeriesExplorerService } from '../../../util/time_series_explorer_service';
import { APP_STATE_ACTION } from '../../../timeseriesexplorer/timeseriesexplorer_constants';
import { validateJobSelection } from '../../../timeseriesexplorer/timeseriesexplorer_utils';
import { TimeSeriesExplorerPage } from '../../../timeseriesexplorer/timeseriesexplorer_page';
import { TimeseriesexplorerNoJobsFound } from '../../../timeseriesexplorer/components/timeseriesexplorer_no_jobs_found';
import { useTableInterval } from '../../../components/controls/select_interval';
import { useTableSeverity } from '../../../components/controls/select_severity';
import { useToastNotificationService } from '../../../services/toast_notification_service';
import { useTimeSeriesExplorerUrlState } from '../../../timeseriesexplorer/hooks/use_timeseriesexplorer_url_state';
import type { TimeSeriesExplorerAppState } from '../../../../../common/types/locator';
import { useJobSelectionFlyout } from '../../../contexts/ml/use_job_selection_flyout';
import { useRefresh } from '../../use_refresh';
import { TimeseriesexplorerNoChartData } from '../../../timeseriesexplorer/components/timeseriesexplorer_no_chart_data';

type AppStateZoom = Exclude<TimeSeriesExplorerAppState['mlTimeSeriesExplorer'], undefined>['zoom'];

interface TimeSeriesExplorerUrlStateManager {
export interface TimeSeriesExplorerUrlStateManager {
config: IUiSettingsClient;
jobsWithTimeRange: MlJobWithTimeRange[];
}
Expand Down
Loading

0 comments on commit d328894

Please sign in to comment.