docs: improve new frontend system docs for techdocs, scaffolder, and catalog
Expand the TechDocs home page customization section with concrete examples showing how to override the page:techdocs extension using a frontend module. Replace the incorrect scaffolder custom step layouts guide with a note that this feature is not yet supported in the new frontend system. Restore missing catalog customization docs for columns, actions, table options, removing filters, and fully custom catalog pages to ensure parity with the old frontend system guide. Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> Made-with: Cursor
This commit is contained in:
@@ -61,7 +61,149 @@ app:
|
||||
|
||||
### Custom filters
|
||||
|
||||
You can create custom catalog filters using the `CatalogFilterBlueprint` from `@backstage/plugin-catalog-react/alpha`. See the [extension overrides](../../frontend-system/architecture/25-extension-overrides.md) documentation for details on how to install custom extensions.
|
||||
You can create custom catalog filters using the `CatalogFilterBlueprint` from `@backstage/plugin-catalog-react/alpha`. For example, to add a custom security tier filter:
|
||||
|
||||
```tsx title="packages/app/src/catalog/SecurityTierFilter.tsx"
|
||||
import { CatalogFilterBlueprint } from '@backstage/plugin-catalog-react/alpha';
|
||||
|
||||
export const securityTierFilter = CatalogFilterBlueprint.make({
|
||||
name: 'security-tier',
|
||||
params: {
|
||||
loader: async () => {
|
||||
const { EntitySecurityTierPicker } = await import(
|
||||
'./EntitySecurityTierPicker'
|
||||
);
|
||||
return <EntitySecurityTierPicker />;
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Then install it as a frontend module:
|
||||
|
||||
```tsx title="packages/app/src/catalog/catalogCustomizations.tsx"
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
import { securityTierFilter } from './SecurityTierFilter';
|
||||
|
||||
export default createFrontendModule({
|
||||
pluginId: 'catalog',
|
||||
extensions: [securityTierFilter],
|
||||
});
|
||||
```
|
||||
|
||||
### Removing default filters
|
||||
|
||||
Default filters can be disabled through `app-config.yaml` by setting them to `false`:
|
||||
|
||||
```yaml title="app-config.yaml"
|
||||
app:
|
||||
extensions:
|
||||
- catalog-filter:catalog/lifecycle: false
|
||||
- catalog-filter:catalog/tag: false
|
||||
- catalog-filter:catalog/processing-status: false
|
||||
```
|
||||
|
||||
## Customizing columns, actions, and table options
|
||||
|
||||
In the old frontend system, customizing the catalog table columns, row actions,
|
||||
and table options was done by passing props directly to the `CatalogIndexPage`
|
||||
component. In the new frontend system, these customizations are done by
|
||||
overriding the `page:catalog` extension.
|
||||
|
||||
For example, to customize the catalog index page with custom columns or actions,
|
||||
you can override the page extension using a frontend module:
|
||||
|
||||
```tsx title="packages/app/src/catalog/customCatalogPage.tsx"
|
||||
import {
|
||||
PageBlueprint,
|
||||
createFrontendModule,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
|
||||
const customCatalogPage = PageBlueprint.make({
|
||||
params: {
|
||||
path: '/catalog',
|
||||
loader: () =>
|
||||
import('./CustomCatalogPage').then(m => <m.CustomCatalogPage />),
|
||||
},
|
||||
});
|
||||
|
||||
export default createFrontendModule({
|
||||
pluginId: 'catalog',
|
||||
extensions: [customCatalogPage],
|
||||
});
|
||||
```
|
||||
|
||||
Inside your custom catalog page component you have full control over the table
|
||||
columns, actions, and options. You can compose a page using components from
|
||||
`@backstage/plugin-catalog` and `@backstage/plugin-catalog-react`:
|
||||
|
||||
```tsx title="packages/app/src/catalog/CustomCatalogPage.tsx"
|
||||
import {
|
||||
PageWithHeader,
|
||||
Content,
|
||||
ContentHeader,
|
||||
SupportButton,
|
||||
} from '@backstage/core-components';
|
||||
import { useApi, configApiRef } from '@backstage/core-plugin-api';
|
||||
import { CatalogTable } from '@backstage/plugin-catalog';
|
||||
import {
|
||||
EntityListProvider,
|
||||
CatalogFilterLayout,
|
||||
EntityKindPicker,
|
||||
EntityLifecyclePicker,
|
||||
EntityNamespacePicker,
|
||||
EntityOwnerPicker,
|
||||
EntityProcessingStatusPicker,
|
||||
EntityTagPicker,
|
||||
EntityTypePicker,
|
||||
UserListPicker,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
|
||||
export const CustomCatalogPage = () => {
|
||||
const orgName =
|
||||
useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage';
|
||||
|
||||
return (
|
||||
<PageWithHeader title={orgName} themeId="home">
|
||||
<Content>
|
||||
<ContentHeader title="">
|
||||
<SupportButton>All your software catalog entities</SupportButton>
|
||||
</ContentHeader>
|
||||
<EntityListProvider pagination>
|
||||
<CatalogFilterLayout>
|
||||
<CatalogFilterLayout.Filters>
|
||||
<EntityKindPicker />
|
||||
<EntityTypePicker />
|
||||
<UserListPicker />
|
||||
<EntityOwnerPicker />
|
||||
<EntityLifecyclePicker />
|
||||
<EntityTagPicker />
|
||||
<EntityProcessingStatusPicker />
|
||||
<EntityNamespacePicker />
|
||||
</CatalogFilterLayout.Filters>
|
||||
<CatalogFilterLayout.Content>
|
||||
<CatalogTable />
|
||||
</CatalogFilterLayout.Content>
|
||||
</CatalogFilterLayout>
|
||||
</EntityListProvider>
|
||||
</Content>
|
||||
</PageWithHeader>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
:::note Note
|
||||
|
||||
The catalog index page is designed to have a minimal code footprint to support
|
||||
easy customization, but creating a replica does introduce a possibility of
|
||||
drifting out of date over time. Be sure to check the catalog
|
||||
[CHANGELOG](https://github.com/backstage/backstage/blob/master/plugins/catalog/CHANGELOG.md)
|
||||
periodically.
|
||||
|
||||
:::
|
||||
|
||||
For more details on extension overrides and the different override patterns
|
||||
available, see the [extension overrides](../../frontend-system/architecture/25-extension-overrides.md) documentation.
|
||||
|
||||
## Entity page
|
||||
|
||||
|
||||
@@ -11,61 +11,12 @@ read the [old frontend system version of this guide](./writing-custom-step-layou
|
||||
instead.
|
||||
::::
|
||||
|
||||
Every form in each step rendered in the frontend uses the default form layout from [react-jsonschema-form](https://rjsf-team.github.io/react-jsonschema-form/docs/). It is possible to override this behaviour by supplying a `ui:ObjectFieldTemplate` property for a particular step:
|
||||
:::caution
|
||||
Custom step layouts are not yet supported in the new frontend system. The
|
||||
scaffolder plugin does not provide an extension blueprint or input for
|
||||
registering custom layouts in the new system.
|
||||
|
||||
```yaml
|
||||
parameters:
|
||||
- title: Fill in some steps
|
||||
ui:ObjectFieldTemplate: TwoColumn
|
||||
```
|
||||
|
||||
This is the same [field](https://rjsf-team.github.io/react-jsonschema-form/docs/advanced-customization/custom-templates#objectfieldtemplate) used by [react-jsonschema-form](https://rjsf-team.github.io/react-jsonschema-form/docs/) but we need to add a couple of steps to ensure that the string value of `TwoColumn` above is resolved to a react component.
|
||||
|
||||
## Registering a React component as a custom step layout
|
||||
|
||||
In the new frontend system, custom step layouts can be registered by creating a scaffolder module plugin that provides the layout through an extension override. Create a new plugin module:
|
||||
|
||||
```tsx title="packages/app/src/scaffolder/customLayouts.tsx"
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
import scaffolderPlugin from '@backstage/plugin-scaffolder/alpha';
|
||||
import { LayoutTemplate } from '@backstage/plugin-scaffolder-react';
|
||||
import { Grid } from '@material-ui/core';
|
||||
|
||||
const TwoColumn: LayoutTemplate = ({ properties, description, title }) => {
|
||||
const mid = Math.ceil(properties.length / 2);
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>{title}</h1>
|
||||
<h2>In two column layout!!</h2>
|
||||
<Grid container justifyContent="flex-end">
|
||||
{properties.slice(0, mid).map(prop => (
|
||||
<Grid item xs={6} key={prop.content.key}>
|
||||
{prop.content}
|
||||
</Grid>
|
||||
))}
|
||||
{properties.slice(mid).map(prop => (
|
||||
<Grid item xs={6} key={prop.content.key}>
|
||||
{prop.content}
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
{description}
|
||||
</>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
Use `createScaffolderLayout` from `@backstage/plugin-scaffolder-react` and `scaffolderPlugin.provide` from `@backstage/plugin-scaffolder` to register the layout under the name `TwoColumn`, then install it through a frontend module using `createFrontendModule` together with `scaffolderPlugin.withOverrides` from `@backstage/plugin-scaffolder/alpha`, following the patterns described in the extension overrides guide.
|
||||
|
||||
For details on how to override and extend extensions in the new frontend system, see the [extension overrides](../../frontend-system/architecture/25-extension-overrides.md) documentation.
|
||||
|
||||
## Using the custom step layout
|
||||
|
||||
Once the layout is registered, it can be used as a `ui:ObjectFieldTemplate` in your template file:
|
||||
|
||||
```yaml
|
||||
parameters:
|
||||
- title: Fill in some steps
|
||||
ui:ObjectFieldTemplate: TwoColumn
|
||||
```
|
||||
If you need custom step layouts, you can continue using the
|
||||
[old frontend system](./writing-custom-step-layouts--old.md) approach with
|
||||
`createScaffolderLayout` and the `ScaffolderLayouts` component.
|
||||
:::
|
||||
|
||||
@@ -120,8 +120,52 @@ similar to the one provided by the Catalog plugin. TechDocs also comes with
|
||||
an alternative grid based layout and panel layout.
|
||||
|
||||
Customization of the TechDocs home page in the new frontend system is done by
|
||||
overriding the default page extension. For details on how to override
|
||||
extensions, see the [extension overrides](../../frontend-system/architecture/25-extension-overrides.md) documentation.
|
||||
overriding the `page:techdocs` extension. The TechDocs home page is a standard
|
||||
page extension created using `PageBlueprint`, which means you can override it
|
||||
just like any other page extension.
|
||||
|
||||
The simplest approach is to create a frontend module that provides a replacement
|
||||
page extension with the same extension ID. Since the TechDocs page extension has
|
||||
the ID `page:techdocs`, you can override it by creating a new page extension
|
||||
under the `techdocs` plugin namespace:
|
||||
|
||||
```tsx title="packages/app/src/techdocs/TechDocsHomePage.tsx"
|
||||
import {
|
||||
PageBlueprint,
|
||||
createFrontendModule,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
|
||||
const customTechDocsPage = PageBlueprint.make({
|
||||
params: {
|
||||
path: '/docs',
|
||||
loader: () =>
|
||||
import('./CustomTechDocsHome').then(m => <m.CustomTechDocsHome />),
|
||||
},
|
||||
});
|
||||
|
||||
export default createFrontendModule({
|
||||
pluginId: 'techdocs',
|
||||
extensions: [customTechDocsPage],
|
||||
});
|
||||
```
|
||||
|
||||
Then install the module in your app:
|
||||
|
||||
```tsx title="packages/app/src/App.tsx"
|
||||
import { createApp } from '@backstage/frontend-defaults';
|
||||
import customTechDocsModule from './techdocs/TechDocsHomePage';
|
||||
|
||||
const app = createApp({
|
||||
features: [customTechDocsModule],
|
||||
});
|
||||
|
||||
export default app.createRoot();
|
||||
```
|
||||
|
||||
You can also use the `.override(...)` method on the original extension if you
|
||||
want to customize the existing page without fully replacing it. For more details
|
||||
on extension overrides and the different override patterns available, see the
|
||||
[extension overrides](../../frontend-system/architecture/25-extension-overrides.md) documentation.
|
||||
|
||||
## How to customize the TechDocs reader page?
|
||||
|
||||
|
||||
Reference in New Issue
Block a user