Merge pull request #16347 from clairelcasey/entity-ownership-card-overlapped-text
Fix #16288: add styling to handle overflow text on ownership and members card
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-org': patch
|
||||
---
|
||||
|
||||
Add styling to the `MembersListCard` and `ComponentsGrid` to handle overflow text.
|
||||
@@ -28,6 +28,19 @@ import {
|
||||
import React from 'react';
|
||||
import { MembersListCard } from './MembersListCard';
|
||||
|
||||
// Mock needed because jsdom doesn't correctly implement box-sizing
|
||||
// https://github.com/ShinyChang/React-Text-Truncate/issues/70
|
||||
// https://stackoverflow.com/questions/71916701/how-to-mock-a-react-function-component-that-takes-a-ref-prop
|
||||
jest.mock('react-text-truncate', () => {
|
||||
const { forwardRef } = jest.requireActual('react');
|
||||
return {
|
||||
__esModule: true,
|
||||
default: forwardRef((props: any, ref: any) => (
|
||||
<div ref={ref}>{props.text}</div>
|
||||
)),
|
||||
};
|
||||
});
|
||||
|
||||
describe('MemberTab Test', () => {
|
||||
const groupEntity: GroupEntity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
@@ -95,7 +108,7 @@ describe('MemberTab Test', () => {
|
||||
expect(
|
||||
rendered.getByText('tara-macgovern@example.com'),
|
||||
).toBeInTheDocument();
|
||||
expect(rendered.getByText('Tara MacGovern')).toHaveAttribute(
|
||||
expect(rendered.getByText('Tara MacGovern').closest('a')).toHaveAttribute(
|
||||
'href',
|
||||
'/catalog/foo-bar/user/tara.macgovern',
|
||||
);
|
||||
|
||||
@@ -44,6 +44,7 @@ import {
|
||||
Progress,
|
||||
ResponseErrorPanel,
|
||||
Link,
|
||||
OverflowTooltip,
|
||||
} from '@backstage/core-components';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
|
||||
@@ -59,18 +60,6 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
flex: '1',
|
||||
minWidth: '0px',
|
||||
},
|
||||
email: {
|
||||
overflow: 'hidden',
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'middle',
|
||||
maxWidth: '100%',
|
||||
'&:hover': {
|
||||
overflow: 'visible',
|
||||
whiteSpace: 'normal',
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -103,23 +92,23 @@ const MemberComponent = (props: { member: UserEntity }) => {
|
||||
<Box
|
||||
pt={2}
|
||||
sx={{
|
||||
maxWidth: '100%',
|
||||
width: '100%',
|
||||
}}
|
||||
textAlign="center"
|
||||
>
|
||||
<Typography variant="h5">
|
||||
<Typography variant="h6">
|
||||
<Link
|
||||
to={generatePath(
|
||||
`/catalog/:namespace/user/${metaName}`,
|
||||
entityRouteParams(props.member),
|
||||
)}
|
||||
>
|
||||
{displayName}
|
||||
<OverflowTooltip text={displayName} />
|
||||
</Link>
|
||||
</Typography>
|
||||
{profile?.email && (
|
||||
<Link className={classes.email} to={`mailto:${profile.email}`}>
|
||||
{profile.email}
|
||||
<Link to={`mailto:${profile.email}`}>
|
||||
<OverflowTooltip text={profile.email} />
|
||||
</Link>
|
||||
)}
|
||||
{description && (
|
||||
|
||||
@@ -15,7 +15,12 @@
|
||||
*/
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { Link, Progress, ResponseErrorPanel } from '@backstage/core-components';
|
||||
import {
|
||||
Link,
|
||||
OverflowTooltip,
|
||||
Progress,
|
||||
ResponseErrorPanel,
|
||||
} from '@backstage/core-components';
|
||||
import { useRouteRef } from '@backstage/core-plugin-api';
|
||||
import { BackstageTheme } from '@backstage/theme';
|
||||
import {
|
||||
@@ -47,6 +52,9 @@ const useStyles = makeStyles((theme: BackstageTheme) =>
|
||||
bold: {
|
||||
fontWeight: theme.typography.fontWeightBold,
|
||||
},
|
||||
smallFont: {
|
||||
fontSize: theme.typography.body2.fontSize,
|
||||
},
|
||||
entityTypeBox: {
|
||||
background: (props: { type: string }) =>
|
||||
theme.getPageTheme({ themeId: props.type }).backgroundImage,
|
||||
@@ -68,6 +76,7 @@ const EntityCountTile = ({
|
||||
const classes = useStyles({ type: type ?? kind });
|
||||
|
||||
const rawTitle = type ?? kind;
|
||||
const isLongText = rawTitle.length > 10;
|
||||
|
||||
return (
|
||||
<Link to={url} variant="body2">
|
||||
@@ -80,9 +89,16 @@ const EntityCountTile = ({
|
||||
<Typography className={classes.bold} variant="h6">
|
||||
{counter}
|
||||
</Typography>
|
||||
<Typography className={classes.bold} variant="h6">
|
||||
{pluralize(rawTitle.toLocaleUpperCase('en-US'), counter)}
|
||||
</Typography>
|
||||
<Box sx={{ width: '100%', textAlign: 'center' }}>
|
||||
<Typography
|
||||
className={`${classes.bold} ${isLongText && classes.smallFont}`}
|
||||
variant="h6"
|
||||
>
|
||||
<OverflowTooltip
|
||||
text={pluralize(rawTitle.toLocaleUpperCase('en-US'), counter)}
|
||||
/>
|
||||
</Typography>
|
||||
</Box>
|
||||
{type && <Typography variant="subtitle1">{kind}</Typography>}
|
||||
</Box>
|
||||
</Link>
|
||||
|
||||
@@ -120,6 +120,19 @@ const getEntitiesMock = (
|
||||
} as GetEntitiesResponse);
|
||||
};
|
||||
|
||||
// Mock needed because jsdom doesn't correctly implement box-sizing
|
||||
// https://github.com/ShinyChang/React-Text-Truncate/issues/70
|
||||
// https://stackoverflow.com/questions/71916701/how-to-mock-a-react-function-component-that-takes-a-ref-prop
|
||||
jest.mock('react-text-truncate', () => {
|
||||
const { forwardRef } = jest.requireActual('react');
|
||||
return {
|
||||
__esModule: true,
|
||||
default: forwardRef((props: any, ref: any) => (
|
||||
<div ref={ref}>{props.text}</div>
|
||||
)),
|
||||
};
|
||||
});
|
||||
|
||||
describe('OwnershipCard', () => {
|
||||
const groupEntity: GroupEntity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
@@ -177,19 +190,19 @@ describe('OwnershipCard', () => {
|
||||
|
||||
expect(getByText('OPENAPI')).toBeInTheDocument();
|
||||
expect(
|
||||
queryByText(getByText('OPENAPI').parentElement!, '1'),
|
||||
queryByText(getByText('OPENAPI').closest('a')!, '1'),
|
||||
).toBeInTheDocument();
|
||||
expect(getByText('SERVICE')).toBeInTheDocument();
|
||||
expect(
|
||||
queryByText(getByText('SERVICE').parentElement!, '1'),
|
||||
queryByText(getByText('SERVICE').closest('a')!, '1'),
|
||||
).toBeInTheDocument();
|
||||
expect(getByText('LIBRARY')).toBeInTheDocument();
|
||||
expect(
|
||||
queryByText(getByText('LIBRARY').parentElement!, '1'),
|
||||
queryByText(getByText('LIBRARY').closest('a')!, '1'),
|
||||
).toBeInTheDocument();
|
||||
expect(getByText('SYSTEM')).toBeInTheDocument();
|
||||
expect(
|
||||
queryByText(getByText('SYSTEM').parentElement!, '1'),
|
||||
queryByText(getByText('SYSTEM').closest('a')!, '1'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -215,17 +228,17 @@ describe('OwnershipCard', () => {
|
||||
|
||||
expect(getByText('SYSTEM')).toBeInTheDocument();
|
||||
expect(
|
||||
queryByText(getByText('SYSTEM').parentElement!, '1'),
|
||||
queryByText(getByText('SYSTEM').closest('a')!, '1'),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
queryByText(getByText('SYSTEM').parentElement!, 'System'),
|
||||
queryByText(getByText('SYSTEM').closest('a')!, 'System'),
|
||||
).not.toBeInTheDocument();
|
||||
expect(getByText('OPENAPI')).toBeInTheDocument();
|
||||
expect(
|
||||
queryByText(getByText('OPENAPI').parentElement!, '1'),
|
||||
queryByText(getByText('OPENAPI').closest('a')!, '1'),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
queryByText(getByText('OPENAPI').parentElement!, 'API'),
|
||||
queryByText(getByText('OPENAPI').closest('a')!, 'API'),
|
||||
).toBeInTheDocument();
|
||||
expect(() => getByText('LIBRARY')).toThrow();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user