From 5cee4f71caba40e2758f1f9a458178d5ec274ebb Mon Sep 17 00:00:00 2001 From: Claire Casey Date: Tue, 14 Feb 2023 14:45:56 -0500 Subject: [PATCH 1/5] add styling to handle overflow text on ownership and members card Signed-off-by: Claire Casey --- .../Cards/Group/MembersList/MembersListCard.tsx | 11 +++++++---- .../Cards/OwnershipCard/ComponentsGrid.tsx | 14 +++++++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx index 7e5b683bf1..65c3144d30 100644 --- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx +++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx @@ -59,15 +59,14 @@ const useStyles = makeStyles((theme: Theme) => flex: '1', minWidth: '0px', }, - email: { + overflowingText: { overflow: 'hidden', - whiteSpace: 'nowrap', textOverflow: 'ellipsis', display: 'inline-block', maxWidth: '100%', '&:hover': { overflow: 'visible', - whiteSpace: 'normal', + wordBreak: 'break-word', }, }, }), @@ -108,6 +107,7 @@ const MemberComponent = (props: { member: UserEntity }) => { > { {profile?.email && ( - + {profile.email} )} diff --git a/plugins/org/src/components/Cards/OwnershipCard/ComponentsGrid.tsx b/plugins/org/src/components/Cards/OwnershipCard/ComponentsGrid.tsx index 567c7ad3bc..edd8cc126f 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/ComponentsGrid.tsx +++ b/plugins/org/src/components/Cards/OwnershipCard/ComponentsGrid.tsx @@ -44,8 +44,16 @@ const useStyles = makeStyles((theme: BackstageTheme) => }, height: '100%', }, - bold: { + title: { fontWeight: theme.typography.fontWeightBold, + textAlign: 'center', + overflow: 'hidden', + textOverflow: 'ellipsis', + maxWidth: '100%', + '&:hover': { + overflow: 'visible', + wordBreak: 'break-word', + }, }, entityTypeBox: { background: (props: { type: string }) => @@ -77,10 +85,10 @@ const EntityCountTile = ({ flexDirection="column" alignItems="center" > - + {counter} - + {pluralize(rawTitle.toLocaleUpperCase('en-US'), counter)} {type && {kind}} From a06fcac40405d66acdbd4d8e3c029f15e3864b21 Mon Sep 17 00:00:00 2001 From: Claire Casey Date: Tue, 14 Feb 2023 15:43:28 -0500 Subject: [PATCH 2/5] add changeset Signed-off-by: Claire Casey --- .changeset/selfish-hats-wait.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/selfish-hats-wait.md diff --git a/.changeset/selfish-hats-wait.md b/.changeset/selfish-hats-wait.md new file mode 100644 index 0000000000..40d0d194e7 --- /dev/null +++ b/.changeset/selfish-hats-wait.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-org': patch +--- + +Add styling to the MembersListCard and ComponentsGrid to handle overflow text. From c915712447f4f356ce0905762fb78362bc3cc1ec Mon Sep 17 00:00:00 2001 From: Claire Casey Date: Thu, 16 Feb 2023 16:29:50 -0500 Subject: [PATCH 3/5] refactor to use OverflowTooltip component Signed-off-by: Claire Casey --- .changeset/selfish-hats-wait.md | 2 +- .../Group/MembersList/MembersListCard.tsx | 16 ++++----- .../Cards/OwnershipCard/ComponentsGrid.tsx | 36 +++++++++++-------- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/.changeset/selfish-hats-wait.md b/.changeset/selfish-hats-wait.md index 40d0d194e7..d706d42e8e 100644 --- a/.changeset/selfish-hats-wait.md +++ b/.changeset/selfish-hats-wait.md @@ -2,4 +2,4 @@ '@backstage/plugin-org': patch --- -Add styling to the MembersListCard and ComponentsGrid to handle overflow text. +Add styling to the `MembersListCard` and `ComponentsGrid` to handle overflow text. diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx index 65c3144d30..bf561a23a4 100644 --- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx +++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx @@ -44,6 +44,7 @@ import { Progress, ResponseErrorPanel, Link, + OverflowTooltip, } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; @@ -59,14 +60,15 @@ const useStyles = makeStyles((theme: Theme) => flex: '1', minWidth: '0px', }, - overflowingText: { + email: { overflow: 'hidden', + whiteSpace: 'nowrap', textOverflow: 'ellipsis', display: 'inline-block', maxWidth: '100%', '&:hover': { overflow: 'visible', - wordBreak: 'break-word', + whiteSpace: 'normal', }, }, }), @@ -105,22 +107,18 @@ const MemberComponent = (props: { member: UserEntity }) => { }} textAlign="center" > - + - {displayName} + {profile?.email && ( - + {profile.email} )} diff --git a/plugins/org/src/components/Cards/OwnershipCard/ComponentsGrid.tsx b/plugins/org/src/components/Cards/OwnershipCard/ComponentsGrid.tsx index edd8cc126f..b2714b5dd5 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/ComponentsGrid.tsx +++ b/plugins/org/src/components/Cards/OwnershipCard/ComponentsGrid.tsx @@ -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 { @@ -44,16 +49,11 @@ const useStyles = makeStyles((theme: BackstageTheme) => }, height: '100%', }, - title: { + bold: { fontWeight: theme.typography.fontWeightBold, - textAlign: 'center', - overflow: 'hidden', - textOverflow: 'ellipsis', - maxWidth: '100%', - '&:hover': { - overflow: 'visible', - wordBreak: 'break-word', - }, + }, + smallFont: { + fontSize: theme.typography.body2.fontSize, }, entityTypeBox: { background: (props: { type: string }) => @@ -76,6 +76,7 @@ const EntityCountTile = ({ const classes = useStyles({ type: type ?? kind }); const rawTitle = type ?? kind; + const isLongText = rawTitle.length > 10; return ( @@ -85,12 +86,19 @@ const EntityCountTile = ({ flexDirection="column" alignItems="center" > - + {counter} - - {pluralize(rawTitle.toLocaleUpperCase('en-US'), counter)} - + + + + + {type && {kind}} From c79857ae25c8dba188413b7aa922d7e17e0980e3 Mon Sep 17 00:00:00 2001 From: Claire Casey Date: Tue, 21 Feb 2023 13:03:25 -0500 Subject: [PATCH 4/5] fix tests broken by OverflowToolTip changes Signed-off-by: Claire Casey --- .../MembersList/MembersListCard.test.tsx | 15 +++++++++- .../OwnershipCard/OwnershipCard.test.tsx | 29 ++++++++++++++----- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx index c98cc3eb32..cc524b60a2 100644 --- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx +++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx @@ -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) => ( +
{props.text}
+ )), + }; +}); + 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', ); diff --git a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx index 84f27fa183..30b7dee2de 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx +++ b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx @@ -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) => ( +
{props.text}
+ )), + }; +}); + 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(); }); From 67b30654f442f3b9f4f94bb46e4046a28a70f002 Mon Sep 17 00:00:00 2001 From: Claire Casey Date: Thu, 23 Feb 2023 13:51:26 -0500 Subject: [PATCH 5/5] use OverflowTooltip component on email in MembershipCard Signed-off-by: Claire Casey --- .../Cards/Group/MembersList/MembersListCard.tsx | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx index bf561a23a4..eb61989144 100644 --- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx +++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx @@ -60,17 +60,6 @@ const useStyles = makeStyles((theme: Theme) => flex: '1', minWidth: '0px', }, - email: { - overflow: 'hidden', - whiteSpace: 'nowrap', - textOverflow: 'ellipsis', - display: 'inline-block', - maxWidth: '100%', - '&:hover': { - overflow: 'visible', - whiteSpace: 'normal', - }, - }, }), ); @@ -103,7 +92,7 @@ const MemberComponent = (props: { member: UserEntity }) => { @@ -118,8 +107,8 @@ const MemberComponent = (props: { member: UserEntity }) => {
{profile?.email && ( - - {profile.email} + + )} {description && (