Merge pull request #7219 from mstergianis/docs/software-catalog-integration

Update plugin software catalog integration docs
This commit is contained in:
Fredrik Adelöw
2021-09-21 09:42:03 +02:00
committed by GitHub
@@ -10,8 +10,8 @@ description: How to integrate a plugin into software catalog
## Steps
1. [Create a plugin](#create-a-plugin)
1. [Export a router with relative routes](#export-a-router)
1. [Import and use router in the APP](#import-and-use-router-in-the-app)
1. [Reading entities from within your plugin](#reading-entities-from-within-your-plugin)
1. [Import your plugin and embed in the entities page](#import-your-plugin-and-embed-in-the-entities-page)
### Create a plugin
@@ -28,98 +28,92 @@ $ yarn create-plugin
Creating the plugin...
```
### Export a router
### Reading entities from within your plugin
Now in the plugin you have a `Router.tsx` file in the `src` folder. By default
it contains only one example route. Create a routing structure needed for your
plugin, keeping in mind that the whole set of routes defined here are going to
be mounted under some different route in the App.
Example:
`my-plugin` consists of 2 different views - `/me` and `/about`. I envision
people integrating it into plugin catalog as a tab named "MyPlugin". Then, my
`Routes.tsx` for the plugin is going to look like:
You can access the currently selected entity using the backstage api
[`useEntity`](../reference/plugin-catalog-react.useentity.md). For example,
```tsx
<Routes>
<Route path="/me" element={<MePage />} />
<Route path="/about" element={<AboutPage />} />
</Routes>
```
import { useEntity } from '@backstage/plugin-catalog-react';
(where MePage and AboutPage are 2 components defined in your plugin and imported
accordingly inside `Router.tsx`)
export const MyPluginEntityContent = () => {
const { entity, loading, error, refresh } = useEntity();
> Pay attention, if your `MePage` references the `AboutPage` it needs to do it
> through link to `about`, not `/about`. This allows react-router v6 to enable
> its relative routing mechanism. Read more -
> https://reacttraining.com/blog/react-router-v6-pre/#relative-route-path-and-link-to
### Import and use router in the APP
In the `app/src/components/catalog/EntityPage.tsx` (app === your folder,
containing Backstage app) import your created Router:
```tsx
import { Router as MyPluginRouter } from '@backstage/plugin-my-plugin;
```
Now, you need to mount `MyPluginRouter` onto some route, for example if you had:
```tsx
const DefaultEntityPage = ({ entity }: { entity: Entity }) => (
<EntityPageLayout>
<EntityPageLayout.Content
path="/"
title="Overview"
element={<OverviewPage entity={entity} />}
/>
</EntityPageLayout>
);
```
after you add your code it becomes:
```tsx
const DefaultEntityPage = ({ entity }: { entity: Entity }) => (
<EntityPageLayout>
<EntityPageLayout.Content
path="/"
title="Overview"
element={<OverviewPage entity={entity} />}
/>
<EntityPageLayout.Content
path="/my-plugin"
title="My Plugin"
element={<MyPluginRouter entity={entity} />}
/>
</EntityPageLayout>
);
```
All of magic happens thanks to the `EntityPageLayout` component, which comes as
an export from `@backstage/plugin-catalog` package.
```tsx
type EntityPageLayoutContentProps = {
/**
* Going to be transformed into react-router v6
* path under the hood. Read more at https://reacttraining.com/blog/react-router-v6-pre
*/
path: string;
/**
* Gets transformed into the title for the tab
*/
title: string;
/**
* Element that is rendered when the location
* matches the path provided
*/
element: JSX.Element;
// Do something with the entity data...
};
```
> You can either pass the entity from App to the plugin's router as a prop or
> use `useEntity` hook from `@backstage/plugin-catalog` directly inside your
> plugin.
Internally `useEntity` makes use of
[react `Context`s](https://reactjs.org/docs/context.html). The entity context is
provided by the entity page into which your plugin will be embedded.
### Import your plugin and embed in the entities page
To begin, you will need to import your plugin in the entities page. Located at
`packages/app/src/components/Catalog/EntityPage.tsx` from the root package of
your backstage app.
```tsx
import { MyPluginEntityContent } from '@backstage/plugin-my-plugin;
```
To add your component to the Entity view, you will need to modify the
`packages/app/src/components/Catalog/EntityPage.tsx`. Depending on the needs of
your plugin, you may only care about certain kinds of
[entities](https://backstage.io/docs/features/software-catalog/descriptor-format),
each of which has its own
[element](https://reactjs.org/docs/rendering-elements.html) for rendering. This
functionality is handled by the `EntitySwitch` component:
```tsx
export const entityPage = (
<EntitySwitch>
<EntitySwitch.Case if={isKind('component')} children={componentPage} />
<EntitySwitch.Case if={isKind('api')} children={apiPage} />
<EntitySwitch.Case if={isKind('group')} children={groupPage} />
<EntitySwitch.Case if={isKind('user')} children={userPage} />
<EntitySwitch.Case if={isKind('system')} children={systemPage} />
<EntitySwitch.Case if={isKind('domain')} children={domainPage} />
<EntitySwitch.Case>{defaultEntityPage}</EntitySwitch.Case>
</EntitySwitch>
);
```
At this point, you will need to modify the specific page where you want your
component to appear. If you are extending the Software Catalog model you will
need to add a new case to the `EntitySwitch`. For adding a plugin to an existing
component type, you modify the existing page. For example, if you want to add
your plugin to the `systemPage`, you can add a new tab by adding an
`EntityLayout.Route` such as below:
```tsx
const systemPage = (
<EntityLayout>
<EntityLayout.Route path="/" title="Overview">
<Grid container spacing={3} alignItems="stretch">
<Grid item md={6}>
<EntityAboutCard variant="gridItem" />
</Grid>
<Grid item md={6}>
<EntityHasComponentsCard variant="gridItem" />
</Grid>
<Grid item md={6}>
<EntityHasApisCard variant="gridItem" />
</Grid>
<Grid item md={6}>
<EntityHasResourcesCard variant="gridItem" />
</Grid>
</Grid>
</EntityLayout.Route>
<EntityLayout.Route path="/diagram" title="Diagram">
<EntitySystemDiagramCard />
</EntityLayout.Route>
{/* Adding a new tab to the system view */}
<EntityLayout.Route path="/your-custom-route" title="CustomTitle">
<MyPluginEntityContent />
</EntityLayout.Route>
</EntityLayout>
);
```