frontend-plugin-api: make header actions a element[]
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -91,7 +91,7 @@ const examplePlugin: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -1722,7 +1722,7 @@ export const PageBlueprint: ExtensionBlueprint_2<{
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
@@ -1735,7 +1735,7 @@ export const PageBlueprint: ExtensionBlueprint_2<{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ExtensionDataRef_2<JSX_2, 'core.reactElement', {}>
|
||||
| ExtensionDataRef_2<JSX_2.Element, 'core.reactElement', {}>
|
||||
| ExtensionDataRef_2<
|
||||
string,
|
||||
'core.title',
|
||||
@@ -1752,7 +1752,7 @@ export const PageBlueprint: ExtensionBlueprint_2<{
|
||||
>;
|
||||
inputs: {
|
||||
pages: ExtensionInput_2<
|
||||
| ConfigurableExtensionDataRef_2<JSX_2, 'core.reactElement', {}>
|
||||
| ConfigurableExtensionDataRef_2<JSX_2.Element, 'core.reactElement', {}>
|
||||
| ConfigurableExtensionDataRef_2<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef_2<
|
||||
RouteRef<AnyRouteRefParams_2>,
|
||||
@@ -1804,7 +1804,7 @@ export interface PageLayoutProps {
|
||||
// (undocumented)
|
||||
children?: ReactNode;
|
||||
// (undocumented)
|
||||
headerActions?: ReactNode;
|
||||
headerActions?: Array<JSX.Element | null>;
|
||||
// (undocumented)
|
||||
icon?: IconElement;
|
||||
// (undocumented)
|
||||
@@ -1853,7 +1853,7 @@ export const PluginHeaderActionBlueprint: ExtensionBlueprint_2<{
|
||||
|
||||
// @public
|
||||
export type PluginHeaderActionsApi = {
|
||||
getPluginHeaderActions(pluginId: string): ReactNode[];
|
||||
getPluginHeaderActions(pluginId: string): Array<JSX_2.Element | null>;
|
||||
};
|
||||
|
||||
// @public
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ReactNode } from 'react';
|
||||
import { JSX } from 'react';
|
||||
import { createApiRef } from '../system';
|
||||
|
||||
/**
|
||||
@@ -32,7 +32,7 @@ export type PluginHeaderActionsApi = {
|
||||
/**
|
||||
* Returns the header actions for a given plugin.
|
||||
*/
|
||||
getPluginHeaderActions(pluginId: string): ReactNode[];
|
||||
getPluginHeaderActions(pluginId: string): Array<JSX.Element | null>;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ReactNode } from 'react';
|
||||
import { JSX } from 'react';
|
||||
import { Routes, Route, Navigate } from 'react-router-dom';
|
||||
import { IconElement } from '../icons/types';
|
||||
import { RouteRef } from '../routing';
|
||||
@@ -27,15 +27,6 @@ import { ExtensionBoundary, PageLayout, PageTab } from '../components';
|
||||
import { useApi } from '../apis/system';
|
||||
import { pluginHeaderActionsApiRef } from '../apis/definitions/PluginHeaderActionsApi';
|
||||
|
||||
function usePluginHeaderActions(pluginId: string): ReactNode {
|
||||
const pluginHeaderActionsApi = useApi(pluginHeaderActionsApiRef);
|
||||
const actions = pluginHeaderActionsApi.getPluginHeaderActions(pluginId);
|
||||
if (actions.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
return <>{actions}</>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates extensions that are routable React page components.
|
||||
*
|
||||
@@ -93,7 +84,9 @@ export const PageBlueprint = createExtensionBlueprint({
|
||||
if (params.loader) {
|
||||
const loader = params.loader;
|
||||
const PageContent = () => {
|
||||
const headerActions = usePluginHeaderActions(pluginId);
|
||||
const headerActionsApi = useApi(pluginHeaderActionsApiRef);
|
||||
const headerActions = headerActionsApi.getPluginHeaderActions(pluginId);
|
||||
|
||||
return (
|
||||
<PageLayout
|
||||
title={title}
|
||||
@@ -123,7 +116,9 @@ export const PageBlueprint = createExtensionBlueprint({
|
||||
|
||||
const PageContent = () => {
|
||||
const firstPagePath = inputs.pages[0]?.get(coreExtensionData.routePath);
|
||||
const headerActions = usePluginHeaderActions(pluginId);
|
||||
|
||||
const headerActionsApi = useApi(pluginHeaderActionsApiRef);
|
||||
const headerActions = headerActionsApi.getPluginHeaderActions(pluginId);
|
||||
|
||||
return (
|
||||
<PageLayout
|
||||
@@ -154,7 +149,8 @@ export const PageBlueprint = createExtensionBlueprint({
|
||||
yield coreExtensionData.reactElement(<PageContent />);
|
||||
} else {
|
||||
const PageContent = () => {
|
||||
const headerActions = usePluginHeaderActions(pluginId);
|
||||
const headerActionsApi = useApi(pluginHeaderActionsApiRef);
|
||||
const headerActions = headerActionsApi.getPluginHeaderActions(pluginId);
|
||||
return (
|
||||
<PageLayout title={title} icon={icon} headerActions={headerActions} />
|
||||
);
|
||||
|
||||
@@ -38,7 +38,7 @@ export interface PageLayoutProps {
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
noHeader?: boolean;
|
||||
headerActions?: ReactNode;
|
||||
headerActions?: Array<JSX.Element | null>;
|
||||
tabs?: PageTab[];
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
@@ -567,7 +567,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef_2;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -113,7 +113,7 @@ const visualizerPlugin: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -14,9 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ReactNode } from 'react';
|
||||
import { JSX } from 'react';
|
||||
import { type PluginHeaderActionsApi } from '@backstage/frontend-plugin-api';
|
||||
|
||||
// Stable reference
|
||||
const EMPTY_ACTIONS = new Array<JSX.Element | null>();
|
||||
|
||||
type ActionInput = {
|
||||
element: JSX.Element;
|
||||
pluginId: string;
|
||||
@@ -28,16 +31,18 @@ type ActionInput = {
|
||||
* @internal
|
||||
*/
|
||||
export class DefaultPluginHeaderActionsApi implements PluginHeaderActionsApi {
|
||||
constructor(private readonly actionsByPlugin: Map<string, ReactNode[]>) {}
|
||||
constructor(
|
||||
private readonly actionsByPlugin: Map<string, Array<JSX.Element | null>>,
|
||||
) {}
|
||||
|
||||
getPluginHeaderActions(pluginId: string): ReactNode[] {
|
||||
return this.actionsByPlugin.get(pluginId) ?? [];
|
||||
getPluginHeaderActions(pluginId: string): Array<JSX.Element | null> {
|
||||
return this.actionsByPlugin.get(pluginId) ?? EMPTY_ACTIONS;
|
||||
}
|
||||
|
||||
static fromActions(
|
||||
actions: Array<ActionInput>,
|
||||
): DefaultPluginHeaderActionsApi {
|
||||
const actionsByPlugin = new Map<string, ReactNode[]>();
|
||||
const actionsByPlugin = new Map<string, Array<JSX.Element | null>>();
|
||||
|
||||
for (const action of actions) {
|
||||
let pluginActions = actionsByPlugin.get(action.pluginId);
|
||||
|
||||
@@ -92,7 +92,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -242,7 +242,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef_2;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -185,7 +185,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef_2;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -134,7 +134,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef_2;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -1084,7 +1084,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef_2;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
@@ -1266,7 +1266,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef_2;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -150,7 +150,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef_2;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -198,7 +198,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -232,7 +232,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef_2;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -106,7 +106,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef_2;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -112,7 +112,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef_2;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -276,7 +276,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef_2;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -185,7 +185,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
@@ -355,7 +355,7 @@ export const searchPage: OverridableExtensionDefinition<{
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -352,7 +352,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef_2;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
@@ -445,7 +445,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef_2;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
@@ -124,7 +124,7 @@ const _default: OverridableFrontendPlugin<
|
||||
path: string;
|
||||
title?: string;
|
||||
icon?: IconElement;
|
||||
loader?: () => Promise<JSX.Element>;
|
||||
loader?: () => Promise<JSX_2.Element>;
|
||||
routeRef?: RouteRef;
|
||||
noHeader?: boolean;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user