diff --git a/plugins/catalog/src/api/CatalogClient.ts b/plugins/catalog/src/api/CatalogClient.ts index 9ea59aab48..c1160773ff 100644 --- a/plugins/catalog/src/api/CatalogClient.ts +++ b/plugins/catalog/src/api/CatalogClient.ts @@ -68,9 +68,20 @@ export class CatalogClient implements CatalogApi { return await response.json(); } - async getEntityByName(name: string): Promise { + + async getEntity({ + name, + namespace, + kind, + }: { + name: string; + namespace?: string; + kind: string; + }): Promise { const response = await fetch( - `${this.apiOrigin}${this.basePath}/entities/by-name/Component/default/${name}`, + `${this.apiOrigin}${this.basePath}/entities/by-name/${kind}/${ + namespace ?? 'default' + }/${name}`, ); const entity = await response.json(); if (entity) return entity; diff --git a/plugins/catalog/src/api/types.ts b/plugins/catalog/src/api/types.ts index 1cfe5736fb..bcaa340036 100644 --- a/plugins/catalog/src/api/types.ts +++ b/plugins/catalog/src/api/types.ts @@ -23,9 +23,13 @@ export const catalogApiRef = createApiRef({ }); export interface CatalogApi { + getEntity(params: { + name: string; + namespace?: string; + kind: string; + }): Promise; getLocationById(id: String): Promise; getEntities(filter?: Record): Promise; - getEntityByName(name: string): Promise; addLocation(type: string, target: string): Promise; getLocationByEntity(entity: Entity): Promise; } diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx index cd91838b06..bea9caf273 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx @@ -30,7 +30,15 @@ const columns: TableColumn[] = [ render: (componentData: any) => ( {componentData.name} diff --git a/plugins/catalog/src/components/ComponentPage/ComponentPage.test.tsx b/plugins/catalog/src/components/ComponentPage/ComponentPage.test.tsx index 252f2d4e3f..98fa6b4408 100644 --- a/plugins/catalog/src/components/ComponentPage/ComponentPage.test.tsx +++ b/plugins/catalog/src/components/ComponentPage/ComponentPage.test.tsx @@ -20,11 +20,12 @@ import { wrapInTestApp } from '@backstage/test-utils'; import { ApiProvider, ApiRegistry, errorApiRef } from '@backstage/core'; import { catalogApiRef, CatalogApi } from '../../api/types'; -const getTestProps = (componentName: string) => { +const getTestProps = (name: string) => { return { match: { params: { - name: componentName, + optionalNamespaceAndName: name, + kind: 'Component', }, }, history: { @@ -46,7 +47,7 @@ describe('ComponentPage', () => { [ catalogApiRef, ({ - async getEntityByName() {}, + async getEntity() {}, } as unknown) as CatalogApi, ], ])} diff --git a/plugins/catalog/src/components/ComponentPage/ComponentPage.tsx b/plugins/catalog/src/components/ComponentPage/ComponentPage.tsx index f26c21b6ca..72aef7fe16 100644 --- a/plugins/catalog/src/components/ComponentPage/ComponentPage.tsx +++ b/plugins/catalog/src/components/ComponentPage/ComponentPage.tsx @@ -40,7 +40,8 @@ const REDIRECT_DELAY = 1000; type ComponentPageProps = { match: { params: { - name: string; + optionalNamespaceAndName: string; + kind: string; }; }; history: { @@ -53,12 +54,13 @@ const ComponentPage: FC = ({ match, history }) => { const [removingPending, setRemovingPending] = useState(false); const showRemovalDialog = () => setConfirmationDialogOpen(true); const hideRemovalDialog = () => setConfirmationDialogOpen(false); - const componentName = match.params.name; + const { optionalNamespaceAndName, kind } = match.params; + const [name, namespace] = optionalNamespaceAndName.split(':').reverse(); const errorApi = useApi(errorApiRef); const catalogApi = useApi(catalogApiRef); const { value: component, error, loading } = useAsync(async () => { - const entity = await catalogApi.getEntityByName(match.params.name); + const entity = await catalogApi.getEntity({ name, namespace, kind }); const location = await catalogApi.getLocationByEntity(entity); return { ...entityToComponent(entity), location }; }); @@ -72,7 +74,7 @@ const ComponentPage: FC = ({ match, history }) => { } }, [error, errorApi, history]); - if (componentName === '') { + if (name === '') { history.push('/catalog'); return null; } diff --git a/plugins/catalog/src/data/component.ts b/plugins/catalog/src/data/component.ts index 86749c6faa..68be7588f0 100644 --- a/plugins/catalog/src/data/component.ts +++ b/plugins/catalog/src/data/component.ts @@ -18,6 +18,7 @@ import { ReactNode } from 'react'; export type Component = { name: string; + namespace?: string; kind: string; metadata: EntityMeta; description: ReactNode; diff --git a/plugins/catalog/src/data/utils.ts b/plugins/catalog/src/data/utils.ts index b731268c41..f84bfee73f 100644 --- a/plugins/catalog/src/data/utils.ts +++ b/plugins/catalog/src/data/utils.ts @@ -24,6 +24,7 @@ import { Component } from './component'; export function entityToComponent(envelope: Entity): Component { return { name: envelope.metadata.name, + namespace: envelope.metadata.namespace, kind: envelope.kind, metadata: envelope.metadata, description: envelope.metadata.annotations?.description ?? 'placeholder', diff --git a/plugins/catalog/src/routes.ts b/plugins/catalog/src/routes.ts index 6498d412b8..69c4e651b4 100644 --- a/plugins/catalog/src/routes.ts +++ b/plugins/catalog/src/routes.ts @@ -25,6 +25,6 @@ export const rootRoute = createRouteRef({ }); export const entityRoute = createRouteRef({ icon: NoIcon, - path: '/catalog/:name/', + path: '/catalog/:kind/:optionalNamespaceAndName/', title: 'Entity', }); diff --git a/plugins/register-component/src/components/RegisterComponentPage/RegisterComponentPage.test.tsx b/plugins/register-component/src/components/RegisterComponentPage/RegisterComponentPage.test.tsx index 48130124b7..4da68fe343 100644 --- a/plugins/register-component/src/components/RegisterComponentPage/RegisterComponentPage.test.tsx +++ b/plugins/register-component/src/components/RegisterComponentPage/RegisterComponentPage.test.tsx @@ -28,7 +28,7 @@ const catalogApi: jest.Mocked = { /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ addLocation: jest.fn((_a, _b) => new Promise(() => {})), getEntities: jest.fn(), - getEntityByName: jest.fn(), + getEntity: jest.fn(), getLocationByEntity: jest.fn(), getLocationById: jest.fn(), }; diff --git a/plugins/register-component/src/components/RegisterComponentResultDialog/RegisterComponentResultDialog.tsx b/plugins/register-component/src/components/RegisterComponentResultDialog/RegisterComponentResultDialog.tsx index 4d158526a0..68b06d1751 100644 --- a/plugins/register-component/src/components/RegisterComponentResultDialog/RegisterComponentResultDialog.tsx +++ b/plugins/register-component/src/components/RegisterComponentResultDialog/RegisterComponentResultDialog.tsx @@ -54,34 +54,39 @@ export const RegisterComponentResultDialog: FC = ({ The following components have been succefully created: - {entities.map((entity: any, index: number) => ( - - - - {generatePath(entityRoute.path, { - name: entity.metadata.name, - })} - - ), - }} - /> - - {index < entities.length - 1 && } - - ))} + {entities.map((entity: any, index: number) => { + const entityPath = generatePath(entityRoute.path, { + optionalNamespaceAndName: [ + entity.metadata.namespace, + entity.metadata.name, + ] + .filter(Boolean) + .join(':'), + kind: entity.kind, + }); + + return ( + + + + {entityPath} + + ), + }} + /> + + {index < entities.length - 1 && } + + ); + })}