feat(home): add new frontend system support
Migrates home plugin to support the new frontend system architecture by introducing extension blueprints for composable homepage functionality. Key changes: - Add CustomHomepageWidgetBlueprint for creating installable homepage widgets - Add CustomHomepageBlueprint for composing pages from widget extensions - Introduce titleExtensionDataRef for NFS title handling This attempts to bring the home plugin up to par with other core plugins that have migrated to the new frontend system Signed-off-by: Adam Kunicki <kunickiaj@gmail.com>
This commit is contained in:
@@ -13,4 +13,21 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* React components and utilities for the home plugin's new frontend system.
|
||||
*
|
||||
* @remarks
|
||||
* This package provides React components, blueprints, and utilities for building
|
||||
* customizable home pages with the new Backstage frontend system.
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
export { homeReactTranslationRef } from './translation';
|
||||
export { titleExtensionDataRef } from './alpha/dataRefs';
|
||||
export {
|
||||
HomepageWidgetBlueprint,
|
||||
widgetMetadataRef,
|
||||
type HomepageWidgetBlueprintParams,
|
||||
} from './alpha/blueprints/HomepageWidgetBlueprint';
|
||||
export type { ComponentParts, CardLayout, CardSettings } from './extensions';
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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 { lazy, ReactElement } from 'react';
|
||||
import { compatWrapper } from '@backstage/core-compat-api';
|
||||
import {
|
||||
coreExtensionData,
|
||||
createExtensionBlueprint,
|
||||
createExtensionDataRef,
|
||||
ExtensionBoundary,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import {
|
||||
CardExtension,
|
||||
CardExtensionProps,
|
||||
CardLayout,
|
||||
CardSettings,
|
||||
ComponentParts,
|
||||
} from '../../extensions';
|
||||
|
||||
/** @alpha */
|
||||
export interface HomepageWidgetBlueprintParams {
|
||||
/**
|
||||
* Optional name for the widget. If not provided, the extension will use only its kind
|
||||
* in the extension ID.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* Optional title displayed for the widget, used as the default card heading.
|
||||
*/
|
||||
title?: string;
|
||||
/**
|
||||
* Optional description shown in the widget catalog when adding new cards.
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* Component parts rendered within the card.
|
||||
*/
|
||||
components: () => Promise<ComponentParts>;
|
||||
/**
|
||||
* Layout hints used by the customizable grid.
|
||||
*/
|
||||
layout?: CardLayout;
|
||||
/**
|
||||
* Schema used to configure widget settings.
|
||||
*/
|
||||
settings?: CardSettings;
|
||||
/**
|
||||
* Default props forwarded to the rendered widget component.
|
||||
*/
|
||||
componentProps?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
const DEFAULT_WIDGET_ATTACH_POINT = {
|
||||
id: 'page:home',
|
||||
input: 'widgets',
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Extension data ref for widget metadata.
|
||||
* @alpha
|
||||
*/
|
||||
export const widgetMetadataRef = createExtensionDataRef<{
|
||||
name?: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
layout?: CardLayout;
|
||||
settings?: CardSettings;
|
||||
}>().with({ id: 'home.widget.metadata' });
|
||||
|
||||
/**
|
||||
* Creates widgets that can be installed into the home page grid.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export const HomepageWidgetBlueprint = createExtensionBlueprint({
|
||||
kind: 'home-widget',
|
||||
attachTo: DEFAULT_WIDGET_ATTACH_POINT,
|
||||
output: [coreExtensionData.reactElement, widgetMetadataRef],
|
||||
*factory(params: HomepageWidgetBlueprintParams, { node }) {
|
||||
const isCustomizable = params.settings?.schema !== undefined;
|
||||
const LazyCard = lazy(() =>
|
||||
params.components().then(parts => ({
|
||||
default: (props: CardExtensionProps<Record<string, unknown>>) => (
|
||||
<CardExtension
|
||||
{...props}
|
||||
{...parts}
|
||||
title={props.title || params.title}
|
||||
isCustomizable={isCustomizable}
|
||||
/>
|
||||
),
|
||||
})),
|
||||
);
|
||||
|
||||
const Widget = (
|
||||
props: CardExtensionProps<Record<string, unknown>>,
|
||||
): ReactElement =>
|
||||
compatWrapper(
|
||||
<ExtensionBoundary node={node}>
|
||||
<LazyCard {...props} />
|
||||
</ExtensionBoundary>,
|
||||
);
|
||||
|
||||
yield coreExtensionData.reactElement(
|
||||
<Widget {...(params.componentProps ?? {})} />,
|
||||
);
|
||||
|
||||
yield widgetMetadataRef({
|
||||
name: params.name,
|
||||
title: params.title,
|
||||
description: params.description,
|
||||
layout: params.layout,
|
||||
settings: params.settings,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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 { createExtensionDataRef } from '@backstage/frontend-plugin-api';
|
||||
|
||||
/**
|
||||
* Title data supplied to the home page extension when composing via the new frontend system.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export const titleExtensionDataRef = createExtensionDataRef<string>().with({
|
||||
id: 'title',
|
||||
});
|
||||
@@ -121,7 +121,7 @@ type CardExtensionComponentProps<T> = CardExtensionProps<T> &
|
||||
overrideTitle?: string;
|
||||
};
|
||||
|
||||
function CardExtension<T>(props: CardExtensionComponentProps<T>) {
|
||||
export function CardExtension<T>(props: CardExtensionComponentProps<T>) {
|
||||
const {
|
||||
Renderer,
|
||||
Content,
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
import { createTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
|
||||
/**
|
||||
* Translation reference for the home-react plugin.
|
||||
* Contains localized text strings for home page components and settings modals.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export const homeReactTranslationRef = createTranslationRef({
|
||||
|
||||
Reference in New Issue
Block a user