diff --git a/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml b/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml
index 6834f0d1b6..058e2a715f 100644
--- a/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml
+++ b/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml
@@ -4,6 +4,9 @@ metadata:
name: react-ssr-template
title: React SSR Template
description: Next.js application skeleton for creating isomorphic web applications.
+ annotations:
+ tags: Recommended,React
spec:
- type: cookiecutter
+ processor: cookiecutter
+ type: website
path: '.'
diff --git a/plugins/scaffolder-backend/sample-templates/springboot-template/template.yaml b/plugins/scaffolder-backend/sample-templates/springboot-template/template.yaml
new file mode 100644
index 0000000000..d44d926ef4
--- /dev/null
+++ b/plugins/scaffolder-backend/sample-templates/springboot-template/template.yaml
@@ -0,0 +1,12 @@
+apiVersion: backstage.io/v1alpha1
+kind: Template
+metadata:
+ name: springboot-template
+ title: Spring Boot Service
+ description: Standard Spring Boot (Java) microservice with recommended configuration.
+ annotations:
+ tags: Recommended,Java
+spec:
+ processor: cookiecutter
+ type: service
+ path: '.'
diff --git a/plugins/scaffolder-backend/scripts/mock-data b/plugins/scaffolder-backend/scripts/mock-data
index be3fa2b6cf..594bd76607 100755
--- a/plugins/scaffolder-backend/scripts/mock-data
+++ b/plugins/scaffolder-backend/scripts/mock-data
@@ -1,8 +1,12 @@
#!/usr/bin/env bash
-curl \
---location \
---request POST 'localhost:7000/catalog/locations' \
---header 'Content-Type: application/json' \
---data-raw "{\"type\": \"file\", \"target\": \"$(pwd)/sample-templates/react-ssr-template/template.yaml\"}"
-
+for URL in \
+ 'react-ssr-template' \
+ 'springboot-template' \
+; do \
+ curl \
+ --location \
+ --request POST 'localhost:7000/catalog/locations' \
+ --header 'Content-Type: application/json' \
+ --data-raw "{\"type\": \"file\", \"target\": \"$(pwd)/sample-templates/${URL}/template.yaml\"}"
+done
diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json
index 3883dfb972..6bd312921e 100644
--- a/plugins/scaffolder/package.json
+++ b/plugins/scaffolder/package.json
@@ -31,7 +31,8 @@
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router-dom": "6.0.0-alpha.5",
- "react-use": "^14.2.0"
+ "react-use": "^14.2.0",
+ "swr": "^0.2.2"
},
"devDependencies": {
"@backstage/cli": "^0.1.1-alpha.12",
diff --git a/plugins/scaffolder/src/components/ScaffolderPage/index.tsx b/plugins/scaffolder/src/components/ScaffolderPage/index.tsx
index 1dbd993d93..a6dbac8f83 100644
--- a/plugins/scaffolder/src/components/ScaffolderPage/index.tsx
+++ b/plugins/scaffolder/src/components/ScaffolderPage/index.tsx
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import React from 'react';
+import React, { useEffect } from 'react';
import {
Lifecycle,
Content,
@@ -24,6 +24,7 @@ import {
Page,
pageTheme,
useApi,
+ errorApiRef,
} from '@backstage/core';
import { catalogApiRef } from '@backstage/plugin-catalog';
import {
@@ -35,25 +36,25 @@ import {
} from '@material-ui/core';
import { Link as RouterLink } from 'react-router-dom';
import TemplateCard from '../TemplateCard';
-import { useAsync } from 'react-use';
+import useStaleWhileRevalidate from 'swr';
import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
const ScaffolderPage: React.FC<{}> = () => {
const catalogApi = useApi(catalogApiRef);
+ const errorApi = useApi(errorApiRef);
- const { value, loading } = useAsync(async () => {
- const entities = await catalogApi.getEntities({ kind: 'Template' });
- return (entities as TemplateEntityV1alpha1[]).map(template => ({
- id: template.metadata.uid,
- type: template.spec.type,
- name: template.metadata.name,
- // TODO(shmidt-i): decide on tags
- tags: ['not-implemented'],
- description: template.metadata.description ?? '-',
- // TODO(shmidt-i): decide on owner
- ownerId: '-',
- }));
- });
+ const { data: templates, isValidating, error } = useStaleWhileRevalidate(
+ 'templates/all',
+ async () =>
+ catalogApi.getEntities({ kind: 'Template' }) as Promise<
+ TemplateEntityV1alpha1[]
+ >,
+ );
+
+ useEffect(() => {
+ if (!error) return;
+ errorApi.post(error);
+ }, [error, errorApi]);
return (
@@ -89,23 +90,26 @@ const ScaffolderPage: React.FC<{}> = () => {
.
- {loading ? (
-
- ) : (
-
- {value!.map(item => {
+ {isValidating && }
+
+ {templates &&
+ templates.map(template => {
return (
-
+
+
+
);
})}
-
- )}
+
);
diff --git a/plugins/scaffolder/src/components/TemplateCard.tsx b/plugins/scaffolder/src/components/TemplateCard.tsx
index 618eda64f1..6d47f05693 100644
--- a/plugins/scaffolder/src/components/TemplateCard.tsx
+++ b/plugins/scaffolder/src/components/TemplateCard.tsx
@@ -14,14 +14,7 @@
* limitations under the License.
*/
import React, { FC } from 'react';
-import {
- Button,
- Card,
- Chip,
- Grid,
- Typography,
- makeStyles,
-} from '@material-ui/core';
+import { Button, Card, Chip, Typography, makeStyles } from '@material-ui/core';
const useStyles = makeStyles(theme => ({
header: {
@@ -59,25 +52,23 @@ const TemplateCard: FC = ({
const classes = useStyles();
return (
-
-
-
-
{type}
-
{title}
+
+
+ {type}
+ {title}
+
+
+ {tags?.map(tag => (
+
+ ))}
+
+ {description}
+
+
+
-
- {tags?.map(tag => (
-
- ))}
-
- {description}
-
-
-
-
-
-
-
+
+
);
};