+
+ e.metadata.name === 't1'}
+ TemplateCardComponent={TemplateCardComponent}
+ />
+
+ ,
+ { mountedRoutes: { '/': rootRouteRef } },
+ );
+
+ expect(() => screen.getByTestId('t1')).toThrow();
+ expect(screen.getByTestId('t2')).toBeDefined();
+ });
+});
diff --git a/plugins/scaffolder/src/components/TemplateList/TemplateList.tsx b/plugins/scaffolder/src/components/TemplateList/TemplateList.tsx
index 90d1c8cceb..9aa0ec5eef 100644
--- a/plugins/scaffolder/src/components/TemplateList/TemplateList.tsx
+++ b/plugins/scaffolder/src/components/TemplateList/TemplateList.tsx
@@ -28,6 +28,7 @@ import {
import { useEntityList } from '@backstage/plugin-catalog-react';
import { Typography } from '@material-ui/core';
import { TemplateCard } from '../TemplateCard';
+import { isTemplateEntity } from '../../lib/isTemplateEntity';
/**
* @internal
@@ -38,8 +39,9 @@ export type TemplateListProps = {
| undefined;
group?: {
title?: React.ReactNode;
- filter: (entity: Entity) => boolean;
+ filter: (entity: TemplateEntityV1beta3) => boolean;
};
+ templateFilter?: (entity: TemplateEntityV1beta3) => boolean;
};
/**
@@ -48,12 +50,14 @@ export type TemplateListProps = {
export const TemplateList = ({
TemplateCardComponent,
group,
+ templateFilter,
}: TemplateListProps) => {
const { loading, error, entities } = useEntityList();
const Card = TemplateCardComponent || TemplateCard;
- const maybeFilteredEntities = group
- ? entities.filter(e => group.filter(e))
- : entities;
+ const templateEntities = entities.filter(isTemplateEntity);
+ const maybeFilteredEntities = (
+ group ? templateEntities.filter(group.filter) : templateEntities
+ ).filter(e => (templateFilter ? !templateFilter(e) : true));
const titleComponent: React.ReactNode = (() => {
if (group && group.title) {
diff --git a/plugins/scaffolder/src/lib/isTemplateEntity.ts b/plugins/scaffolder/src/lib/isTemplateEntity.ts
new file mode 100644
index 0000000000..61ceabaa53
--- /dev/null
+++ b/plugins/scaffolder/src/lib/isTemplateEntity.ts
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2023 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 { Entity } from '@backstage/catalog-model';
+import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';
+
+export const isTemplateEntity = (
+ entity: Entity,
+): entity is TemplateEntityV1beta3 =>
+ entity.apiVersion === 'scaffolder.backstage.io/v1beta3' &&
+ entity.kind === 'Template';
diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx
index 5066e96d6c..75d87602e4 100644
--- a/plugins/scaffolder/src/next/Router/Router.tsx
+++ b/plugins/scaffolder/src/next/Router/Router.tsx
@@ -29,7 +29,7 @@ import {
} from '@backstage/plugin-scaffolder-react';
import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';
-import { TemplateGroupFilter } from '../TemplateListPage/TemplateGroups';
+import { TemplateGroupFilter } from '../TemplateListPage';
import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default';
import {
@@ -61,6 +61,7 @@ export type NextRouterProps = {
}>;
};
groups?: TemplateGroupFilter[];
+ templateFilter?: (entity: TemplateEntityV1beta3) => boolean;
// todo(blam): rename this to formProps
FormProps?: FormProps;
contextMenu?: {
@@ -111,6 +112,7 @@ export const Router = (props: PropsWithChildren