diff --git a/.changeset/sixty-islands-develop.md b/.changeset/sixty-islands-develop.md new file mode 100644 index 0000000000..9eb36cc1a9 --- /dev/null +++ b/.changeset/sixty-islands-develop.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-scaffolder': minor +--- + +Added props to override default Scaffolder page title, subtitle and pageTitleOverride. +Routes like `rootRouteRef`, `selectedTemplateRouteRef`, `nextRouteRef`, `nextSelectedTemplateRouteRef` were made public and can be used in your app (e.g. in custom TemplateCard component). diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index cf69736bd4..158c75e5bd 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -24,10 +24,12 @@ import { JsonObject } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; import { JsonValue } from '@backstage/types'; import { Observable } from '@backstage/types'; +import { PathParams } from '@backstage/core-plugin-api'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; import { ScmIntegrationRegistry } from '@backstage/integration'; +import { SubRouteRef } from '@backstage/core-plugin-api'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { TaskStep } from '@backstage/plugin-scaffolder-common'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; @@ -199,6 +201,9 @@ export type NextFieldExtensionOptions< validation?: NextCustomFieldValidator; }; +// @alpha (undocumented) +export const nextRouteRef: RouteRef; + // @alpha export type NextRouterProps = { components?: { @@ -215,6 +220,11 @@ export const NextScaffolderPage: ( props: PropsWithChildren, ) => JSX.Element; +// @alpha (undocumented) +export const nextSelectedTemplateRouteRef: SubRouteRef< + PathParams<'/templates/:namespace/:templateName'> +>; + // @public export const OwnedEntityPickerFieldExtension: FieldExtensionComponent< string, @@ -287,6 +297,9 @@ export interface RepoUrlPickerUiOptions { }; } +// @public (undocumented) +export const rootRouteRef: RouteRef; + // @public export type RouterProps = { components?: { @@ -302,6 +315,11 @@ export type RouterProps = { filter: (entity: Entity) => boolean; }>; defaultPreviewTemplate?: string; + headerOptions?: { + pageTitleOverride?: string; + title?: string; + subtitle?: string; + }; contextMenu?: { editor?: boolean; actions?: boolean; @@ -508,6 +526,11 @@ export interface ScaffolderUseTemplateSecrets { setSecrets: (input: Record) => void; } +// @public (undocumented) +export const selectedTemplateRouteRef: SubRouteRef< + PathParams<'/templates/:namespace/:templateName'> +>; + // @public export const TaskPage: ({ loadingText }: TaskPageProps) => JSX.Element; diff --git a/plugins/scaffolder/src/components/Router.tsx b/plugins/scaffolder/src/components/Router.tsx index 021d73f5e9..097eddf6cd 100644 --- a/plugins/scaffolder/src/components/Router.tsx +++ b/plugins/scaffolder/src/components/Router.tsx @@ -63,6 +63,11 @@ export type RouterProps = { filter: (entity: Entity) => boolean; }>; defaultPreviewTemplate?: string; + headerOptions?: { + pageTitleOverride?: string; + title?: string; + subtitle?: string; + }; /** * Options for the context menu on the scaffolder page. */ @@ -143,6 +148,7 @@ export const Router = (props: RouterProps) => { groups={groups} TemplateCardComponent={TemplateCardComponent} contextMenu={props.contextMenu} + headerOptions={props.headerOptions} /> } /> diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx index 60a761d171..9c13db72b1 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx @@ -54,12 +54,18 @@ export type ScaffolderPageProps = { actions?: boolean; tasks?: boolean; }; + headerOptions?: { + pageTitleOverride?: string; + title?: string; + subtitle?: string; + }; }; export const ScaffolderPageContents = ({ TemplateCardComponent, groups, contextMenu, + headerOptions, }: ScaffolderPageProps) => { const registerComponentLink = useRouteRef(registerComponentRouteRef); const otherTemplatesGroup = { @@ -80,6 +86,7 @@ export const ScaffolderPageContents = ({ pageTitleOverride="Create a New Component" title="Create a New Component" subtitle="Create new software components using standard templates" + {...headerOptions} > @@ -134,12 +141,14 @@ export const ScaffolderPage = ({ TemplateCardComponent, groups, contextMenu, + headerOptions, }: ScaffolderPageProps) => ( ); diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index e68eece8e5..7853667101 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -61,6 +61,12 @@ export { scaffolderPlugin, } from './plugin'; export * from './components'; +export { + rootRouteRef, + nextRouteRef, + selectedTemplateRouteRef, + nextSelectedTemplateRouteRef, +} from './routes'; export type { TaskPageProps } from './components/TaskPage'; /** next exports */ diff --git a/plugins/scaffolder/src/routes.ts b/plugins/scaffolder/src/routes.ts index 5e2d191443..7451a3a943 100644 --- a/plugins/scaffolder/src/routes.ts +++ b/plugins/scaffolder/src/routes.ts @@ -30,6 +30,7 @@ export const viewTechDocRouteRef = createExternalRouteRef({ params: ['namespace', 'kind', 'name'], }); +/** @public */ export const rootRouteRef = createRouteRef({ id: 'scaffolder', }); @@ -43,16 +44,19 @@ export const legacySelectedTemplateRouteRef = createSubRouteRef({ path: '/templates/:templateName', }); +/** @alpha */ export const nextRouteRef = createRouteRef({ id: 'scaffolder/next', }); +/** @public */ export const selectedTemplateRouteRef = createSubRouteRef({ id: 'scaffolder/selected-template', parent: rootRouteRef, path: '/templates/:namespace/:templateName', }); +/** @alpha */ export const nextSelectedTemplateRouteRef = createSubRouteRef({ id: 'scaffolder/next/selected-template', parent: nextRouteRef,