From 5645f9ff14afb414cc2357a7de74890242064083 Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Wed, 11 Sep 2024 15:10:12 +0200 Subject: [PATCH] update apis cards empty state to use external icon on link Signed-off-by: Emma Indal --- .../ApisCards/ConsumedApisCard.test.tsx | 13 ++++++++- .../components/ApisCards/ConsumedApisCard.tsx | 25 ++++++++++++++-- .../ApisCards/ProvidedApisCard.test.tsx | 14 ++++++++- .../components/ApisCards/ProvidedApisCard.tsx | 29 +++++++++++++++---- 4 files changed, 72 insertions(+), 9 deletions(-) diff --git a/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx b/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx index d664ce78e8..95e279bad5 100644 --- a/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx +++ b/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx @@ -62,7 +62,7 @@ describe('', () => { relations: [], }; - const { getByText } = await renderInTestApp( + const { getByText, getByRole, container } = await renderInTestApp( @@ -77,6 +77,17 @@ describe('', () => { expect(getByText(/Consumed APIs/i)).toBeInTheDocument(); expect(getByText(/does not consume any APIs/i)).toBeInTheDocument(); + + // Also render external link icon + const externalLink = getByRole('link'); + expect(externalLink).toHaveAttribute( + 'href', + 'https://backstage.io/docs/features/software-catalog/descriptor-format#specconsumesapis-optional', + ); + const externalLinkIcon: HTMLElement | null = container.querySelector( + 'svg[class*="externalLink"]', + ); + expect(externalLink).toContainElement(externalLinkIcon); }); it('shows consumed APIs', async () => { diff --git a/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.tsx b/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.tsx index f68e6dcb40..c72da45dd3 100644 --- a/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.tsx +++ b/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.tsx @@ -33,6 +33,16 @@ import { TableOptions, WarningPanel, } from '@backstage/core-components'; +import OpenInNew from '@material-ui/icons/OpenInNew'; +import { useApp } from '@backstage/core-plugin-api'; +import { makeStyles, Theme } from '@material-ui/core/styles'; + +const useStyles = makeStyles((theme: Theme) => ({ + externalLink: { + verticalAlign: 'bottom', + marginLeft: theme.spacing(0.5), + }, +})); /** * @public @@ -53,6 +63,9 @@ export const ConsumedApisCard = (props: { const { entities, loading, error } = useRelatedEntities(entity, { type: RELATION_CONSUMES_API, }); + const app = useApp(); + const ExternalLinkIcon = app.getSystemIcon('externalLink') || OpenInNew; + const classes = useStyles(); if (loading) { return ( @@ -85,8 +98,16 @@ export const ConsumedApisCard = (props: { APIs. - - Learn how to change this. + + } + > + Learn how to change this diff --git a/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx b/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx index 3dbc4edd63..8c4f7dd26b 100644 --- a/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx +++ b/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx @@ -62,7 +62,7 @@ describe('', () => { relations: [], }; - const { getByText } = await renderInTestApp( + const { getByText, getByRole, container } = await renderInTestApp( @@ -77,6 +77,18 @@ describe('', () => { expect(getByText(/Provided APIs/i)).toBeInTheDocument(); expect(getByText(/does not provide any APIs/i)).toBeInTheDocument(); + expect(getByText(/Learn how to change this/)).toBeInTheDocument(); + + // Also render external link icon + const externalLink = getByRole('link'); + expect(externalLink).toHaveAttribute( + 'href', + 'https://backstage.io/docs/features/software-catalog/descriptor-format#specprovidesapis-optional', + ); + const externalLinkIcon: HTMLElement | null = container.querySelector( + 'svg[class*="externalLink"]', + ); + expect(externalLink).toContainElement(externalLinkIcon); }); it('shows consumed APIs', async () => { diff --git a/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.tsx b/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.tsx index 48099df375..2063f23673 100644 --- a/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.tsx +++ b/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.tsx @@ -33,6 +33,16 @@ import { TableOptions, WarningPanel, } from '@backstage/core-components'; +import { useApp } from '@backstage/core-plugin-api'; +import OpenInNew from '@material-ui/icons/OpenInNew'; +import { makeStyles, Theme } from '@material-ui/core/styles'; + +const useStyles = makeStyles((theme: Theme) => ({ + externalLink: { + verticalAlign: 'bottom', + marginLeft: theme.spacing(0.5), + }, +})); /** * @public @@ -53,6 +63,9 @@ export const ProvidedApisCard = (props: { const { entities, loading, error } = useRelatedEntities(entity, { type: RELATION_PROVIDES_API, }); + const app = useApp(); + const ExternalLinkIcon = app.getSystemIcon('externalLink') || OpenInNew; + const classes = useStyles(); if (loading) { return ( @@ -84,11 +97,17 @@ export const ProvidedApisCard = (props: { This {entity.kind.toLocaleLowerCase('en-US')} does not provide any APIs. - - - Learn how to change this. - - + + } + > + Learn how to change this + } columns={columns}