目录定制
Backstage 软件目录带有一个默认的CatalogIndexPage的默认设置。@backstage/create-app.
如果您想更改默认索引页面,例如在目录中添加自定义过滤器,您可以创建自己的CatalogIndexPage.
注意:目录索引页的设计只占用了最少的代码,以 > 支持简便的定制,但创建一个副本确实有可能 > 随着时间的推移而过时。 请务必定期检查目录 > CHANGELOG>。
例如,假设我想允许通过添加到实体中的自定义注释进行过滤、company.com/security-tier首先,我将复制默认目录页面的代码并创建一个组件。
// imports, etc omitted for brevity. for full source see:
// https://github.com/backstage/backstage/blob/master/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx
export const CustomCatalogPage = ({
  columns,
  actions,
  initiallySelectedFilter = 'owned',
}: CatalogPageProps) => {
  const createComponentLink = useRouteRef(
    catalogPlugin.externalRoutes.createComponent,
  );
  return (
    <PageWithHeader title={`${orgName} Catalog`} themeId="home">
      <EntityListProvider>
        <Content>
          <ContentHeader titleComponent={<CatalogKindHeader />}>
            <CreateButton title="Create Component" to={createComponentLink()} />
            <SupportButton>All your software catalog entities</SupportButton>
          </ContentHeader>
          <CatalogFilterLayout>
            <CatalogFilterLayout.Filters>
              <EntityTypePicker />
              <UserListPicker initialFilter={initiallySelectedFilter} />
              <EntityTagPicker />
            </CatalogFilterLayout.Filters>
            <CatalogFilterLayout.Content>
              <CatalogTable columns={columns} actions={actions} />
            </CatalogFilterLayout.Content>
          </CatalogFilterLayout>
        </Content>
      </EntityListProvider>
    </PageWithHeader>
  );
};
EntityListProvider中的实体列表。catalog-backend以及连接过滤器的方法。
现在,我们可以创建一个新的过滤器来实现EntityFilter接口:
import { EntityFilter } from '@backstage/plugin-catalog-react';
import { Entity } from '@backstage/catalog-model';
class EntitySecurityTierFilter implements EntityFilter {
  constructor(readonly values: string[]) {}
  filterEntity(entity: Entity): boolean {
    const tier = entity.metadata.annotations?.['company.com/security-tier'];
    return tier !== undefined && this.values.includes(tier);
  }
}
EntityFilter接口允许后端过滤器,这些过滤器会被传递给catalog-backend- 或前端过滤器,在从后端加载实体后应用。
我们将使用此过滤器以类型安全的方式扩展默认过滤器。 让我们创建自定义过滤器形状,并在此过滤器旁边的某个地方扩展默认过滤器:
export type CustomFilters = DefaultEntityFilters & {
  securityTiers?: EntitySecurityTierFilter;
};
为了控制该过滤器,我们可以创建一个 React 组件,用于显示安全层级的复选框。 该组件将利用useEntityList钩子,该钩子接受该扩展过滤器类型作为非专利参数:
export const EntitySecurityTierPicker = () => {
  // The securityTiers key is recognized due to the CustomFilter generic
  const {
    filters: { securityTiers },
    updateFilters,
  } = useEntityList<CustomFilters>();
  // Toggles the value, depending on whether it's already selected
  function onChange(value: string) {
    const newTiers = securityTiers?.values.includes(value)
      ? securityTiers.values.filter(tier => tier !== value)
      : [...(securityTiers?.values ?? []), value];
    updateFilters({
      securityTiers: newTiers.length
        ? new EntitySecurityTierFilter(newTiers)
        : undefined,
    });
  }
  const tierOptions = ['1', '2', '3'];
  return (
    <FormControl component="fieldset">
      <Typography variant="button">Security Tier</Typography>
      <FormGroup>
        {tierOptions.map(tier => (
          <FormControlLabel
            key={tier}
            control={
              <Checkbox
                checked={securityTiers?.values.includes(tier)}
                onChange={() => onChange(tier)}
              />
            }
            label={`Tier ${tier}`}
          />
        ))}
      </FormGroup>
    </FormControl>
  );
};
现在我们可以将组件添加到CustomCatalogPage:
export const CustomCatalogPage = ({
  columns,
  actions,
  initiallySelectedFilter = 'owned',
}: CatalogPageProps) => {
  return (
    {/* ... */}
        <EntityListProvider>
          <CatalogFilterLayout>
            <CatalogFilterLayout.Filters>
              <EntityKindPicker initialFilter="component" hidden />
              <EntityTypePicker />
              <UserListPicker initialFilter={initiallySelectedFilter} />
              <EntitySecurityTierPicker />
              <EntityTagPicker />
            <CatalogFilterLayout.Filters>
            <CatalogFilterLayout.Content>
              <CatalogTable columns={columns} actions={actions} />
            </CatalogFilterLayout.Content>
          </CatalogFilterLayout>
        </EntityListProvider>
    {/* ... */}
};
最后,我们可以将新的CustomCatalogPage.
packages/app/src/App.tsx
const routes = (
  <FlatRoutes>
    <Navigate key="/" to="catalog" />
    <Route path="/catalog" element={<CatalogIndexPage />} />
    <Route path="/catalog" element={<CatalogIndexPage />}>
      <CustomCatalogPage />
    </Route>
    {/* ... */}
  </FlatRoutes>
);
同样的方法也可以用来定制_默认_在这种情况下,不需要使用通用参数,因为过滤器的形状与默认值相同。