diff --git a/.changeset/lucky-points-wash.md b/.changeset/lucky-points-wash.md new file mode 100644 index 0000000000..961c354574 --- /dev/null +++ b/.changeset/lucky-points-wash.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-org': patch +--- + +Added an edit button to the `UserProfileCard` that is enabled when the `backstage.io/edit-url` is present, this matches how the `GroupProfileCard` works diff --git a/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.test.tsx b/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.test.tsx index 68e9715b06..f339a5828c 100644 --- a/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.test.tsx +++ b/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.test.tsx @@ -73,3 +73,86 @@ describe('UserSummary Test', () => { expect(rendered.getByText('Super awesome human')).toBeInTheDocument(); }); }); + +describe('Edit Button', () => { + it('Should not be present by default', async () => { + const userEntity: UserEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'calum.leavy', + description: 'Super awesome human', + }, + spec: { + profile: { + displayName: 'Calum Leavy', + email: 'calum-leavy@example.com', + }, + memberOf: ['ExampleGroup'], + }, + relations: [ + { + type: 'memberOf', + targetRef: 'group:default/examplegroup', + }, + ], + }; + + const rendered = await renderWithEffects( + wrapInTestApp( + + + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name': entityRouteRef, + }, + }, + ), + ); + + expect(rendered.queryByTitle('Edit Metadata')).not.toBeInTheDocument(); + }); + + it('Should be visible when edit URL annotation is present', async () => { + const annotations: Record = { + 'backstage.io/edit-url': 'https://example.com/user.yaml', + }; + const userEntity: UserEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'calum.leavy', + description: 'Super awesome human', + annotations, + }, + spec: { + profile: { + displayName: 'Calum Leavy', + email: 'calum-leavy@example.com', + }, + memberOf: ['ExampleGroup'], + }, + relations: [ + { + type: 'memberOf', + targetRef: 'group:default/examplegroup', + }, + ], + }; + + const rendered = await renderWithEffects( + wrapInTestApp( + + + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name': entityRouteRef, + }, + }, + ), + ); + expect(rendered.getByRole('button')).toBeInTheDocument(); + }); +}); diff --git a/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.tsx b/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.tsx index 148fb03d19..dd75578687 100644 --- a/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.tsx +++ b/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.tsx @@ -14,7 +14,11 @@ * limitations under the License. */ -import { RELATION_MEMBER_OF, UserEntity } from '@backstage/catalog-model'; +import { + RELATION_MEMBER_OF, + UserEntity, + ANNOTATION_EDIT_URL, +} from '@backstage/catalog-model'; import { EntityRefLinks, getEntityRelations, @@ -23,12 +27,14 @@ import { import { Box, Grid, + IconButton, List, ListItem, ListItemIcon, ListItemText, Tooltip, } from '@material-ui/core'; +import EditIcon from '@material-ui/icons/Edit'; import EmailIcon from '@material-ui/icons/Email'; import GroupIcon from '@material-ui/icons/Group'; import PersonIcon from '@material-ui/icons/Person'; @@ -56,6 +62,9 @@ export const UserProfileCard = (props: { variant?: InfoCardVariants }) => { return User not found; } + const entityMetadataEditUrl = + user.metadata.annotations?.[ANNOTATION_EDIT_URL]; + const { metadata: { name: metaName, description }, spec: { profile }, @@ -71,6 +80,20 @@ export const UserProfileCard = (props: { variant?: InfoCardVariants }) => { title={} subheader={description} variant={props.variant} + action={ + <> + {entityMetadataEditUrl && ( + + + + )} + + } >