Merge pull request #5578 from GunnerStraiker1/template-card-owner

Add Owner Field into TemplateCard and ownedBy & ownerOf relations for TemplateEntity
This commit is contained in:
Fredrik Adelöw
2021-05-20 11:46:44 +02:00
committed by GitHub
14 changed files with 176 additions and 7 deletions
@@ -21,6 +21,7 @@ import {
GroupEntity,
ResourceEntity,
SystemEntity,
TemplateEntity,
UserEntity,
} from '@backstage/catalog-model';
import { BuiltinKindsEntityProcessor } from './BuiltinKindsEntityProcessor';
@@ -520,5 +521,47 @@ describe('BuiltinKindsEntityProcessor', () => {
},
});
});
it('generates relations for template entities', async () => {
const entity: TemplateEntity = {
apiVersion: 'backstage.io/v1alpha1',
kind: 'Template',
metadata: { name: 'n' },
spec: {
schema: {
properties: {
description: {
title: 'd',
type: 'string',
description: 'des',
},
},
},
templater: 'cookiecutter',
path: '.',
type: 'service',
owner: 'o',
},
};
await processor.postProcessEntity(entity, location, emit);
expect(emit).toBeCalledTimes(2);
expect(emit).toBeCalledWith({
type: 'relation',
relation: {
source: { kind: 'Group', namespace: 'default', name: 'o' },
type: 'ownerOf',
target: { kind: 'Template', namespace: 'default', name: 'n' },
},
});
expect(emit).toBeCalledWith({
type: 'relation',
relation: {
source: { kind: 'Template', namespace: 'default', name: 'n' },
type: 'ownedBy',
target: { kind: 'Group', namespace: 'default', name: 'o' },
},
});
});
});
});
@@ -46,6 +46,7 @@ import {
resourceEntityV1alpha1Validator,
SystemEntity,
systemEntityV1alpha1Validator,
TemplateEntity,
templateEntityV1alpha1Validator,
templateEntityV1beta2Validator,
UserEntity,
@@ -131,6 +132,19 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor {
}
}
/*
* Emit relations for the Template kind
*/
if (entity.kind === 'Template') {
const template = entity as TemplateEntity;
doEmit(
template.spec.owner,
{ defaultKind: 'Group', defaultNamespace: selfRef.namespace },
RELATION_OWNED_BY,
RELATION_OWNER_OF,
);
}
/*
* Emit relations for the Component kind
*/
@@ -60,6 +60,7 @@ describe('JobProcessor', () => {
},
},
},
owner: 'example@email.com',
},
};
@@ -55,6 +55,7 @@ describe('Helpers', () => {
},
},
},
owner: 'team-d@example.com',
},
};
@@ -103,6 +104,7 @@ describe('Helpers', () => {
},
},
},
owner: 'team-b@example.com',
},
};
@@ -151,6 +153,7 @@ describe('Helpers', () => {
},
},
},
owner: 'team-a@example.com',
},
};
@@ -198,6 +201,7 @@ describe('Helpers', () => {
},
},
},
owner: 'team-b@example.com',
},
};
@@ -243,6 +247,7 @@ describe('Helpers', () => {
},
},
},
owner: 'team-c@example.com',
},
};
@@ -23,29 +23,48 @@ import {
CardMedia,
Chip,
makeStyles,
Typography,
useTheme,
} from '@material-ui/core';
import React from 'react';
import { generatePath } from 'react-router';
import { rootRouteRef } from '../../routes';
import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
import {
TemplateEntityV1alpha1,
Entity,
RELATION_OWNED_BY,
} from '@backstage/catalog-model';
import { FavouriteTemplate } from '../FavouriteTemplate/FavouriteTemplate';
import {
getEntityRelations,
EntityRefLinks,
} from '@backstage/plugin-catalog-react';
const useStyles = makeStyles({
const useStyles = makeStyles(theme => ({
cardHeader: {
position: 'relative',
},
title: {
backgroundImage: ({ backgroundImage }: any) => backgroundImage,
},
description: {
box: {
overflow: 'hidden',
textOverflow: 'ellipsis',
display: '-webkit-box',
'-webkit-line-clamp': 10,
'-webkit-box-orient': 'vertical',
paddingBottom: '0.8em',
},
});
label: {
color: theme.palette.text.secondary,
textTransform: 'uppercase',
fontSize: '0.65rem',
fontWeight: 'bold',
letterSpacing: 0.5,
lineHeight: 1,
paddingBottom: '0.2rem',
},
}));
export type TemplateCardProps = {
template: TemplateEntityV1alpha1;
@@ -76,7 +95,10 @@ export const TemplateCard = ({ template }: TemplateCardProps) => {
const backstageTheme = useTheme<BackstageTheme>();
const rootLink = useRouteRef(rootRouteRef);
const templateProps = getTemplateCardProps(template);
const ownedByRelations = getEntityRelations(
template as Entity,
RELATION_OWNED_BY,
);
const themeId = pageTheme[templateProps.type] ? templateProps.type : 'other';
const theme = backstageTheme.getPageTheme({ themeId });
const classes = useStyles({ backgroundImage: theme.backgroundImage });
@@ -94,13 +116,27 @@ export const TemplateCard = ({ template }: TemplateCardProps) => {
classes={{ root: classes.title }}
/>
</CardMedia>
<CardContent>
<CardContent style={{ display: 'grid' }}>
<Box className={classes.box}>
<Typography variant="body2" className={classes.label}>
Description
</Typography>
{templateProps.description}
</Box>
<Box className={classes.box}>
<Typography variant="body2" className={classes.label}>
Owner
</Typography>
<EntityRefLinks entityRefs={ownedByRelations} defaultKind="Group" />
</Box>
<Box>
<Typography variant="body2" className={classes.label}>
Tags
</Typography>
{templateProps.tags?.map(tag => (
<Chip size="small" label={tag} key={tag} />
))}
</Box>
<Box className={classes.description}>{templateProps.description}</Box>
</CardContent>
<CardActions>
<Button