Display the owner and system as links to the entity pages in the about card
This commit is contained in:
@@ -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';
|
||||
Reference in New Issue
Block a user