refactor(home): restructure extension architecture to match catalog pattern
Reorganize the home plugin's new frontend system extensions to follow the same pattern as the catalog plugin's EntityContentLayoutBlueprint. Key changes: - Widgets now attach directly to page:home instead of through an intermediate HomepageBlueprint extension - Add HomePageLayoutBlueprint in home-react for custom layout creation, with a built-in default layout as fallback - Remove compatWrapper from HomepageWidgetBlueprint (consumer responsibility, reduced need with NFS support in old system) - Remove HomepageCompositionRoot usage (old system artifact) - Delete HomepageBlueprint (replaced by HomePageLayoutBlueprint) - Update app-next example and dev harness to use new pattern Signed-off-by: Adam Kunicki <kunickiaj@gmail.com>
This commit is contained in:
@@ -28,8 +28,14 @@ export {
|
||||
HomepageWidgetBlueprint,
|
||||
type HomepageWidgetBlueprintParams,
|
||||
} from './alpha/blueprints/HomepageWidgetBlueprint';
|
||||
export {
|
||||
HomePageLayoutBlueprint,
|
||||
type HomePageLayoutBlueprintParams,
|
||||
} from './alpha/blueprints/HomePageLayoutBlueprint';
|
||||
export {
|
||||
homePageWidgetDataRef,
|
||||
type HomePageWidgetData,
|
||||
homePageLayoutComponentDataRef,
|
||||
type HomePageLayoutProps,
|
||||
} from './alpha/dataRefs';
|
||||
export type { ComponentParts, CardLayout, CardSettings } from './extensions';
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2025 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { JSX } from 'react';
|
||||
import {
|
||||
createExtensionBlueprint,
|
||||
ExtensionBoundary,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import {
|
||||
homePageLayoutComponentDataRef,
|
||||
HomePageLayoutProps,
|
||||
} from '../dataRefs';
|
||||
|
||||
/**
|
||||
* Parameters for creating a home page layout extension.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export interface HomePageLayoutBlueprintParams {
|
||||
/**
|
||||
* Async loader that returns the layout component.
|
||||
* The component receives the collected widgets and renders them.
|
||||
*/
|
||||
loader: () => Promise<(props: HomePageLayoutProps) => JSX.Element>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blueprint for creating custom home page layouts.
|
||||
*
|
||||
* A layout receives the list of installed widgets and is responsible for
|
||||
* arranging them on the home page. This follows the same pattern as
|
||||
* `EntityContentLayoutBlueprint` in the catalog plugin.
|
||||
*
|
||||
* If no layout extension is installed, the home page uses a built-in default.
|
||||
* Users can install their own layout to customize how widgets are arranged.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export const HomePageLayoutBlueprint = createExtensionBlueprint({
|
||||
kind: 'home-page-layout',
|
||||
attachTo: { id: 'page:home', input: 'layouts' },
|
||||
output: [homePageLayoutComponentDataRef],
|
||||
dataRefs: {
|
||||
component: homePageLayoutComponentDataRef,
|
||||
},
|
||||
*factory({ loader }: HomePageLayoutBlueprintParams, { node }) {
|
||||
yield homePageLayoutComponentDataRef(
|
||||
ExtensionBoundary.lazyComponent(node, loader),
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
import { lazy, ReactElement } from 'react';
|
||||
import { compatWrapper } from '@backstage/core-compat-api';
|
||||
import {
|
||||
createExtensionBlueprint,
|
||||
ExtensionBoundary,
|
||||
@@ -96,12 +95,11 @@ export const HomepageWidgetBlueprint = createExtensionBlueprint({
|
||||
|
||||
const Widget = (
|
||||
props: CardExtensionProps<Record<string, unknown>>,
|
||||
): ReactElement =>
|
||||
compatWrapper(
|
||||
<ExtensionBoundary node={node}>
|
||||
<LazyCard {...props} />
|
||||
</ExtensionBoundary>,
|
||||
);
|
||||
): ReactElement => (
|
||||
<ExtensionBoundary node={node}>
|
||||
<LazyCard {...props} />
|
||||
</ExtensionBoundary>
|
||||
);
|
||||
|
||||
yield homePageWidgetDataRef({
|
||||
component: <Widget {...(params.componentProps ?? {})} />,
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { createExtensionDataRef } from '@backstage/frontend-plugin-api';
|
||||
import { ReactElement } from 'react';
|
||||
import { JSX, ReactElement } from 'react';
|
||||
import type { CardLayout, CardSettings } from '../extensions';
|
||||
|
||||
/**
|
||||
@@ -64,3 +64,30 @@ export const homePageWidgetDataRef =
|
||||
createExtensionDataRef<HomePageWidgetData>().with({
|
||||
id: 'home.widget.data',
|
||||
});
|
||||
|
||||
/**
|
||||
* Props provided to a home page layout component.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export interface HomePageLayoutProps {
|
||||
/**
|
||||
* The list of widget elements and metadata to render on the home page.
|
||||
*/
|
||||
widgets: Array<HomePageWidgetData>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension data ref for home page layout components.
|
||||
*
|
||||
* A layout receives the collected widgets and is responsible for arranging
|
||||
* them on the home page. This follows the same pattern as
|
||||
* EntityContentLayoutBlueprint in the catalog plugin.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export const homePageLayoutComponentDataRef = createExtensionDataRef<
|
||||
(props: HomePageLayoutProps) => JSX.Element
|
||||
>().with({
|
||||
id: 'home.layout.component',
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user