diff --git a/.changeset/mean-bobcats-taste.md b/.changeset/mean-bobcats-taste.md new file mode 100644 index 0000000000..299273209c --- /dev/null +++ b/.changeset/mean-bobcats-taste.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +Add a "View Component" button as the primary CTA after registering a new component using a link to catalog-info.yaml diff --git a/plugins/catalog-import/src/components/Buttons/index.tsx b/plugins/catalog-import/src/components/Buttons/index.tsx index a478bfd4cc..4b9043cd6d 100644 --- a/plugins/catalog-import/src/components/Buttons/index.tsx +++ b/plugins/catalog-import/src/components/Buttons/index.tsx @@ -14,6 +14,7 @@ * limitations under the License. */ +import { LinkButton } from '@backstage/core-components'; import { Button, CircularProgress } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import React, { ComponentProps } from 'react'; @@ -68,3 +69,20 @@ export const BackButton = (props: ComponentProps) => { ); }; + +export const ViewComponentButton = ( + props: ComponentProps, +) => { + const classes = useStyles(); + + return ( + + {props.children} + + ); +}; diff --git a/plugins/catalog-import/src/components/StepFinishImportLocation/StepFinishImportLocation.tsx b/plugins/catalog-import/src/components/StepFinishImportLocation/StepFinishImportLocation.tsx index 8d1a588079..38372e59ba 100644 --- a/plugins/catalog-import/src/components/StepFinishImportLocation/StepFinishImportLocation.tsx +++ b/plugins/catalog-import/src/components/StepFinishImportLocation/StepFinishImportLocation.tsx @@ -17,23 +17,45 @@ import { Grid, Typography } from '@material-ui/core'; import LocationOnIcon from '@material-ui/icons/LocationOn'; import React from 'react'; -import { BackButton } from '../Buttons'; +import { BackButton, ViewComponentButton } from '../Buttons'; import { EntityListComponent } from '../EntityListComponent'; import { PrepareResult } from '../useImportState'; import { Link } from '@backstage/core-components'; import partition from 'lodash/partition'; +import { CompoundEntityRef } from '@backstage/catalog-model'; +import { entityRouteRef } from '@backstage/plugin-catalog-react'; +import { useRouteRef } from '@backstage/core-plugin-api'; type Props = { prepareResult: PrepareResult; onReset: () => void; }; +// Among the newly registered entities, return a software entity (e.g. Component, API, Resource) +const filterComponentEntity = ( + newLocations: Array<{ + exists?: boolean; + target: string; + entities: CompoundEntityRef[]; + }>, +): CompoundEntityRef | null => { + for (const location of newLocations) { + for (const entity of location.entities) { + if ( + ['component', 'api', 'resource'].includes( + entity.kind.toLocaleLowerCase('en-US'), + ) + ) { + return entity; + } + } + } + + return null; +}; + export const StepFinishImportLocation = ({ prepareResult, onReset }: Props) => { - const continueButton = ( - - Register another - - ); + const entityRoute = useRouteRef(entityRouteRef); if (prepareResult.type === 'repository') { return ( @@ -48,12 +70,13 @@ export const StepFinishImportLocation = ({ prepareResult, onReset }: Props) => { {prepareResult.pullRequest.url} - Your entities will be imported as soon as the Pull Request is merged. - - {continueButton} + + Register another + + ; ); } @@ -62,7 +85,7 @@ export const StepFinishImportLocation = ({ prepareResult, onReset }: Props) => { prepareResult.locations, l => l.exists, ); - + const newComponentEntity = filterComponentEntity(newLocations); return ( <> {newLocations.length > 0 && ( @@ -91,7 +114,14 @@ export const StepFinishImportLocation = ({ prepareResult, onReset }: Props) => { /> )} - {continueButton} + + {newComponentEntity && ( + + View Component + + )} + Register another + ); }; diff --git a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx index a9d662cab0..d8a12d0e5c 100644 --- a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx +++ b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx @@ -64,12 +64,8 @@ describe('', () => { wrapper: Wrapper, }); - expect( - screen.getByRole('textbox', { name: /Repository/i }), - ).toBeInTheDocument(); - expect(screen.getByRole('textbox', { name: /Repository/i })).toHaveValue( - '', - ); + expect(screen.getByRole('textbox', { name: /URL/i })).toBeInTheDocument(); + expect(screen.getByRole('textbox', { name: /URL/i })).toHaveValue(''); }); it('should use default analysis url', async () => { @@ -83,10 +79,8 @@ describe('', () => { }, ); - expect( - screen.getByRole('textbox', { name: /Repository/i }), - ).toBeInTheDocument(); - expect(screen.getByRole('textbox', { name: /Repository/i })).toHaveValue( + expect(screen.getByRole('textbox', { name: /URL/i })).toBeInTheDocument(); + expect(screen.getByRole('textbox', { name: /URL/i })).toHaveValue( 'https://default', ); }); @@ -120,7 +114,7 @@ describe('', () => { await act(async () => { await userEvent.type( - screen.getByRole('textbox', { name: /Repository/i }), + screen.getByRole('textbox', { name: /URL/i }), 'http:/', ); await userEvent.click(screen.getByRole('button', { name: /Analyze/i })); @@ -152,7 +146,7 @@ describe('', () => { await act(async () => { await userEvent.type( - screen.getByRole('textbox', { name: /Repository/i }), + screen.getByRole('textbox', { name: /URL/i }), 'https://my-repository', ); await userEvent.click(screen.getByRole('button', { name: /Analyze/i })); @@ -186,7 +180,7 @@ describe('', () => { await act(async () => { await userEvent.type( - screen.getByRole('textbox', { name: /Repository/i }), + screen.getByRole('textbox', { name: /URL/i }), 'https://my-repository-1', ); await userEvent.click(screen.getByRole('button', { name: /Analyze/i })); @@ -219,7 +213,7 @@ describe('', () => { await act(async () => { await userEvent.type( - screen.getByRole('textbox', { name: /Repository/i }), + screen.getByRole('textbox', { name: /URL/i }), 'https://my-repository-1', ); await userEvent.click(screen.getByRole('button', { name: /Analyze/i })); @@ -260,7 +254,7 @@ describe('', () => { await act(async () => { await userEvent.type( - screen.getByRole('textbox', { name: /Repository/i }), + screen.getByRole('textbox', { name: /URL/i }), 'https://my-repository-2', ); await userEvent.click(screen.getByRole('button', { name: /Analyze/i })); @@ -295,7 +289,7 @@ describe('', () => { await act(async () => { await userEvent.type( - screen.getByRole('textbox', { name: /Repository/i }), + screen.getByRole('textbox', { name: /URL/i }), 'https://my-repository-2', ); await userEvent.click(screen.getByRole('button', { name: /Analyze/i })); @@ -339,7 +333,7 @@ describe('', () => { await act(async () => { await userEvent.type( - screen.getByRole('textbox', { name: /Repository/i }), + screen.getByRole('textbox', { name: /URL/i }), 'https://my-repository-2', ); await userEvent.click(screen.getByRole('button', { name: /Analyze/i })); @@ -365,7 +359,7 @@ describe('', () => { await act(async () => { await userEvent.type( - screen.getByRole('textbox', { name: /Repository/i }), + screen.getByRole('textbox', { name: /URL/i }), 'https://my-repository-2', ); await userEvent.click(screen.getByRole('button', { name: /Analyze/i })); diff --git a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx index 3c655ec11b..588217974c 100644 --- a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx +++ b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx @@ -147,7 +147,7 @@ export const StepInitAnalyzeUrl = (props: StepInitAnalyzeUrlProps) => { )} fullWidth id="url" - label="Repository URL" + label="URL" placeholder={exampleLocationUrl} helperText="Enter the full path to your entity file to start tracking your component" margin="normal"