diff --git a/.changeset/fast-bears-lick.md b/.changeset/fast-bears-lick.md
new file mode 100644
index 0000000000..8e0dc8e60b
--- /dev/null
+++ b/.changeset/fast-bears-lick.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog': patch
+---
+
+Migrate catalog entity cards to new frontend system extension format.
diff --git a/plugins/catalog/src/alpha/apis.tsx b/plugins/catalog/src/alpha/apis.tsx
new file mode 100644
index 0000000000..a887a33a04
--- /dev/null
+++ b/plugins/catalog/src/alpha/apis.tsx
@@ -0,0 +1,51 @@
+/*
+ * 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 {
+ createApiFactory,
+ discoveryApiRef,
+ fetchApiRef,
+ storageApiRef,
+} from '@backstage/core-plugin-api';
+import { CatalogClient } from '@backstage/catalog-client';
+import { createApiExtension } from '@backstage/frontend-plugin-api';
+import {
+ catalogApiRef,
+ starredEntitiesApiRef,
+} from '@backstage/plugin-catalog-react';
+import { DefaultStarredEntitiesApi } from '../apis';
+
+export const CatalogApi = createApiExtension({
+ factory: createApiFactory({
+ api: catalogApiRef,
+ deps: {
+ discoveryApi: discoveryApiRef,
+ fetchApi: fetchApiRef,
+ },
+ factory: ({ discoveryApi, fetchApi }) =>
+ new CatalogClient({ discoveryApi, fetchApi }),
+ }),
+});
+
+export const StarredEntitiesApi = createApiExtension({
+ factory: createApiFactory({
+ api: starredEntitiesApiRef,
+ deps: { storageApi: storageApiRef },
+ factory: ({ storageApi }) => new DefaultStarredEntitiesApi({ storageApi }),
+ }),
+});
+
+export default [CatalogApi, StarredEntitiesApi];
diff --git a/plugins/catalog/src/alpha/entityCards.tsx b/plugins/catalog/src/alpha/entityCards.tsx
new file mode 100644
index 0000000000..cc30928fcf
--- /dev/null
+++ b/plugins/catalog/src/alpha/entityCards.tsx
@@ -0,0 +1,102 @@
+/*
+ * 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 React from 'react';
+import { createEntityCardExtension } from '@backstage/plugin-catalog-react/alpha';
+
+export const EntityAboutCard = createEntityCardExtension({
+ id: 'about',
+ loader: async () =>
+ import('../components/AboutCard').then(m => (
+
+ )),
+});
+
+export const EntityLinksCard = createEntityCardExtension({
+ id: 'links',
+ loader: async () =>
+ import('../components/EntityLinksCard').then(m => {
+ return ;
+ }),
+});
+
+export const EntityLabelsCard = createEntityCardExtension({
+ id: 'labels',
+ loader: async () =>
+ import('../components/EntityLabelsCard').then(m => (
+
+ )),
+});
+
+export const EntityDependsOnComponentsCard = createEntityCardExtension({
+ id: 'dependsOn.components',
+ loader: async () =>
+ import('../components/DependsOnComponentsCard').then(m => (
+
+ )),
+});
+
+export const EntityDependsOnResourcesCard = createEntityCardExtension({
+ id: 'dependsOn.resources',
+ loader: async () =>
+ import('../components/DependsOnResourcesCard').then(m => (
+
+ )),
+});
+
+export const EntityHasComponentsCard = createEntityCardExtension({
+ id: 'has.components',
+ loader: async () =>
+ import('../components/HasComponentsCard').then(m => (
+
+ )),
+});
+
+export const EntityHasResourcesCard = createEntityCardExtension({
+ id: 'has.resources',
+ loader: async () =>
+ import('../components/HasResourcesCard').then(m => (
+
+ )),
+});
+
+export const EntityHasSubcomponentsCard = createEntityCardExtension({
+ id: 'has.subcomponents',
+ loader: async () =>
+ import('../components/HasSubcomponentsCard').then(m => (
+
+ )),
+});
+
+export const EntityHasSystemsCard = createEntityCardExtension({
+ id: 'has.systems',
+ loader: async () =>
+ import('../components/HasSystemsCard').then(m => (
+
+ )),
+});
+
+export default [
+ EntityAboutCard,
+ EntityLinksCard,
+ EntityLabelsCard,
+ EntityDependsOnComponentsCard,
+ EntityDependsOnResourcesCard,
+ EntityHasComponentsCard,
+ EntityHasResourcesCard,
+ EntityHasSubcomponentsCard,
+ EntityHasSystemsCard,
+];
diff --git a/plugins/catalog/src/alpha/entityContents.tsx b/plugins/catalog/src/alpha/entityContents.tsx
new file mode 100644
index 0000000000..0e26373b5e
--- /dev/null
+++ b/plugins/catalog/src/alpha/entityContents.tsx
@@ -0,0 +1,46 @@
+/*
+ * 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 React from 'react';
+import { Grid } from '@material-ui/core';
+import {
+ coreExtensionData,
+ createExtensionInput,
+} from '@backstage/frontend-plugin-api';
+import { createEntityContentExtension } from '@backstage/plugin-catalog-react/alpha';
+
+export const OverviewEntityContent = createEntityContentExtension({
+ id: 'overview',
+ defaultPath: '/',
+ defaultTitle: 'Overview',
+ disabled: false,
+ inputs: {
+ cards: createExtensionInput({
+ element: coreExtensionData.reactElement,
+ }),
+ },
+ loader: async ({ inputs }) => (
+
+ {inputs.cards.map(card => (
+
+ {card.element}
+
+ ))}
+
+ ),
+});
+
+export default [OverviewEntityContent];
diff --git a/plugins/catalog/src/alpha/builtInFilterExtensions.tsx b/plugins/catalog/src/alpha/filters.tsx
similarity index 98%
rename from plugins/catalog/src/alpha/builtInFilterExtensions.tsx
rename to plugins/catalog/src/alpha/filters.tsx
index 5a7575c4f5..7b73c2d14b 100644
--- a/plugins/catalog/src/alpha/builtInFilterExtensions.tsx
+++ b/plugins/catalog/src/alpha/filters.tsx
@@ -109,7 +109,7 @@ const CatalogUserListFilter = createCatalogFilterExtension({
},
});
-export const builtInFilterExtensions = [
+export default [
CatalogEntityTagFilter,
CatalogEntityKindFilter,
CatalogEntityTypeFilter,
diff --git a/plugins/catalog/src/alpha/navItems.tsx b/plugins/catalog/src/alpha/navItems.tsx
new file mode 100644
index 0000000000..b6481fd764
--- /dev/null
+++ b/plugins/catalog/src/alpha/navItems.tsx
@@ -0,0 +1,29 @@
+/*
+ * 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 HomeIcon from '@material-ui/icons/Home';
+import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha';
+import { createNavItemExtension } from '@backstage/frontend-plugin-api';
+import { rootRouteRef } from '../routes';
+
+export const CatalogIndexNavItem = createNavItemExtension({
+ id: 'catalog.nav.index',
+ routeRef: convertLegacyRouteRef(rootRouteRef),
+ title: 'Catalog',
+ icon: HomeIcon,
+});
+
+export default [CatalogIndexNavItem];
diff --git a/plugins/catalog/src/alpha/pages.tsx b/plugins/catalog/src/alpha/pages.tsx
new file mode 100644
index 0000000000..6270ae777d
--- /dev/null
+++ b/plugins/catalog/src/alpha/pages.tsx
@@ -0,0 +1,83 @@
+/*
+ * 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 React from 'react';
+import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha';
+import {
+ createPageExtension,
+ coreExtensionData,
+ createExtensionInput,
+} from '@backstage/frontend-plugin-api';
+import {
+ AsyncEntityProvider,
+ entityRouteRef,
+} from '@backstage/plugin-catalog-react';
+import { entityContentTitleExtensionDataRef } from '@backstage/plugin-catalog-react/alpha';
+import { rootRouteRef } from '../routes';
+import { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl';
+
+export const CatalogIndexPage = createPageExtension({
+ id: 'plugin.catalog.page.index',
+ defaultPath: '/catalog',
+ routeRef: convertLegacyRouteRef(rootRouteRef),
+ inputs: {
+ filters: createExtensionInput({
+ element: coreExtensionData.reactElement,
+ }),
+ },
+ loader: async ({ inputs }) => {
+ const { BaseCatalogPage } = await import('../components/CatalogPage');
+ const filters = inputs.filters.map(filter => filter.element);
+ return {filters}>} />;
+ },
+});
+
+export const CatalogEntityPage = createPageExtension({
+ id: 'plugin.catalog.page.entity',
+ defaultPath: '/catalog/:namespace/:kind/:name',
+ routeRef: convertLegacyRouteRef(entityRouteRef),
+ inputs: {
+ contents: createExtensionInput({
+ element: coreExtensionData.reactElement,
+ path: coreExtensionData.routePath,
+ routeRef: coreExtensionData.routeRef.optional(),
+ title: entityContentTitleExtensionDataRef,
+ }),
+ },
+ loader: async ({ inputs }) => {
+ const { EntityLayout } = await import('../components/EntityLayout');
+ const Component = () => {
+ return (
+
+
+ {inputs.contents.map(content => (
+
+ {content.element}
+
+ ))}
+
+
+ );
+ };
+ return ;
+ },
+});
+
+export default [CatalogIndexPage, CatalogEntityPage];
diff --git a/plugins/catalog/src/alpha/plugin.tsx b/plugins/catalog/src/alpha/plugin.tsx
index d9d2878213..2f019ca33e 100644
--- a/plugins/catalog/src/alpha/plugin.tsx
+++ b/plugins/catalog/src/alpha/plugin.tsx
@@ -14,166 +14,25 @@
* limitations under the License.
*/
-import React from 'react';
-import HomeIcon from '@material-ui/icons/Home';
-import {
- createApiFactory,
- discoveryApiRef,
- fetchApiRef,
- storageApiRef,
-} from '@backstage/core-plugin-api';
import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha';
-import { CatalogClient } from '@backstage/catalog-client';
-import {
- createApiExtension,
- createPageExtension,
- createPlugin,
- createNavItemExtension,
- coreExtensionData,
- createExtensionInput,
-} from '@backstage/frontend-plugin-api';
-import {
- AsyncEntityProvider,
- catalogApiRef,
- entityRouteRef,
- starredEntitiesApiRef,
-} from '@backstage/plugin-catalog-react';
-import {
- createEntityContentExtension,
- createEntityCardExtension,
- entityContentTitleExtensionDataRef,
-} from '@backstage/plugin-catalog-react/alpha';
-import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha';
-import { DefaultStarredEntitiesApi } from '../apis';
+import { createPlugin } from '@backstage/frontend-plugin-api';
+
+import { entityRouteRef } from '@backstage/plugin-catalog-react';
+
import {
createComponentRouteRef,
createFromTemplateRouteRef,
rootRouteRef,
viewTechDocRouteRef,
} from '../routes';
-import { builtInFilterExtensions } from './builtInFilterExtensions';
-import { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl';
-import Grid from '@material-ui/core/Grid';
-/** @alpha */
-export const CatalogApi = createApiExtension({
- factory: createApiFactory({
- api: catalogApiRef,
- deps: {
- discoveryApi: discoveryApiRef,
- fetchApi: fetchApiRef,
- },
- factory: ({ discoveryApi, fetchApi }) =>
- new CatalogClient({ discoveryApi, fetchApi }),
- }),
-});
-
-/** @alpha */
-export const StarredEntitiesApi = createApiExtension({
- factory: createApiFactory({
- api: starredEntitiesApiRef,
- deps: { storageApi: storageApiRef },
- factory: ({ storageApi }) => new DefaultStarredEntitiesApi({ storageApi }),
- }),
-});
-
-/** @alpha */
-export const CatalogSearchResultListItemExtension =
- createSearchResultListItemExtension({
- id: 'catalog',
- predicate: result => result.type === 'software-catalog',
- component: () =>
- import('../components/CatalogSearchResultListItem').then(
- m => m.CatalogSearchResultListItem,
- ),
- });
-
-const CatalogIndexPage = createPageExtension({
- id: 'plugin.catalog.page.index',
- defaultPath: '/catalog',
- routeRef: convertLegacyRouteRef(rootRouteRef),
- inputs: {
- filters: createExtensionInput({
- element: coreExtensionData.reactElement,
- }),
- },
- loader: async ({ inputs }) => {
- const { BaseCatalogPage } = await import('../components/CatalogPage');
- const filters = inputs.filters.map(filter => filter.element);
- return {filters}>} />;
- },
-});
-
-const CatalogEntityPage = createPageExtension({
- id: 'plugin.catalog.page.entity',
- defaultPath: '/catalog/:namespace/:kind/:name',
- routeRef: convertLegacyRouteRef(entityRouteRef),
- inputs: {
- contents: createExtensionInput({
- element: coreExtensionData.reactElement,
- path: coreExtensionData.routePath,
- routeRef: coreExtensionData.routeRef.optional(),
- title: entityContentTitleExtensionDataRef,
- }),
- },
- loader: async ({ inputs }) => {
- const { EntityLayout } = await import('../components/EntityLayout');
- const Component = () => {
- return (
-
-
- {inputs.contents.map(content => (
-
- {content.element}
-
- ))}
-
-
- );
- };
- return ;
- },
-});
-
-const EntityAboutCard = createEntityCardExtension({
- id: 'about',
- loader: async () =>
- import('../components/AboutCard').then(m => (
-
- )),
-});
-
-const OverviewEntityContent = createEntityContentExtension({
- id: 'overview',
- defaultPath: '/',
- defaultTitle: 'Overview',
- disabled: false,
- inputs: {
- cards: createExtensionInput({
- element: coreExtensionData.reactElement,
- }),
- },
- loader: async ({ inputs }) => (
-
- {inputs.cards.map(card => (
-
- {card.element}
-
- ))}
-
- ),
-});
-
-const CatalogNavItem = createNavItemExtension({
- id: 'catalog.nav.index',
- routeRef: convertLegacyRouteRef(rootRouteRef),
- title: 'Catalog',
- icon: HomeIcon,
-});
+import apis from './apis';
+import pages from './pages';
+import filters from './filters';
+import navItems from './navItems';
+import entityCards from './entityCards';
+import entityContents from './entityContents';
+import searchResultItems from './searchResultItems';
/** @alpha */
export default createPlugin({
@@ -188,14 +47,12 @@ export default createPlugin({
createFromTemplate: convertLegacyRouteRef(createFromTemplateRouteRef),
},
extensions: [
- CatalogApi,
- StarredEntitiesApi,
- CatalogSearchResultListItemExtension,
- CatalogIndexPage,
- CatalogEntityPage,
- CatalogNavItem,
- OverviewEntityContent,
- EntityAboutCard,
- ...builtInFilterExtensions,
+ ...apis,
+ ...pages,
+ ...filters,
+ ...navItems,
+ ...entityCards,
+ ...entityContents,
+ ...searchResultItems,
],
});
diff --git a/plugins/catalog/src/alpha/searchResultItems.tsx b/plugins/catalog/src/alpha/searchResultItems.tsx
new file mode 100644
index 0000000000..f677869136
--- /dev/null
+++ b/plugins/catalog/src/alpha/searchResultItems.tsx
@@ -0,0 +1,29 @@
+/*
+ * 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 { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha';
+
+export const CatalogSearchResultListItemExtension =
+ createSearchResultListItemExtension({
+ id: 'catalog',
+ predicate: result => result.type === 'software-catalog',
+ component: () =>
+ import('../components/CatalogSearchResultListItem').then(
+ m => m.CatalogSearchResultListItem,
+ ),
+ });
+
+export default [CatalogSearchResultListItemExtension];