From e2caba7b17201a7f0d12ad626853e405360825c3 Mon Sep 17 00:00:00 2001 From: Matthew Prinold Date: Wed, 25 Oct 2023 09:58:45 +0100 Subject: [PATCH 01/10] feat(EntityLayout): navigates to root of catalog after unregistering and entity Signed-off-by: Matthew Prinold --- .../app/src/components/catalog/EntityPage.test.tsx | 8 +++++++- .../src/components/EntityLayout/EntityLayout.test.tsx | 7 +++++++ .../src/components/EntityLayout/EntityLayout.tsx | 5 ++++- .../Cards/Group/MembersList/MembersListCard.test.tsx | 11 ++++++++++- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/packages/app/src/components/catalog/EntityPage.test.tsx b/packages/app/src/components/catalog/EntityPage.test.tsx index 68ce5fb497..25181db2c1 100644 --- a/packages/app/src/components/catalog/EntityPage.test.tsx +++ b/packages/app/src/components/catalog/EntityPage.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { EntityLayout } from '@backstage/plugin-catalog'; +import { EntityLayout, catalogPlugin } from '@backstage/plugin-catalog'; import { EntityProvider, starredEntitiesApiRef, @@ -51,6 +51,7 @@ describe('EntityPage Test', () => { listWorkflowRuns: jest.fn().mockResolvedValue([]), }; const mockPermissionApi = new MockPermissionApi(); + const rootRouteRef = catalogPlugin.routes.catalogIndex; describe('cicdContent', () => { it('Should render GitHub Actions View', async () => { @@ -70,6 +71,11 @@ describe('EntityPage Test', () => { , + { + mountedRoutes: { + '/catalog': rootRouteRef, + }, + }, ); expect(rendered.getByText('ExampleComponent')).toBeInTheDocument(); diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx index 3634405af8..4f46d1d7f3 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx @@ -35,6 +35,7 @@ import { import { act, fireEvent, screen } from '@testing-library/react'; import React from 'react'; import { EntityLayout } from './EntityLayout'; +import { rootRouteRef } from '../../routes'; const mockEntity = { kind: 'MyKind', @@ -65,6 +66,7 @@ describe('EntityLayout', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -97,6 +99,7 @@ describe('EntityLayout', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -120,6 +123,7 @@ describe('EntityLayout', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -146,6 +150,7 @@ describe('EntityLayout', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -178,6 +183,7 @@ describe('EntityLayout', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -225,6 +231,7 @@ describe('EntityLayout', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx index f9999f26e9..7df02abe4e 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx @@ -33,6 +33,7 @@ import { attachComponentData, IconComponent, useElementFilter, + useRouteRef, useRouteRefParams, } from '@backstage/core-plugin-api'; import { @@ -50,6 +51,7 @@ import { Alert } from '@material-ui/lab'; import React, { useEffect, useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import { EntityContextMenu } from '../EntityContextMenu/EntityContextMenu'; +import { rootRouteRef } from '../../routes'; /** @public */ export type EntityLayoutRouteProps = { @@ -229,10 +231,11 @@ export const EntityLayout = (props: EntityLayoutProps) => { const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false); const [inspectionDialogOpen, setInspectionDialogOpen] = useState(false); const navigate = useNavigate(); + const catalogRoute = useRouteRef(rootRouteRef); const cleanUpAfterRemoval = async () => { setConfirmationDialogOpen(false); setInspectionDialogOpen(false); - navigate('/'); + navigate(catalogRoute()); }; // Make sure to close the dialog if the user clicks links in it that navigate 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 6613aa5b6a..cd5801ac71 100644 --- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx +++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx @@ -31,7 +31,7 @@ import { mockedCatalogApiSupportingGroups, } from '../../../../__testUtils__/catalogMocks'; import { permissionApiRef } from '@backstage/plugin-permission-react'; -import { EntityLayout } from '@backstage/plugin-catalog'; +import { EntityLayout, catalogPlugin } from '@backstage/plugin-catalog'; import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { Observable } from '@backstage/types'; @@ -63,6 +63,8 @@ const mockedStarredEntitiesApi: Partial = { }, }; +const rootRouteRef = catalogPlugin.routes.catalogIndex; + describe('MemberTab Test', () => { const groupEntity: GroupEntity = { apiVersion: 'backstage.io/v1alpha1', @@ -122,6 +124,7 @@ describe('MemberTab Test', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -151,6 +154,7 @@ describe('MemberTab Test', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -179,6 +183,7 @@ describe('MemberTab Test', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -206,6 +211,7 @@ describe('MemberTab Test', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -231,6 +237,7 @@ describe('MemberTab Test', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -265,6 +272,7 @@ describe('MemberTab Test', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -299,6 +307,7 @@ describe('MemberTab Test', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); From cd910c4fa55bb6e1b22db02f13c40e6f2cb01b69 Mon Sep 17 00:00:00 2001 From: Matthew Prinold Date: Wed, 25 Oct 2023 10:07:20 +0100 Subject: [PATCH 02/10] chore(changeset): adds changeset Signed-off-by: Matthew Prinold --- .changeset/lucky-kids-cough.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/lucky-kids-cough.md diff --git a/.changeset/lucky-kids-cough.md b/.changeset/lucky-kids-cough.md new file mode 100644 index 0000000000..1bfacb853c --- /dev/null +++ b/.changeset/lucky-kids-cough.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +refactors redirection after successfully unregistering an entity to use the catalog rootRouteRef "/catalog" instead of "/" From 934ddf3794012e7904ae133c3ff80dea949481eb Mon Sep 17 00:00:00 2001 From: Matthew Prinold Date: Thu, 26 Oct 2023 12:08:54 +0100 Subject: [PATCH 03/10] feat(EntityLayout): navigates to externalRouteRef after entity removal if bound Signed-off-by: Matthew Prinold --- plugins/catalog/package.json | 3 +- .../EntityLayout/EntityLayout.test.tsx | 206 ++++++++++++++++-- .../components/EntityLayout/EntityLayout.tsx | 8 +- plugins/catalog/src/plugin.ts | 2 + plugins/catalog/src/routes.ts | 5 + 5 files changed, 204 insertions(+), 20 deletions(-) diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 150f5362f3..14628a0323 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -77,7 +77,8 @@ "peerDependencies": { "react": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", - "react-router-dom": "6.0.0-beta.0 || ^6.3.0" + "react-router-dom": "6.0.0-beta.0 || ^6.3.0", + "react-router": "6.17.0" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx index 4f46d1d7f3..96b1a3ae59 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx @@ -15,7 +15,11 @@ */ import { CatalogApi } from '@backstage/catalog-client'; -import { Entity } from '@backstage/catalog-model'; +import { + ANNOTATION_ORIGIN_LOCATION, + Entity, + RELATION_OWNED_BY, +} from '@backstage/catalog-model'; import { ApiProvider } from '@backstage/core-app-api'; import { AlertApi, alertApiRef } from '@backstage/core-plugin-api'; import { @@ -30,28 +34,30 @@ import { permissionApiRef } from '@backstage/plugin-permission-react'; import { MockPermissionApi, renderInTestApp, + TestApiProvider, TestApiRegistry, } from '@backstage/test-utils'; -import { act, fireEvent, screen } from '@testing-library/react'; +import { act, fireEvent, screen, waitFor } from '@testing-library/react'; import React from 'react'; import { EntityLayout } from './EntityLayout'; -import { rootRouteRef } from '../../routes'; - -const mockEntity = { - kind: 'MyKind', - metadata: { - name: 'my-entity', - }, -} as Entity; - -const mockApis = TestApiRegistry.from( - [catalogApiRef, {} as CatalogApi], - [alertApiRef, {} as AlertApi], - [starredEntitiesApiRef, new MockStarredEntitiesApi()], - [permissionApiRef, new MockPermissionApi()], -); +import { rootRouteRef, unregisterRedirectRouteRef } from '../../routes'; +import * as router from 'react-router'; describe('EntityLayout', () => { + const mockEntity = { + kind: 'MyKind', + metadata: { + name: 'my-entity', + }, + } as Entity; + + const mockApis = TestApiRegistry.from( + [catalogApiRef, {} as CatalogApi], + [alertApiRef, {} as AlertApi], + [starredEntitiesApiRef, new MockStarredEntitiesApi()], + [permissionApiRef, new MockPermissionApi()], + ); + it('renders simplest case', async () => { await renderInTestApp( @@ -272,3 +278,169 @@ describe('EntityLayout', () => { expect(linkParent?.tagName).toBe('P'); }); }); + +describe('EntityLayout - CleanUpAfterRemoval', () => { + const entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'n', + namespace: 'ns', + annotations: { + [ANNOTATION_ORIGIN_LOCATION]: 'url:http://example.com', + }, + }, + spec: { + owner: 'tools', + type: 'service', + }, + relations: [ + { + type: RELATION_OWNED_BY, + targetRef: 'group:default/tools', + }, + ], + }; + const getLocationByRef: jest.MockedFunction = + jest.fn(); + const getEntities: jest.MockedFunction = jest.fn(); + const removeEntityByUid: jest.MockedFunction< + CatalogApi['removeEntityByUid'] + > = jest.fn(); + const getEntityFacets: jest.MockedFunction = + jest.fn(); + getLocationByRef.mockResolvedValue(undefined); + getEntities.mockResolvedValue({ items: [{ ...entity }] }); + getEntityFacets.mockResolvedValue({ + facets: { + 'relations.ownedBy': [{ count: 1, value: 'group:default/tools' }], + }, + }); + + const alertApi: AlertApi = { + post() { + return undefined; + }, + alert$() { + throw new Error('not implemented'); + }, + }; + + const navigate = jest.fn(); + beforeEach(() => { + jest.spyOn(router, 'useNavigate').mockImplementation(() => navigate); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('redirects to externalRouteRef when unregisterRedirectRouteRef is bound', async () => { + await renderInTestApp( + + + + +
tabbed-test-content
+
+
+
+
, + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, + '/testExternalRouteRef': unregisterRedirectRouteRef, + }, + }, + ); + + const menuButton = screen.queryAllByTestId('menu-button')[0]; + fireEvent.click(menuButton); + const listItemUnregister = screen.queryAllByRole('menuitem', { + name: /Unregister entity/i, + })[0]; + fireEvent.click(listItemUnregister); + await waitFor(() => { + const deleteEntityButton = screen.getByRole('button', { + name: /Delete Entity/i, + }); + act(() => { + fireEvent.click(deleteEntityButton); + }); + }); + + await waitFor(() => { + expect(navigate).toHaveBeenCalledWith('/testExternalRouteRef'); + }); + }); + + it('redirects to rootRouteRef when unregisterRedirectRouteRef is not bound', async () => { + await renderInTestApp( + + + + +
tabbed-test-content
+
+
+
+
, + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, + }, + }, + ); + + const menuButton = screen.queryAllByTestId('menu-button')[0]; + fireEvent.click(menuButton); + const listItemUnregister = screen.queryAllByRole('menuitem', { + name: /Unregister entity/i, + })[0]; + fireEvent.click(listItemUnregister); + await waitFor(() => { + const deleteEntityButton = screen.getByRole('button', { + name: /Delete Entity/i, + }); + act(() => { + fireEvent.click(deleteEntityButton); + }); + }); + + await waitFor(() => { + expect(navigate).toHaveBeenCalledWith('/catalog'); + }); + }); +}); diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx index 7df02abe4e..8e11f92599 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx @@ -51,7 +51,7 @@ import { Alert } from '@material-ui/lab'; import React, { useEffect, useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import { EntityContextMenu } from '../EntityContextMenu/EntityContextMenu'; -import { rootRouteRef } from '../../routes'; +import { rootRouteRef, unregisterRedirectRouteRef } from '../../routes'; /** @public */ export type EntityLayoutRouteProps = { @@ -232,10 +232,14 @@ export const EntityLayout = (props: EntityLayoutProps) => { const [inspectionDialogOpen, setInspectionDialogOpen] = useState(false); const navigate = useNavigate(); const catalogRoute = useRouteRef(rootRouteRef); + const unregisterRedirectRoute = useRouteRef(unregisterRedirectRouteRef); + const cleanUpAfterRemoval = async () => { setConfirmationDialogOpen(false); setInspectionDialogOpen(false); - navigate(catalogRoute()); + navigate( + unregisterRedirectRoute ? unregisterRedirectRoute() : catalogRoute(), + ); }; // Make sure to close the dialog if the user clicks links in it that navigate diff --git a/plugins/catalog/src/plugin.ts b/plugins/catalog/src/plugin.ts index d310639fb1..f41fefe404 100644 --- a/plugins/catalog/src/plugin.ts +++ b/plugins/catalog/src/plugin.ts @@ -25,6 +25,7 @@ import { import { createComponentRouteRef, createFromTemplateRouteRef, + unregisterRedirectRouteRef, viewTechDocRouteRef, } from './routes'; import { @@ -89,6 +90,7 @@ export const catalogPlugin = createPlugin({ createComponent: createComponentRouteRef, viewTechDoc: viewTechDocRouteRef, createFromTemplate: createFromTemplateRouteRef, + unregisterRedirect: unregisterRedirectRouteRef, }, }); diff --git a/plugins/catalog/src/routes.ts b/plugins/catalog/src/routes.ts index ab70a3c551..1926576f70 100644 --- a/plugins/catalog/src/routes.ts +++ b/plugins/catalog/src/routes.ts @@ -36,6 +36,11 @@ export const createFromTemplateRouteRef = createExternalRouteRef({ params: ['namespace', 'templateName'], }); +export const unregisterRedirectRouteRef = createExternalRouteRef({ + id: 'unregister-redirect', + optional: true, +}); + export const rootRouteRef = createRouteRef({ id: 'catalog', }); From fc1137924d00f2a380f80e1970f94f33fb2b05ca Mon Sep 17 00:00:00 2001 From: Matthew Prinold Date: Thu, 26 Oct 2023 12:16:52 +0100 Subject: [PATCH 04/10] chore(changeset): updates description to include the optional external route Signed-off-by: Matthew Prinold --- .changeset/lucky-kids-cough.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/lucky-kids-cough.md b/.changeset/lucky-kids-cough.md index 1bfacb853c..a12f85c127 100644 --- a/.changeset/lucky-kids-cough.md +++ b/.changeset/lucky-kids-cough.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog': patch --- -refactors redirection after successfully unregistering an entity to use the catalog rootRouteRef "/catalog" instead of "/" +fixes bug where after unregistering an entity you are redirected to "/". Adds an optional externalRoute "unregisterRedirect" into the catalog plugin which when bound will be navigated to on successfull removal of an entity. If the external route is not bound it will default to using the catalog rootRouteRef "/catalog". From 6c14c07bee67d8d79594c394bff8bc6da1facbd7 Mon Sep 17 00:00:00 2001 From: Matthew Prinold Date: Fri, 27 Oct 2023 11:29:10 +0100 Subject: [PATCH 05/10] fix(EntityLayout.test): removes peer dependency react-router Signed-off-by: Matthew Prinold --- plugins/catalog/package.json | 3 +-- .../EntityLayout/EntityLayout.test.tsx | 25 +++++++++---------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 14628a0323..150f5362f3 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -77,8 +77,7 @@ "peerDependencies": { "react": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", - "react-router-dom": "6.0.0-beta.0 || ^6.3.0", - "react-router": "6.17.0" + "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx index 96b1a3ae59..9196ad9e8d 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx @@ -41,7 +41,7 @@ import { act, fireEvent, screen, waitFor } from '@testing-library/react'; import React from 'react'; import { EntityLayout } from './EntityLayout'; import { rootRouteRef, unregisterRedirectRouteRef } from '../../routes'; -import * as router from 'react-router'; +import { Route, Routes } from 'react-router-dom'; describe('EntityLayout', () => { const mockEntity = { @@ -326,15 +326,6 @@ describe('EntityLayout - CleanUpAfterRemoval', () => { }, }; - const navigate = jest.fn(); - beforeEach(() => { - jest.spyOn(router, 'useNavigate').mockImplementation(() => navigate); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - it('redirects to externalRouteRef when unregisterRedirectRouteRef is bound', async () => { await renderInTestApp( { + + catalog-page

} /> + external-page

} /> +
, { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, '/catalog': rootRouteRef, - '/testExternalRouteRef': unregisterRedirectRouteRef, + '/testRoute': unregisterRedirectRouteRef, }, }, ); @@ -386,7 +381,7 @@ describe('EntityLayout - CleanUpAfterRemoval', () => { }); await waitFor(() => { - expect(navigate).toHaveBeenCalledWith('/testExternalRouteRef'); + expect(screen.getByText('external-page')).toBeInTheDocument(); }); }); @@ -415,6 +410,10 @@ describe('EntityLayout - CleanUpAfterRemoval', () => { + + catalog-page

} /> + external-page

} /> +
, { mountedRoutes: { @@ -440,7 +439,7 @@ describe('EntityLayout - CleanUpAfterRemoval', () => { }); await waitFor(() => { - expect(navigate).toHaveBeenCalledWith('/catalog'); + expect(screen.getByText('catalog-page')).toBeInTheDocument(); }); }); }); From 56fb06fbc7a59a4bf19a2e94ec7cd773c6d0435b Mon Sep 17 00:00:00 2001 From: Matthew Prinold Date: Fri, 27 Oct 2023 11:50:22 +0100 Subject: [PATCH 06/10] fix(changeset): fixes spelling mistakes Signed-off-by: Matthew Prinold --- .changeset/lucky-kids-cough.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/lucky-kids-cough.md b/.changeset/lucky-kids-cough.md index a12f85c127..2e2bed118e 100644 --- a/.changeset/lucky-kids-cough.md +++ b/.changeset/lucky-kids-cough.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog': patch --- -fixes bug where after unregistering an entity you are redirected to "/". Adds an optional externalRoute "unregisterRedirect" into the catalog plugin which when bound will be navigated to on successfull removal of an entity. If the external route is not bound it will default to using the catalog rootRouteRef "/catalog". +fixes bug where after unregistering an entity you are redirected to "/". Adds an optional external route "unregisterRedirect" into the catalog plugin which when bound will be navigated to on successful removal of an entity. If the external route is not bound it will default to using the catalog rootRouteRef "/catalog". From 793610227f556d30dea69ed358bb0599876a8dbc Mon Sep 17 00:00:00 2001 From: Matthew Prinold Date: Fri, 27 Oct 2023 12:57:00 +0100 Subject: [PATCH 07/10] fix(api-report): rebuilt api-report Signed-off-by: Matthew Prinold --- plugins/catalog/api-report.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/catalog/api-report.md b/plugins/catalog/api-report.md index 6647f8deaa..874d294cdc 100644 --- a/plugins/catalog/api-report.md +++ b/plugins/catalog/api-report.md @@ -122,6 +122,7 @@ export const catalogPlugin: BackstagePlugin< }, true >; + unregisterRedirect: ExternalRouteRef; } >; From 3014f6f374efb8b6b18952c4ae3965fe5a1611d5 Mon Sep 17 00:00:00 2001 From: Matthew Prinold Date: Wed, 15 Nov 2023 08:57:08 +0000 Subject: [PATCH 08/10] refactor(routes): renames unregister redirect external route idto include a namespace Signed-off-by: Matthew Prinold --- plugins/catalog/src/routes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog/src/routes.ts b/plugins/catalog/src/routes.ts index 1926576f70..dcc46c7988 100644 --- a/plugins/catalog/src/routes.ts +++ b/plugins/catalog/src/routes.ts @@ -37,7 +37,7 @@ export const createFromTemplateRouteRef = createExternalRouteRef({ }); export const unregisterRedirectRouteRef = createExternalRouteRef({ - id: 'unregister-redirect', + id: 'catalog:unregister-redirect', optional: true, }); From 45f102992d323b1f5515716619cb70998a627edf Mon Sep 17 00:00:00 2001 From: Matthew Prinold Date: Wed, 15 Nov 2023 08:58:39 +0000 Subject: [PATCH 09/10] docs(changeset): restructures changeset description Signed-off-by: Matthew Prinold --- .changeset/lucky-kids-cough.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.changeset/lucky-kids-cough.md b/.changeset/lucky-kids-cough.md index 2e2bed118e..5ab1856e35 100644 --- a/.changeset/lucky-kids-cough.md +++ b/.changeset/lucky-kids-cough.md @@ -2,4 +2,5 @@ '@backstage/plugin-catalog': patch --- -fixes bug where after unregistering an entity you are redirected to "/". Adds an optional external route "unregisterRedirect" into the catalog plugin which when bound will be navigated to on successful removal of an entity. If the external route is not bound it will default to using the catalog rootRouteRef "/catalog". +- Fixes bug where after unregistering an entity you are redirected to `/`. +- Adds an optional external route `unregisterRedirect` to override this behaviour to another route. From b4c0d96978bf4ac7cbc9228f23d3a969c3ab39fe Mon Sep 17 00:00:00 2001 From: Matthew Prinold Date: Wed, 15 Nov 2023 11:30:26 +0000 Subject: [PATCH 10/10] fix(EntityLayout.test): mounts rootRouteRef to new tests Signed-off-by: Matthew Prinold --- .../catalog/src/components/EntityLayout/EntityLayout.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx index 9196ad9e8d..c222c2d7b6 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx @@ -266,6 +266,7 @@ describe('EntityLayout', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, );