Introduce external route for linking to the entity page from the explore plugin
Signed-off-by: Oliver Sand <oliver.sand@sda-se.com>
This commit is contained in:
committed by
Patrik Oldsberg
parent
9d455f69a8
commit
cfc83cac16
@@ -0,0 +1,19 @@
|
||||
---
|
||||
'@backstage/plugin-explore': minor
|
||||
---
|
||||
|
||||
Introduce external route for linking to the entity page from the explore plugin.
|
||||
|
||||
To use the explore plugin you have to bind the external route in your app:
|
||||
|
||||
```typescript
|
||||
const app = createApp({
|
||||
...
|
||||
bindRoutes({ bind }) {
|
||||
...
|
||||
bind(explorePlugin.externalRoutes, {
|
||||
catalogEntity: catalogPlugin.routes.catalogEntity,
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
@@ -33,7 +33,7 @@ import {
|
||||
CostInsightsPage,
|
||||
CostInsightsProjectGrowthInstructionsPage,
|
||||
} from '@backstage/plugin-cost-insights';
|
||||
import { ExplorePage } from '@backstage/plugin-explore';
|
||||
import { ExplorePage, explorePlugin } from '@backstage/plugin-explore';
|
||||
import { GcpProjectsPage } from '@backstage/plugin-gcp-projects';
|
||||
import { GraphiQLPage } from '@backstage/plugin-graphiql';
|
||||
import { LighthousePage } from '@backstage/plugin-lighthouse';
|
||||
@@ -79,6 +79,9 @@ const app = createApp({
|
||||
bind(apiDocsPlugin.externalRoutes, {
|
||||
createComponent: scaffolderPlugin.routes.root,
|
||||
});
|
||||
bind(explorePlugin.externalRoutes, {
|
||||
catalogEntity: catalogPlugin.routes.catalogEntity,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
*/
|
||||
|
||||
import { DomainEntity } from '@backstage/catalog-model';
|
||||
import { render } from '@testing-library/react';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { catalogEntityRouteRef } from '../../routes';
|
||||
import { DomainCard } from './DomainCard';
|
||||
|
||||
describe('<DomainCard />', () => {
|
||||
it('renders a domain card', () => {
|
||||
it('renders a domain card', async () => {
|
||||
const entity: DomainEntity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Domain',
|
||||
@@ -34,9 +34,14 @@ describe('<DomainCard />', () => {
|
||||
owner: 'guest',
|
||||
},
|
||||
};
|
||||
const { getByText } = render(<DomainCard entity={entity} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
const { getByText } = await renderInTestApp(
|
||||
<DomainCard entity={entity} />,
|
||||
{
|
||||
mountedRoutes: {
|
||||
'/catalog/:namespace/:kind/:name': catalogEntityRouteRef,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
expect(getByText('artists')).toBeInTheDocument();
|
||||
expect(getByText('Everything about artists')).toBeInTheDocument();
|
||||
|
||||
@@ -14,15 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { DomainEntity, RELATION_OWNED_BY } from '@backstage/catalog-model';
|
||||
import { ItemCard } from '@backstage/core';
|
||||
import { ItemCard, useRouteRef } from '@backstage/core';
|
||||
import {
|
||||
EntityRefLinks,
|
||||
entityRoute,
|
||||
entityRouteParams,
|
||||
getEntityRelations,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import React from 'react';
|
||||
import { generatePath } from 'react-router-dom';
|
||||
import { catalogEntityRouteRef } from '../../routes';
|
||||
|
||||
type DomainCardProps = {
|
||||
entity: DomainEntity;
|
||||
@@ -30,6 +29,7 @@ type DomainCardProps = {
|
||||
|
||||
export const DomainCard = ({ entity }: DomainCardProps) => {
|
||||
const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);
|
||||
const catalogEntityRoute = useRouteRef(catalogEntityRouteRef);
|
||||
|
||||
return (
|
||||
<ItemCard
|
||||
@@ -44,11 +44,7 @@ export const DomainCard = ({ entity }: DomainCardProps) => {
|
||||
/>
|
||||
}
|
||||
label="Explore"
|
||||
// TODO: Use useRouteRef here to generate the path
|
||||
href={generatePath(
|
||||
`/catalog/${entityRoute.path}`,
|
||||
entityRouteParams(entity),
|
||||
)}
|
||||
href={catalogEntityRoute(entityRouteParams(entity))}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
*/
|
||||
|
||||
import { DomainEntity } from '@backstage/catalog-model';
|
||||
import { render } from '@testing-library/react';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { catalogEntityRouteRef } from '../../routes';
|
||||
import { DomainCardGrid } from './DomainCardGrid';
|
||||
|
||||
describe('<DomainCardGrid />', () => {
|
||||
it('renders a grid of domain cards', () => {
|
||||
it('renders a grid of domain cards', async () => {
|
||||
const entities: DomainEntity[] = [
|
||||
{
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
@@ -44,9 +44,14 @@ describe('<DomainCardGrid />', () => {
|
||||
},
|
||||
},
|
||||
];
|
||||
const { getByText } = render(<DomainCardGrid entities={entities} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
const { getByText } = await renderInTestApp(
|
||||
<DomainCardGrid entities={entities} />,
|
||||
{
|
||||
mountedRoutes: {
|
||||
'/catalog/:namespace/:kind/:name': catalogEntityRouteRef,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
expect(getByText('artists')).toBeInTheDocument();
|
||||
expect(getByText('playback')).toBeInTheDocument();
|
||||
|
||||
@@ -20,6 +20,7 @@ import { catalogApiRef } from '@backstage/plugin-catalog-react';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { waitFor } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { catalogEntityRouteRef } from '../../routes';
|
||||
import { DomainExplorerContent } from './DomainExplorerContent';
|
||||
|
||||
describe('<DomainExplorerContent />', () => {
|
||||
@@ -71,6 +72,11 @@ describe('<DomainExplorerContent />', () => {
|
||||
<Wrapper>
|
||||
<DomainExplorerContent />
|
||||
</Wrapper>,
|
||||
{
|
||||
mountedRoutes: {
|
||||
'/catalog/:namespace/:kind/:name': catalogEntityRouteRef,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
@@ -86,6 +92,11 @@ describe('<DomainExplorerContent />', () => {
|
||||
<Wrapper>
|
||||
<DomainExplorerContent />
|
||||
</Wrapper>,
|
||||
{
|
||||
mountedRoutes: {
|
||||
'/catalog/:namespace/:kind/:name': catalogEntityRouteRef,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
await waitFor(() =>
|
||||
@@ -101,6 +112,11 @@ describe('<DomainExplorerContent />', () => {
|
||||
<Wrapper>
|
||||
<DomainExplorerContent />
|
||||
</Wrapper>,
|
||||
{
|
||||
mountedRoutes: {
|
||||
'/catalog/:namespace/:kind/:name': catalogEntityRouteRef,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
await waitFor(() =>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import { createApiFactory, createPlugin } from '@backstage/core';
|
||||
import { exploreToolsConfigRef } from '@backstage/plugin-explore-react';
|
||||
import { exploreRouteRef } from './routes';
|
||||
import { catalogEntityRouteRef, exploreRouteRef } from './routes';
|
||||
import { exampleTools } from './util/examples';
|
||||
|
||||
export const explorePlugin = createPlugin({
|
||||
@@ -37,4 +37,7 @@ export const explorePlugin = createPlugin({
|
||||
routes: {
|
||||
explore: exploreRouteRef,
|
||||
},
|
||||
externalRoutes: {
|
||||
catalogEntity: catalogEntityRouteRef,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createRouteRef } from '@backstage/core';
|
||||
import { createExternalRouteRef, createRouteRef } from '@backstage/core';
|
||||
|
||||
const NoIcon = () => null;
|
||||
|
||||
@@ -22,3 +22,8 @@ export const exploreRouteRef = createRouteRef({
|
||||
icon: NoIcon,
|
||||
title: 'Explore',
|
||||
});
|
||||
|
||||
export const catalogEntityRouteRef = createExternalRouteRef({
|
||||
id: 'catalog-entity',
|
||||
params: ['namespace', 'kind', 'name'],
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user