Convert components to use React.lazy for bundling (#96185)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Clint Andrew Hall 2021-04-06 10:31:18 -05:00 committed by GitHub
parent 2adc060044
commit b066e9714d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 146 additions and 69 deletions

View file

@ -23,7 +23,7 @@ import {
EuiOutsideClickDetector,
} from '@elastic/eui';
import { DashboardCopyToCapabilities } from './copy_to_dashboard_action';
import { DashboardPicker } from '../../services/presentation_util';
import { LazyDashboardPicker, withSuspense } from '../../services/presentation_util';
import { dashboardCopyToDashboardAction } from '../../dashboard_strings';
import { EmbeddableStateTransfer, IEmbeddable } from '../../services/embeddable';
import { createDashboardEditUrl, DashboardConstants } from '../..';
@ -37,6 +37,8 @@ interface CopyToDashboardModalProps {
closeModal: () => void;
}
const DashboardPicker = withSuspense(LazyDashboardPicker);
export function CopyToDashboardModal({
PresentationUtilContext,
stateTransfer,

View file

@ -6,4 +6,8 @@
* Side Public License, v 1.
*/
export { PresentationUtilPluginStart, DashboardPicker } from '../../../presentation_util/public';
export {
PresentationUtilPluginStart,
LazyDashboardPicker,
withSuspense,
} from '../../../presentation_util/public';

View file

@ -99,3 +99,7 @@ export function DashboardPicker(props: DashboardPickerProps) {
/>
);
}
// required for dynamic import using React.lazy()
// eslint-disable-next-line import/no-default-export
export default DashboardPicker;

View file

@ -0,0 +1,32 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React, { Suspense, ComponentType, ReactElement } from 'react';
import { EuiLoadingSpinner, EuiErrorBoundary } from '@elastic/eui';
/**
* A HOC which supplies React.Suspense with a fallback component, and a `EuiErrorBoundary` to contain errors.
* @param Component A component deferred by `React.lazy`
* @param fallback A fallback component to render while things load; default is `EuiLoadingSpinner`
*/
export const withSuspense = <P extends {}>(
Component: ComponentType<P>,
fallback: ReactElement | null = <EuiLoadingSpinner />
) => (props: P) => (
<EuiErrorBoundary>
<Suspense fallback={fallback}>
<Component {...props} />
</Suspense>
</EuiErrorBoundary>
);
export const LazyDashboardPicker = React.lazy(() => import('./dashboard_picker'));
export const LazySavedObjectSaveModalDashboard = React.lazy(
() => import('./saved_object_save_modal_dashboard')
);

View file

@ -10,32 +10,15 @@ import React, { useState } from 'react';
import { i18n } from '@kbn/i18n';
import {
OnSaveProps,
SaveModalState,
SavedObjectSaveModal,
} from '../../../../plugins/saved_objects/public';
import { OnSaveProps, SavedObjectSaveModal } from '../../../../plugins/saved_objects/public';
import './saved_object_save_modal_dashboard.scss';
import { pluginServices } from '../services';
import { SaveModalDashboardProps } from './types';
import { SaveModalDashboardSelector } from './saved_object_save_modal_dashboard_selector';
interface SaveModalDocumentInfo {
id?: string;
title: string;
description?: string;
}
import './saved_object_save_modal_dashboard.scss';
export interface SaveModalDashboardProps {
documentInfo: SaveModalDocumentInfo;
canSaveByReference: boolean;
objectType: string;
onClose: () => void;
onSave: (props: OnSaveProps & { dashboardId: string | null; addToLibrary: boolean }) => void;
tagOptions?: React.ReactNode | ((state: SaveModalState) => React.ReactNode);
}
export function SavedObjectSaveModalDashboard(props: SaveModalDashboardProps) {
function SavedObjectSaveModalDashboard(props: SaveModalDashboardProps) {
const { documentInfo, tagOptions, objectType, onClose, canSaveByReference } = props;
const { id: documentId } = documentInfo;
const initialCopyOnSave = !Boolean(documentId);
@ -136,3 +119,7 @@ export function SavedObjectSaveModalDashboard(props: SaveModalDashboardProps) {
/>
);
}
// required for dynamic import using React.lazy()
// eslint-disable-next-line import/no-default-export
export default SavedObjectSaveModalDashboard;

View file

@ -22,7 +22,7 @@ import {
EuiCheckbox,
} from '@elastic/eui';
import { DashboardPicker, DashboardPickerProps } from './dashboard_picker';
import DashboardPicker, { DashboardPickerProps } from './dashboard_picker';
import './saved_object_save_modal_dashboard.scss';

View file

@ -0,0 +1,24 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { OnSaveProps, SaveModalState } from '../../../../plugins/saved_objects/public';
interface SaveModalDocumentInfo {
id?: string;
title: string;
description?: string;
}
export interface SaveModalDashboardProps {
documentInfo: SaveModalDocumentInfo;
canSaveByReference: boolean;
objectType: string;
onClose: () => void;
onSave: (props: OnSaveProps & { dashboardId: string | null; addToLibrary: boolean }) => void;
tagOptions?: React.ReactNode | ((state: SaveModalState) => React.ReactNode);
}

View file

@ -8,14 +8,12 @@
import { PresentationUtilPlugin } from './plugin';
export {
SavedObjectSaveModalDashboard,
SaveModalDashboardProps,
} from './components/saved_object_save_modal_dashboard';
export { LazyDashboardPicker, LazySavedObjectSaveModalDashboard, withSuspense } from './components';
export { DashboardPicker } from './components/dashboard_picker';
export { SaveModalDashboardProps } from './components/types';
export function plugin() {
return new PresentationUtilPlugin();
}
export { PresentationUtilPluginSetup, PresentationUtilPluginStart } from './types';

View file

@ -18,7 +18,10 @@ import {
SavedObjectSaveOpts,
OnSaveProps,
} from '../../../../saved_objects/public';
import { SavedObjectSaveModalDashboard } from '../../../../presentation_util/public';
import {
LazySavedObjectSaveModalDashboard,
withSuspense,
} from '../../../../presentation_util/public';
import { unhashUrl } from '../../../../kibana_utils/public';
import {
@ -52,6 +55,8 @@ interface TopNavConfigParams {
embeddableId?: string;
}
const SavedObjectSaveModalDashboard = withSuspense(LazySavedObjectSaveModalDashboard);
export const showPublicUrlSwitch = (anonymousUserCapabilities: Capabilities) => {
if (!anonymousUserCapabilities.visualize) return false;
@ -420,40 +425,47 @@ export const getTopNavConfig = (
const useByRefFlow =
!!originatingApp || !dashboard.dashboardFeatureFlagConfig.allowByValueEmbeddables;
const saveModal = useByRefFlow ? (
<SavedObjectSaveModalOrigin
documentInfo={savedVis || { title: '' }}
onSave={onSave}
options={tagOptions}
getAppNameFromId={stateTransfer.getAppNameFromId}
objectType={'visualization'}
onClose={() => {}}
originatingApp={originatingApp}
returnToOriginSwitchLabel={
originatingApp && embeddableId
? i18n.translate('visualize.topNavMenu.updatePanel', {
defaultMessage: 'Update panel on {originatingAppName}',
values: {
originatingAppName: stateTransfer.getAppNameFromId(originatingApp),
},
})
: undefined
}
/>
) : (
<SavedObjectSaveModalDashboard
documentInfo={{
id: visualizeCapabilities.save ? savedVis?.id : undefined,
title: savedVis?.title || '',
description: savedVis?.description || '',
}}
canSaveByReference={Boolean(visualizeCapabilities.save)}
onSave={onSave}
tagOptions={tagOptions}
objectType={'visualization'}
onClose={() => {}}
/>
);
let saveModal;
if (useByRefFlow) {
saveModal = (
<SavedObjectSaveModalOrigin
documentInfo={savedVis || { title: '' }}
onSave={onSave}
options={tagOptions}
getAppNameFromId={stateTransfer.getAppNameFromId}
objectType={'visualization'}
onClose={() => {}}
originatingApp={originatingApp}
returnToOriginSwitchLabel={
originatingApp && embeddableId
? i18n.translate('visualize.topNavMenu.updatePanel', {
defaultMessage: 'Update panel on {originatingAppName}',
values: {
originatingAppName: stateTransfer.getAppNameFromId(originatingApp),
},
})
: undefined
}
/>
);
} else {
saveModal = (
<SavedObjectSaveModalDashboard
documentInfo={{
id: visualizeCapabilities.save ? savedVis?.id : undefined,
title: savedVis?.title || '',
description: savedVis?.description || '',
}}
canSaveByReference={Boolean(visualizeCapabilities.save)}
onSave={onSave}
tagOptions={tagOptions}
objectType={'visualization'}
onClose={() => {}}
/>
);
}
showSaveModal(
saveModal,
I18nContext,

View file

@ -9,7 +9,8 @@ import React, { FC, useState, useMemo, useCallback } from 'react';
import { OnSaveProps } from '../../../../../src/plugins/saved_objects/public';
import {
SaveModalDashboardProps,
SavedObjectSaveModalDashboard,
LazySavedObjectSaveModalDashboard,
withSuspense,
} from '../../../../../src/plugins/presentation_util/public';
import { SavedObjectTaggingPluginStart } from '../../../saved_objects_tagging/public';
@ -29,6 +30,8 @@ export type TagEnhancedSavedObjectSaveModalDashboardProps = Omit<
onSave: (props: DashboardSaveProps) => void;
};
const SavedObjectSaveModalDashboard = withSuspense(LazySavedObjectSaveModalDashboard);
export const TagEnhancedSavedObjectSaveModalDashboard: FC<TagEnhancedSavedObjectSaveModalDashboardProps> = ({
initialTags,
onSave,

View file

@ -28,7 +28,12 @@ import {
import { MAP_SAVED_OBJECT_TYPE } from '../../../common/constants';
import { SavedMap } from './saved_map';
import { getMapEmbeddableDisplayName } from '../../../common/i18n_getters';
import { SavedObjectSaveModalDashboard } from '../../../../../../src/plugins/presentation_util/public';
import {
LazySavedObjectSaveModalDashboard,
withSuspense,
} from '../../../../../../src/plugins/presentation_util/public';
const SavedObjectSaveModalDashboard = withSuspense(LazySavedObjectSaveModalDashboard);
export function getTopNavConfig({
savedMap,
@ -192,21 +197,27 @@ export function getTopNavConfig({
}),
};
const PresentationUtilContext = getPresentationUtilContext();
const saveModal =
savedMap.getOriginatingApp() || !getIsAllowByValueEmbeddables() ? (
let saveModal;
if (savedMap.getOriginatingApp() || !getIsAllowByValueEmbeddables()) {
saveModal = (
<SavedObjectSaveModalOrigin
{...saveModalProps}
originatingApp={savedMap.getOriginatingApp()}
getAppNameFromId={savedMap.getAppNameFromId}
options={tagSelector}
/>
) : (
);
} else {
saveModal = (
<SavedObjectSaveModalDashboard
{...saveModalProps}
canSaveByReference={true} // we know here that we have save capabilities.
tagOptions={tagSelector}
/>
);
}
showSaveModal(saveModal, getCoreI18n().Context, PresentationUtilContext);
},