Merge pull request #4520 from egnwd/sb/plugin-org

Storybook: Org Plugin Components
This commit is contained in:
Ben Lambert
2021-02-16 15:44:11 +01:00
committed by GitHub
9 changed files with 401 additions and 5 deletions
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/plugin-org': patch
---
- Fixes padding in `MembersListCard`
- Fixes email icon size in `GroupProfileCard`
- Uniform sizing across `GroupProfileCard` and `UserProfileCard`
+2
View File
@@ -22,6 +22,7 @@
"dependencies": {
"@backstage/catalog-model": "^0.7.1",
"@backstage/core": "^0.6.1",
"@backstage/core-api": "^0.2.9",
"@backstage/plugin-catalog-react": "^0.0.3",
"@backstage/theme": "^0.2.3",
"@material-ui/core": "^4.11.0",
@@ -29,6 +30,7 @@
"@material-ui/lab": "4.0.0-alpha.45",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router": "6.0.0-beta.0",
"react-router-dom": "6.0.0-beta.0",
"react-use": "^15.3.3"
},
@@ -0,0 +1,67 @@
/*
* Copyright 2021 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 { Grid } from '@material-ui/core';
import React from 'react';
import { MemoryRouter } from 'react-router';
import { GroupEntity } from '@backstage/catalog-model';
import { EntityContext } from '@backstage/plugin-catalog-react';
import { GroupProfileCard } from '.';
export default {
title: 'Plugins/Org/Group Profile Card',
component: GroupProfileCard,
};
const dummyDepartment = {
type: 'childOf',
target: {
namespace: 'default',
kind: 'group',
name: 'department-a',
},
};
const defaultEntity: GroupEntity = {
apiVersion: 'backstage.io/v1alpha1',
kind: 'Group',
metadata: {
name: 'team-a',
description: 'Team A',
},
spec: {
profile: {
displayName: 'Team A',
email: 'team-a@example.com',
picture:
'https://avatars.dicebear.com/api/identicon/team-a@example.com.svg?background=%23fff&margin=25',
},
type: 'group',
children: [],
},
relations: [dummyDepartment],
};
export const Default = () => (
<MemoryRouter>
<EntityContext.Provider value={{ entity: defaultEntity, loading: false }}>
<Grid container spacing={4}>
<Grid item xs={12} md={4}>
<GroupProfileCard variant="gridItem" />
</Grid>
</Grid>
</EntityContext.Provider>
</MemoryRouter>
);
@@ -117,7 +117,7 @@ export const GroupProfileCard = ({
<ListItem>
<ListItemIcon>
<Tooltip title="Email">
<EmailIcon fontSize="inherit" />
<EmailIcon />
</Tooltip>
</ListItemIcon>
<ListItemText>{profile.email}</ListItemText>
@@ -0,0 +1,131 @@
/*
* Copyright 2021 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 { Grid } from '@material-ui/core';
import React from 'react';
import { MemoryRouter } from 'react-router';
import { Entity, GroupEntity } from '@backstage/catalog-model';
import { EntityContext, catalogApiRef } from '@backstage/plugin-catalog-react';
import { ApiProvider, ApiRegistry } from '@backstage/core-api';
import { MembersListCard } from '.';
export default {
title: 'Plugins/Org/Group Members List Card',
component: MembersListCard,
};
const makeUser = ({
name,
uid,
displayName,
email,
}: {
name: string;
uid: string;
displayName: string;
email: string;
}) => ({
apiVersion: 'backstage.io/v1alpha1',
kind: 'User',
metadata: {
name,
uid,
},
spec: {
profile: {
displayName,
email,
picture: `https://avatars.dicebear.com/api/avataaars/${email}.svg?background=%23fff`,
},
},
relations: [
{
type: 'memberOf',
target: {
namespace: 'default',
kind: 'group',
name: 'team-a',
},
},
],
});
const defaultEntity: GroupEntity = {
apiVersion: 'backstage.io/v1alpha1',
kind: 'Group',
metadata: {
name: 'team-a',
description: 'Team A',
},
spec: {
profile: {
displayName: 'Team A',
email: 'team-a@example.com',
picture:
'https://avatars.dicebear.com/api/identicon/team-a@example.com.svg?background=%23fff&margin=25',
},
type: 'group',
children: [],
},
};
const alice = makeUser({
name: 'alice',
uid: '123',
displayName: 'Alice Doe',
email: 'alice@example.com',
});
const bob = makeUser({
name: 'bob',
uid: '456',
displayName: 'Bob Jones',
email: 'bob@example.com',
});
const catalogApi = (items: Entity[]) => ({
getEntities: () => Promise.resolve({ items }),
});
const apiRegistry = (items: Entity[]) =>
ApiRegistry.from([[catalogApiRef, catalogApi(items)]]);
export const Default = () => (
<MemoryRouter>
<ApiProvider apis={apiRegistry([alice, bob])}>
<EntityContext.Provider value={{ entity: defaultEntity, loading: false }}>
<Grid container spacing={4}>
<Grid item xs={12} md={6}>
<MembersListCard />
</Grid>
</Grid>
</EntityContext.Provider>
</ApiProvider>
</MemoryRouter>
);
export const Empty = () => (
<MemoryRouter>
<ApiProvider apis={apiRegistry([])}>
<EntityContext.Provider value={{ entity: defaultEntity, loading: false }}>
<Grid container spacing={4}>
<Grid item xs={12} md={6}>
<MembersListCard />
</Grid>
</Grid>
</EntityContext.Provider>
</ApiProvider>
</MemoryRouter>
);
@@ -47,7 +47,7 @@ const useStyles = makeStyles((theme: Theme) =>
borderRadius: '4px',
overflow: 'visible',
position: 'relative',
margin: theme.spacing(3, 0, 1),
margin: theme.spacing(4, 1, 1),
flex: '1',
minWidth: '0px',
},
@@ -69,7 +69,7 @@ const MemberComponent = ({
const displayName = profile?.displayName ?? metaName;
return (
<Grid item container xs={12} sm={6} md={3} xl={2}>
<Grid item container xs={12} sm={6} md={4} xl={2}>
<Box className={classes.card}>
<Box
display="flex"
@@ -0,0 +1,96 @@
/*
* Copyright 2021 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 { Grid } from '@material-ui/core';
import React from 'react';
import { MemoryRouter } from 'react-router';
import { GroupEntity } from '@backstage/catalog-model';
import {
EntityContext,
CatalogApi,
catalogApiRef,
} from '@backstage/plugin-catalog-react';
import { ApiProvider, ApiRegistry } from '@backstage/core-api';
import { OwnershipCard } from '.';
export default {
title: 'Plugins/Org/Ownership Card',
component: OwnershipCard,
};
const defaultEntity: GroupEntity = {
apiVersion: 'backstage.io/v1alpha1',
kind: 'Group',
metadata: {
name: 'team-a',
description: 'Team A',
},
spec: {
profile: {
displayName: 'Team A',
email: 'team-a@example.com',
picture:
'https://avatars.dicebear.com/api/identicon/team-a@example.com.svg?background=%23fff&margin=25',
},
type: 'group',
children: [],
},
};
const makeComponent = ({ type, name }: { type: string; name: string }) => ({
apiVersion: 'backstage.io/v1alpha1',
kind: 'Component',
metadata: {
name,
},
spec: {
type,
},
relations: [
{
type: 'ownedBy',
target: {
namespace: 'default',
kind: 'Group',
name: 'team-a',
},
},
],
});
const serviceA = makeComponent({ type: 'service', name: 'service-a' });
const serviceB = makeComponent({ type: 'service', name: 'service-a' });
const websiteA = makeComponent({ type: 'website', name: 'website-a' });
const catalogApi: Partial<CatalogApi> = {
getEntities: () => Promise.resolve({ items: [serviceA, serviceB, websiteA] }),
};
const apiRegistry = ApiRegistry.from([[catalogApiRef, catalogApi]]);
export const Default = () => (
<MemoryRouter>
<ApiProvider apis={apiRegistry}>
<EntityContext.Provider value={{ entity: defaultEntity, loading: false }}>
<Grid container spacing={4}>
<Grid item xs={12} md={6}>
<OwnershipCard variant="gridItem" />
</Grid>
</Grid>
</EntityContext.Provider>
</ApiProvider>
</MemoryRouter>
);
@@ -0,0 +1,93 @@
/*
* Copyright 2021 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 { Grid } from '@material-ui/core';
import React from 'react';
import { MemoryRouter } from 'react-router';
import { UserEntity } from '@backstage/catalog-model';
import { EntityContext } from '@backstage/plugin-catalog-react';
import { UserProfileCard } from '.';
export default {
title: 'Plugins/Org/User Profile Card',
component: UserProfileCard,
};
const dummyGroup = {
type: 'memberOf',
target: {
namespace: 'default',
kind: 'group',
name: 'team-a',
},
};
const defaultEntity: UserEntity = {
apiVersion: 'backstage.io/v1alpha1',
kind: 'User',
metadata: {
name: 'guest',
},
spec: {
profile: {
displayName: 'Guest User',
email: 'guest@example.com',
picture:
'https://avatars.dicebear.com/api/avataaars/guest@example.com.svg?background=%23fff',
},
memberOf: ['team-a'],
},
relations: [dummyGroup],
};
export const Default = () => (
<MemoryRouter>
<EntityContext.Provider value={{ entity: defaultEntity, loading: false }}>
<Grid container spacing={4}>
<Grid item xs={12} md={4}>
<UserProfileCard variant="gridItem" />
</Grid>
</Grid>
</EntityContext.Provider>
</MemoryRouter>
);
const noImageEntity: UserEntity = {
apiVersion: 'backstage.io/v1alpha1',
kind: 'User',
metadata: {
name: 'guest',
},
spec: {
profile: {
displayName: 'Guest User',
email: 'guest@example.com',
},
memberOf: ['team-a'],
},
relations: [dummyGroup],
};
export const NoImage = () => (
<MemoryRouter>
<EntityContext.Provider value={{ entity: noImageEntity, loading: false }}>
<Grid container spacing={4}>
<Grid item xs={12} md={4}>
<UserProfileCard variant="gridItem" />
</Grid>
</Grid>
</EntityContext.Provider>
</MemoryRouter>
);
@@ -95,11 +95,11 @@ export const UserProfileCard = ({
return (
<InfoCard title={<CardTitle title={displayName} />} variant={variant}>
<Grid container spacing={3} alignItems="flex-start">
<Grid item md={2} lg={1}>
<Grid item xs={12} sm={2} xl={1}>
<Avatar displayName={displayName} picture={profile?.picture} />
</Grid>
<Grid item md={10} lg={11}>
<Grid item md={10} xl={11}>
<List>
{profile?.email && (
<ListItem>