diff --git a/.changeset/chatty-seals-tap.md b/.changeset/chatty-seals-tap.md
new file mode 100644
index 0000000000..384a89e6ce
--- /dev/null
+++ b/.changeset/chatty-seals-tap.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-catalog': patch
+'example-app': patch
+---
+
+Add link from Template entity to the scaffolder launch page for the template in the AboutCard.
diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx
index bc9eac8c64..0efcafba26 100644
--- a/packages/app/src/App.tsx
+++ b/packages/app/src/App.tsx
@@ -142,6 +142,7 @@ const app = createApp({
bind(catalogPlugin.externalRoutes, {
createComponent: scaffolderPlugin.routes.root,
viewTechDoc: techdocsPlugin.routes.docRoot,
+ selectedTemplateRoute: scaffolderPlugin.routes.selectedTemplate,
});
bind(apiDocsPlugin.externalRoutes, {
registerApi: catalogImportPlugin.routes.importPage,
diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json
index 21983f762e..16176b9662 100644
--- a/plugins/catalog/package.json
+++ b/plugins/catalog/package.json
@@ -40,6 +40,7 @@
"@backstage/integration-react": "workspace:^",
"@backstage/plugin-catalog-common": "workspace:^",
"@backstage/plugin-catalog-react": "workspace:^",
+ "@backstage/plugin-scaffolder-common": "workspace:^",
"@backstage/plugin-search-common": "workspace:^",
"@backstage/plugin-search-react": "workspace:^",
"@backstage/theme": "workspace:^",
diff --git a/plugins/catalog/src/components/AboutCard/AboutCard.tsx b/plugins/catalog/src/components/AboutCard/AboutCard.tsx
index cb48be2b26..4be201b555 100644
--- a/plugins/catalog/src/components/AboutCard/AboutCard.tsx
+++ b/plugins/catalog/src/components/AboutCard/AboutCard.tsx
@@ -49,12 +49,14 @@ import {
IconButton,
makeStyles,
} from '@material-ui/core';
+import AddIcon from '@material-ui/icons/Add';
import CachedIcon from '@material-ui/icons/Cached';
import DocsIcon from '@material-ui/icons/Description';
import EditIcon from '@material-ui/icons/Edit';
import React, { useCallback } from 'react';
-import { viewTechDocRouteRef } from '../../routes';
+import { selectedTemplateRouteRef, viewTechDocRouteRef } from '../../routes';
import { AboutContent } from './AboutContent';
+import { isTemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';
const useStyles = makeStyles({
gridItemCard: {
@@ -97,6 +99,7 @@ export function AboutCard(props: AboutCardProps) {
const alertApi = useApi(alertApiRef);
const errorApi = useApi(errorApiRef);
const viewTechdocLink = useRouteRef(viewTechDocRouteRef);
+ const templateRoute = useRouteRef(selectedTemplateRouteRef);
const entitySourceLocation = getEntitySourceLocation(
entity,
@@ -126,6 +129,23 @@ export function AboutCard(props: AboutCardProps) {
}),
};
+ const subHeaderLinks = [viewInSource, viewInTechDocs];
+
+ if (isTemplateEntityV1beta3(entity)) {
+ const launchTemplate: IconLinkVerticalProps = {
+ label: 'Launch Template',
+ icon: ,
+ href:
+ templateRoute &&
+ templateRoute({
+ templateName: entity.metadata.name,
+ namespace: entity.metadata.namespace || DEFAULT_NAMESPACE,
+ }),
+ };
+
+ subHeaderLinks.push(launchTemplate);
+ }
+
let cardClass = '';
if (variant === 'gridItem') {
cardClass = classes.gridItemCard;
@@ -179,7 +199,7 @@ export function AboutCard(props: AboutCardProps) {
>
}
- subheader={}
+ subheader={}
/>
diff --git a/plugins/catalog/src/plugin.ts b/plugins/catalog/src/plugin.ts
index ea6ddcaff2..22c85a755d 100644
--- a/plugins/catalog/src/plugin.ts
+++ b/plugins/catalog/src/plugin.ts
@@ -21,7 +21,11 @@ import {
entityRouteRef,
starredEntitiesApiRef,
} from '@backstage/plugin-catalog-react';
-import { createComponentRouteRef, viewTechDocRouteRef } from './routes';
+import {
+ createComponentRouteRef,
+ selectedTemplateRouteRef,
+ viewTechDocRouteRef,
+} from './routes';
import {
createApiFactory,
createComponentExtension,
@@ -77,6 +81,7 @@ export const catalogPlugin = createPlugin({
externalRoutes: {
createComponent: createComponentRouteRef,
viewTechDoc: viewTechDocRouteRef,
+ selectedTemplateRoute: selectedTemplateRouteRef,
},
__experimentalConfigure(
options?: CatalogInputPluginOptions,
diff --git a/plugins/catalog/src/routes.ts b/plugins/catalog/src/routes.ts
index 5c0d195d74..2d9667d8e2 100644
--- a/plugins/catalog/src/routes.ts
+++ b/plugins/catalog/src/routes.ts
@@ -30,6 +30,12 @@ export const viewTechDocRouteRef = createExternalRouteRef({
params: ['namespace', 'kind', 'name'],
});
+export const selectedTemplateRouteRef = createExternalRouteRef({
+ id: 'selected-template',
+ optional: true,
+ params: ['namespace', 'templateName'],
+});
+
export const rootRouteRef = createRouteRef({
id: 'catalog',
});
diff --git a/yarn.lock b/yarn.lock
index 2e6f814cf5..6ce19fdede 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5739,6 +5739,7 @@ __metadata:
"@backstage/plugin-catalog-common": "workspace:^"
"@backstage/plugin-catalog-react": "workspace:^"
"@backstage/plugin-permission-react": "workspace:^"
+ "@backstage/plugin-scaffolder-common": "workspace:^"
"@backstage/plugin-search-common": "workspace:^"
"@backstage/plugin-search-react": "workspace:^"
"@backstage/test-utils": "workspace:^"