feat(frontend-plugin-api): use extension boundary and suspense
Signed-off-by: Camila Belo <camilaibs@gmail.com>
This commit is contained in:
@@ -14,18 +14,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { ExtensionBoundary } from '../components';
|
||||
import React, { lazy, useEffect } from 'react';
|
||||
import { useAnalytics } from '@backstage/core-plugin-api';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { routableExtensionRenderedEvent } from '../../../core-plugin-api/src/analytics/Tracker';
|
||||
import { ExtensionBoundary, ExtensionSuspense } from '../components';
|
||||
import { createSchemaFromZod, PortableSchema } from '../schema';
|
||||
import {
|
||||
coreExtensionData,
|
||||
createExtension,
|
||||
Extension,
|
||||
ExtensionInputValues,
|
||||
AnyExtensionInputMap,
|
||||
} from '../wiring';
|
||||
import { AnyExtensionInputMap } from '../wiring/createExtension';
|
||||
import { Expand } from '../types';
|
||||
import { RouteRef } from '../routing';
|
||||
import { Expand } from '../types';
|
||||
|
||||
/**
|
||||
* Helper for creating extensions for a routable React page component.
|
||||
@@ -55,6 +58,10 @@ export function createPageExtension<
|
||||
}) => Promise<JSX.Element>;
|
||||
},
|
||||
): Extension<TConfig> {
|
||||
const { id, routeRef } = options;
|
||||
|
||||
const attachTo = options.attachTo ?? { id: 'core.routes', input: 'routes' };
|
||||
|
||||
const configSchema =
|
||||
'configSchema' in options
|
||||
? options.configSchema
|
||||
@@ -63,33 +70,49 @@ export function createPageExtension<
|
||||
) as PortableSchema<TConfig>);
|
||||
|
||||
return createExtension({
|
||||
id: options.id,
|
||||
attachTo: options.attachTo ?? { id: 'core.routes', input: 'routes' },
|
||||
id,
|
||||
attachTo,
|
||||
configSchema,
|
||||
inputs: options.inputs,
|
||||
disabled: options.disabled,
|
||||
output: {
|
||||
element: coreExtensionData.reactElement,
|
||||
path: coreExtensionData.routePath,
|
||||
routeRef: coreExtensionData.routeRef.optional(),
|
||||
},
|
||||
inputs: options.inputs,
|
||||
configSchema,
|
||||
factory({ bind, config, inputs, source }) {
|
||||
const LazyComponent = React.lazy(() =>
|
||||
const { path } = config;
|
||||
|
||||
const PageComponent = lazy(() =>
|
||||
options
|
||||
.loader({ config, inputs })
|
||||
.then(element => ({ default: () => element })),
|
||||
);
|
||||
|
||||
const ExtensionComponent = () => {
|
||||
const analytics = useAnalytics();
|
||||
|
||||
// This event, never exposed to end-users of the analytics API,
|
||||
// helps inform which extension metadata gets associated with a
|
||||
// navigation event when the route navigated to is a gathered
|
||||
// mountpoint.
|
||||
useEffect(() => {
|
||||
analytics.captureEvent(routableExtensionRenderedEvent, '');
|
||||
}, [analytics]);
|
||||
|
||||
return <PageComponent />;
|
||||
};
|
||||
|
||||
bind({
|
||||
path: config.path,
|
||||
path,
|
||||
routeRef,
|
||||
element: (
|
||||
<ExtensionBoundary source={source}>
|
||||
<React.Suspense fallback="...">
|
||||
<LazyComponent />
|
||||
</React.Suspense>
|
||||
<ExtensionBoundary id={id} source={source} routeRef={routeRef}>
|
||||
<ExtensionSuspense>
|
||||
<ExtensionComponent />
|
||||
</ExtensionSuspense>
|
||||
</ExtensionBoundary>
|
||||
),
|
||||
routeRef: options.routeRef,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user