Display the owner and system as links to the entity pages in the about card

This commit is contained in:
Oliver Sand
2021-01-15 11:13:58 +01:00
parent b55f27dcc5
commit 33846acfcb
5 changed files with 206 additions and 19 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog': patch
---
Display the owner and system as links to the entity pages in the about card.
@@ -14,15 +14,16 @@
* limitations under the License.
*/
import React from 'react';
import { Grid, Typography, Chip, makeStyles } from '@material-ui/core';
import { AboutField } from './AboutField';
import {
Entity,
ENTITY_DEFAULT_NAMESPACE,
RELATION_OWNED_BY,
serializeEntityRef,
RELATION_PART_OF,
} from '@backstage/catalog-model';
import { Chip, Grid, makeStyles, Typography } from '@material-ui/core';
import React from 'react';
import { EntityRefLink } from '../EntityRefLink';
import { getEntityRelations } from '../getEntityRelations';
import { AboutField } from './AboutField';
const useStyles = makeStyles({
description: {
@@ -36,6 +37,11 @@ type Props = {
export const AboutContent = ({ entity }: Props) => {
const classes = useStyles();
const [partOfSystemRelation] = getEntityRelations(entity, RELATION_PART_OF, {
kind: 'system',
});
const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);
return (
<Grid container>
<AboutField label="Description" gridSizes={{ xs: 12 }}>
@@ -43,22 +49,21 @@ export const AboutContent = ({ entity }: Props) => {
{entity?.metadata?.description || 'No description'}
</Typography>
</AboutField>
<AboutField label="Owner" gridSizes={{ xs: 12, sm: 6, lg: 4 }}>
{ownedByRelations.map((t, i) => [
i > 0 && ', ',
<EntityRefLink key={i} entityRef={t} />,
])}
</AboutField>
<AboutField
label="Owner"
value={entity?.relations
?.filter(r => r.type === RELATION_OWNED_BY)
.map(({ target: { kind, name, namespace } }) =>
// TODO(Rugvip): we want to provide some utils for this
serializeEntityRef({
kind,
name,
namespace:
namespace === ENTITY_DEFAULT_NAMESPACE ? undefined : namespace,
}),
)
.join(', ')}
label="System"
value="No System"
gridSizes={{ xs: 12, sm: 6, lg: 4 }}
/>
>
{partOfSystemRelation && (
<EntityRefLink entityRef={partOfSystemRelation} />
)}
</AboutField>
<AboutField
label="Type"
value={entity?.spec?.type as string}
@@ -0,0 +1,86 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { render } from '@testing-library/react';
import React from 'react';
import { MemoryRouter } from 'react-router';
import { EntityRefLink } from './EntityRefLink';
describe('<EntityRefLink />', () => {
it('renders link for entity in default namespace', () => {
const entity = {
apiVersion: 'v1',
kind: 'Component',
metadata: {
name: 'software',
},
spec: {
owner: 'guest',
type: 'service',
lifecycle: 'production',
},
};
const { getByText } = render(<EntityRefLink entityRef={entity} />, {
wrapper: MemoryRouter,
});
expect(getByText('component:software')).toBeInTheDocument();
});
it('renders link for entity in other namespace', () => {
const entity = {
apiVersion: 'v1',
kind: 'Component',
metadata: {
name: 'software',
namespace: 'test',
},
spec: {
owner: 'guest',
type: 'service',
lifecycle: 'production',
},
};
const { getByText } = render(<EntityRefLink entityRef={entity} />, {
wrapper: MemoryRouter,
});
expect(getByText('component:test/software')).toBeInTheDocument();
});
it('renders link for entity name in default namespace', () => {
const entityName = {
kind: 'Component',
namespace: 'default',
name: 'software',
};
const { getByText } = render(<EntityRefLink entityRef={entityName} />, {
wrapper: MemoryRouter,
});
expect(getByText('component:software')).toBeInTheDocument();
});
it('renders link for entity name in other namespace', () => {
const entityName = {
kind: 'Component',
namespace: 'test',
name: 'software',
};
const { getByText } = render(<EntityRefLink entityRef={entityName} />, {
wrapper: MemoryRouter,
});
expect(getByText('component:test/software')).toBeInTheDocument();
});
});
@@ -0,0 +1,75 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
Entity,
EntityName,
ENTITY_DEFAULT_NAMESPACE,
serializeEntityRef,
} from '@backstage/catalog-model';
import { Link } from '@material-ui/core';
import React from 'react';
import { generatePath } from 'react-router';
import { Link as RouterLink } from 'react-router-dom';
import { entityRoute } from '../../routes';
type EntityRefLinkProps = {
entityRef: Entity | EntityName;
};
// TODO: This component is private for now, as it should probably belong into
// some kind of helper module for the catalog plugin to avoid a dependency on
// the catalog plugin itself.
export const EntityRefLink = ({ entityRef }: EntityRefLinkProps) => {
let kind;
let namespace;
let name;
if ('metadata' in entityRef) {
kind = entityRef.kind;
namespace = entityRef.metadata.namespace;
name = entityRef.metadata.name;
} else {
kind = entityRef.kind;
namespace = entityRef.namespace;
name = entityRef.name;
}
if (namespace === ENTITY_DEFAULT_NAMESPACE) {
namespace = undefined;
}
kind = kind.toLowerCase();
const title = `${serializeEntityRef({
kind,
name,
namespace,
})}`;
const routeParams = {
kind,
namespace: namespace?.toLowerCase() ?? ENTITY_DEFAULT_NAMESPACE,
name,
};
return (
<Link
component={RouterLink}
to={generatePath(`/catalog/${entityRoute.path}`, routeParams)}
>
{title}
</Link>
);
};
@@ -0,0 +1,16 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { EntityRefLink } from './EntityRefLink';