list templates
This commit is contained in:
@@ -36,7 +36,7 @@ static_resources:
|
||||
route:
|
||||
cluster: inventory_service
|
||||
max_grpc_timeout: 0s
|
||||
- match: { prefix: '/spotify.backstage.scaffolder.v1.Scaffolder' }
|
||||
- match: { prefix: '/spotify.backstage.scaffolder.v1.Scaffolder/' }
|
||||
route:
|
||||
cluster: scaffolder_service
|
||||
max_grpc_timeout: 0s
|
||||
@@ -87,5 +87,5 @@ static_resources:
|
||||
lb_policy: round_robin
|
||||
hosts:
|
||||
- socket_address:
|
||||
address: identity
|
||||
address: scaffolder
|
||||
port_value: 50051
|
||||
|
||||
@@ -48,4 +48,7 @@ services:
|
||||
args:
|
||||
service: scaffolder
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./backend/scaffolder/templates:/app/templates
|
||||
|
||||
env_file: secrets.env
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
|
||||
// Shared MUI styles for a grid-based Card layout
|
||||
export const CardLayoutStyles = theme => ({
|
||||
container: {
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(auto-fill, 296px)',
|
||||
gridGap: theme.spacing(3),
|
||||
marginBottom: theme.spacing(6),
|
||||
},
|
||||
card: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
},
|
||||
cardActions: {
|
||||
flexGrow: '1',
|
||||
alignItems: 'flex-end',
|
||||
},
|
||||
});
|
||||
|
||||
export const useCardLayoutStyles = makeStyles(CardLayoutStyles);
|
||||
@@ -0,0 +1,67 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import TemplateCardMedia from './TemplateCardMedia';
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
CardActions,
|
||||
CardContent,
|
||||
Chip,
|
||||
Typography,
|
||||
withStyles,
|
||||
} from '@material-ui/core';
|
||||
import { Link } from '@material-ui/core';
|
||||
import { CardLayoutStyles } from './CardLayoutStyles';
|
||||
|
||||
const styles = theme => ({
|
||||
...CardLayoutStyles(theme),
|
||||
chip: {
|
||||
backgroundColor: theme.palette.gold,
|
||||
marginRight: 6,
|
||||
},
|
||||
});
|
||||
|
||||
export class TemplateCard extends Component {
|
||||
static propTypes = {
|
||||
isGoldenPath: PropTypes.bool,
|
||||
item: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
isGoldenPath: false,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { item, isGoldenPath, classes } = this.props;
|
||||
const isExperimental = item.lifecycle === 'experimental';
|
||||
// if (!item.owner) {
|
||||
// // If an item has no owner, it has most likely been unregistered from sysmodel. Should not crash the whole page.
|
||||
// return null;
|
||||
// }
|
||||
return (
|
||||
<Card key={item.id} className={classes.card}>
|
||||
<TemplateCardMedia name={item.name} />
|
||||
{item.description && (
|
||||
<CardContent>
|
||||
{isGoldenPath && (
|
||||
<Chip
|
||||
label="Golden Path"
|
||||
color="secondary"
|
||||
classes={{ root: classes.chip }}
|
||||
/>
|
||||
)}
|
||||
{isExperimental && <Chip label="Experimental" />}
|
||||
<Typography component="div">{item.description}</Typography>
|
||||
</CardContent>
|
||||
)}
|
||||
<CardActions className={classes.cardActions}>
|
||||
<Link to={item.link || `/create-component/${item.id}`}>
|
||||
<Button color="primary">{item.callToAction || 'Choose'}</Button>
|
||||
</Link>
|
||||
</CardActions>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(styles)(TemplateCard);
|
||||
@@ -0,0 +1,41 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Typography, withStyles } from '@material-ui/core';
|
||||
|
||||
const styles = theme => ({
|
||||
media: {
|
||||
color: theme.palette.bursts.fontColor,
|
||||
backgroundColor: theme.palette.bursts.backgroundColor.default,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'flex-start',
|
||||
padding: theme.spacing(2),
|
||||
minHeight: 120,
|
||||
position: 'relative',
|
||||
isolation: 'isolate',
|
||||
},
|
||||
title: {
|
||||
paddingTop: theme.spacing(1),
|
||||
paddingBottom: theme.spacing(1),
|
||||
lineHeight: 1,
|
||||
},
|
||||
slackChannel: {
|
||||
color: theme.palette.bursts.slackChannelText,
|
||||
},
|
||||
});
|
||||
|
||||
export class TemplateCardMedia extends Component {
|
||||
render() {
|
||||
const { classes, name, ownerName } = this.props;
|
||||
|
||||
return (
|
||||
<div className={classes.media}>
|
||||
<Typography color="inherit">{ownerName}</Typography>
|
||||
<Typography color="inherit" className={classes.title} variant="h6">
|
||||
{name}
|
||||
</Typography>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(styles)(TemplateCardMedia);
|
||||
@@ -0,0 +1,42 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withStyles } from '@material-ui/core';
|
||||
import TemplateCard from './TemplateCard';
|
||||
import { CardLayoutStyles } from './CardLayoutStyles';
|
||||
|
||||
export class TemplateList extends Component {
|
||||
static GOLDEN_PATH_TEMPLATE_IDS = [
|
||||
'simple-apollo-standalone',
|
||||
'scio-cookie',
|
||||
'react-skeleton',
|
||||
'science-box-cookie',
|
||||
];
|
||||
|
||||
static propTypes = {
|
||||
items: PropTypes.array.isRequired,
|
||||
};
|
||||
|
||||
static isGoldenPathItem(item) {
|
||||
return TemplateList.GOLDEN_PATH_TEMPLATE_IDS.includes(item.id);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { items, classes } = this.props;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div className={classes.container}>
|
||||
{items.map(item => (
|
||||
<TemplateCard
|
||||
key={item.id}
|
||||
item={item}
|
||||
isGoldenPath={TemplateList.isGoldenPathItem(item)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(CardLayoutStyles)(TemplateList);
|
||||
@@ -16,3 +16,4 @@ export { default as ProgressCard } from './components/ProgressCard';
|
||||
export { default as CircleProgress } from './components/CircleProgress';
|
||||
export { default as Progress } from './components/Progress';
|
||||
export { default as SortableTable } from './components/SortableTable';
|
||||
export { default as TemplateList } from '../src/components/TemplateList/TemplateList';
|
||||
|
||||
+19
-12
@@ -1,19 +1,26 @@
|
||||
import React, { FC, Fragment } from 'react';
|
||||
import { InfoCard } from '@backstage/core';
|
||||
import { IdentityClient, GetUserRequest } from "@backstage/protocol-definitions/generated/identity/v1/identity_pb_service";
|
||||
|
||||
const client = new IdentityClient("http://localhost:8080");
|
||||
const req = new GetUserRequest();
|
||||
req.setUsername("johndoe");
|
||||
client.getUser(req, (err, user) => {
|
||||
console.log(err);
|
||||
console.log(user);
|
||||
});
|
||||
import React, { FC, Fragment, useEffect, useState } from 'react';
|
||||
import { InfoCard, TemplateList } from '@backstage/core';
|
||||
import { scaffolderV1 } from '@backstage/protobuf-definitions';
|
||||
|
||||
const CreateEntityPage: FC<{}> = () => {
|
||||
const [templates, setTemplates] = useState<
|
||||
scaffolderV1.Template.AsObject[]
|
||||
>();
|
||||
|
||||
useEffect(() => {
|
||||
const client = new scaffolderV1.Client('http://localhost:8080');
|
||||
const req = new scaffolderV1.Empty();
|
||||
client.listTemplates(req).then((res: scaffolderV1.ListTemplatesReply) => {
|
||||
console.log(res.toObject().templatesList);
|
||||
setTemplates(res.toObject().templatesList);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<InfoCard title="Create New ..."></InfoCard>
|
||||
<InfoCard title="Create New ...">
|
||||
{templates && <TemplateList items={templates}></TemplateList>}
|
||||
</InfoCard>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15730,13 +15730,6 @@ ts-pnp@1.1.5, ts-pnp@^1.1.2:
|
||||
resolved "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.5.tgz#840e0739c89fce5f3abd9037bb091dbff16d9dec"
|
||||
integrity sha512-ti7OGMOUOzo66wLF3liskw6YQIaSsBgc4GOAlWRnIEj8htCxJUxskanMUoJOD6MDCRAXo36goXJZch+nOS0VMA==
|
||||
|
||||
ts-protoc-gen@^0.12.0:
|
||||
version "0.12.0"
|
||||
resolved "https://registry.npmjs.org/ts-protoc-gen/-/ts-protoc-gen-0.12.0.tgz#932e5738f14b67e7202825b06f8c548cb7d8ef34"
|
||||
integrity sha512-V7jnICJxKqalBrnJSMTW5tB9sGi48gOC325bfcM7TDNUItVOlaMM//rQmuo49ybipk/SyJTnWXgtJnhHCevNJw==
|
||||
dependencies:
|
||||
google-protobuf "^3.6.1"
|
||||
|
||||
tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
|
||||
|
||||
Reference in New Issue
Block a user