feat(scaffolder): use swr, pretty template mocks, move out grid item
This commit is contained in:
@@ -4,7 +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: '.'
|
||||
|
||||
|
||||
@@ -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: '.'
|
||||
@@ -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
|
||||
|
||||
@@ -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.9",
|
||||
|
||||
@@ -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 (
|
||||
<Page theme={pageTheme.home}>
|
||||
@@ -89,23 +90,26 @@ const ScaffolderPage: React.FC<{}> = () => {
|
||||
</Link>
|
||||
.
|
||||
</Typography>
|
||||
{loading ? (
|
||||
<LinearProgress />
|
||||
) : (
|
||||
<Grid container>
|
||||
{value!.map(item => {
|
||||
{isValidating && <LinearProgress />}
|
||||
<Grid container>
|
||||
{templates &&
|
||||
templates.map(template => {
|
||||
return (
|
||||
<TemplateCard
|
||||
key={item.id}
|
||||
title={item.name}
|
||||
type={item.type}
|
||||
description={item.description}
|
||||
tags={item.tags}
|
||||
/>
|
||||
<Grid item xs={12} sm={6} md={3}>
|
||||
<TemplateCard
|
||||
key={template.metadata.uid}
|
||||
title={`${
|
||||
(template.metadata.title || template.metadata.name) ?? ''
|
||||
}`}
|
||||
type={template.spec.type ?? ''}
|
||||
description={template.metadata.description ?? '-'}
|
||||
// TODO(shmidt-i): how to store tags
|
||||
tags={template.metadata.annotations?.tags.split(',') ?? []}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</Content>
|
||||
</Page>
|
||||
);
|
||||
|
||||
@@ -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<TemplateCardProps> = ({
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<Grid item xs={12} sm={6} md={3}>
|
||||
<Card>
|
||||
<div className={classes.header}>
|
||||
<Typography variant="subtitle2">{type}</Typography>
|
||||
<Typography variant="h6">{title}</Typography>
|
||||
<Card>
|
||||
<div className={classes.header}>
|
||||
<Typography variant="subtitle2">{type}</Typography>
|
||||
<Typography variant="h6">{title}</Typography>
|
||||
</div>
|
||||
<div className={classes.content}>
|
||||
{tags?.map(tag => (
|
||||
<Chip label={tag} key={tag} />
|
||||
))}
|
||||
<Typography variant="body2" paragraph className={classes.description}>
|
||||
{description}
|
||||
</Typography>
|
||||
<div className={classes.footer}>
|
||||
<Button color="primary">Choose</Button>
|
||||
</div>
|
||||
<div className={classes.content}>
|
||||
{tags?.map(tag => (
|
||||
<Chip label={tag} key={tag} />
|
||||
))}
|
||||
<Typography variant="body2" paragraph className={classes.description}>
|
||||
{description}
|
||||
</Typography>
|
||||
<div className={classes.footer}>
|
||||
<Button color="primary">Choose</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</Grid>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user