Merge pull request #4822 from backstage/rugvip/ents
migrate all entity pages to composability api
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
--
|
||||
'@backstage/create-app': patch
|
||||
|
||||
---
|
||||
|
||||
**Fully migrated the template to the new composability API**
|
||||
|
||||
The `create-app` template is now fully migrated to the new composability API, see [Composability System Migration Documentation](https://backstage.io/docs/plugins/composability) for explanations and more details. The final change which is now done was to migrate the `EntityPage` from being a component built on top of the `EntityPageLayout` and several more custom components, to an element tree built with `EntitySwitch` and `EntityLayout`.
|
||||
|
||||
To apply this change to an existing plugin, it is important that all plugins that you are using have already been migrated. In this case the most crucial piece is that no entity page cards of contents may require the `entity` prop, and they must instead consume the entity from context using `useEntity`.
|
||||
|
||||
Since this change is large with a lot of repeated changes, we'll describe a couple of common cases rather than the entire change. If your entity pages are unchanged from the `create-app` template, you can also just bring in the latest version directly from the [template itself](https://github.com/backstage/backstage/blob/master/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx).
|
||||
|
||||
The first step of the change is to change the `packages/app/src/components/catalog/EntityPage.tsx` export to `entityPage` rather than `EntityPage`. This will require an update to `App.tsx`, which is the only change we need to do outside of `EntityPage.tsx`:
|
||||
|
||||
```diff
|
||||
-import { EntityPage } from './components/catalog/EntityPage';
|
||||
+import { entityPage } from './components/catalog/EntityPage';
|
||||
|
||||
<Route
|
||||
path="/catalog/:namespace/:kind/:name"
|
||||
element={<CatalogEntityPage />}
|
||||
>
|
||||
- <EntityPage />
|
||||
+ {entityPage}
|
||||
</Route>
|
||||
```
|
||||
|
||||
The rest of the changes happen within `EntityPage.tsx`, and can be split into two broad categories, updating page components, and updating switch components.
|
||||
|
||||
#### Migrating Page Components
|
||||
|
||||
Let's start with an example of migrating a user page component. The following is the old code in the template:
|
||||
|
||||
```tsx
|
||||
const UserOverviewContent = ({ entity }: { entity: UserEntity }) => (
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<UserProfileCard entity={entity} variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<OwnershipCard entity={entity} variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
const UserEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayout>
|
||||
<EntityPageLayout.Content
|
||||
path="/*"
|
||||
title="Overview"
|
||||
element={<UserOverviewContent entity={entity as UserEntity} />}
|
||||
/>
|
||||
</EntityPageLayout>
|
||||
);
|
||||
```
|
||||
|
||||
There's the main `UserEntityPage` component, and the `UserOverviewContent` component. Let's start with migrating the page contents, which we do by rendering an element rather than creating a component, as well as replace the cards with their new composability compatible variants. The new cards and content components can be identified by the `Entity` prefix.
|
||||
|
||||
```tsx
|
||||
const userOverviewContent = (
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityUserProfileCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityOwnershipCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
```
|
||||
|
||||
Now let's migrate the page component, again by converting it into a rendered element instead of a component, as well as replacing the use of `EntityPageLayout` with `EntityLayout`.
|
||||
|
||||
```tsx
|
||||
const userPage = (
|
||||
<EntityLayout>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
{userOverviewContent}
|
||||
</EntityLayout.Route>
|
||||
</EntityLayout>
|
||||
);
|
||||
```
|
||||
|
||||
At this point the `userPage` is quite small, so throughout this migration we have inlined the page contents for all pages. This is an optional step, but may help reduce noise. The final page now looks like this:
|
||||
|
||||
```tsx
|
||||
const userPage = (
|
||||
<EntityLayout>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityUserProfileCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityOwnershipCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
</EntityLayout>
|
||||
);
|
||||
```
|
||||
|
||||
#### Migrating Switch Components
|
||||
|
||||
Switch components were used to select what entity page components or cards to render, based on for example the kind of entity. For this example we'll focus on the root `EntityPage` switch component, but the process is the same for example for the CI/CD switcher.
|
||||
|
||||
The old `EntityPage` looked like this:
|
||||
|
||||
```tsx
|
||||
export const EntityPage = () => {
|
||||
const { entity } = useEntity();
|
||||
|
||||
switch (entity?.kind?.toLocaleLowerCase('en-US')) {
|
||||
case 'component':
|
||||
return <ComponentEntityPage entity={entity} />;
|
||||
case 'api':
|
||||
return <ApiEntityPage entity={entity} />;
|
||||
case 'group':
|
||||
return <GroupEntityPage entity={entity} />;
|
||||
case 'user':
|
||||
return <UserEntityPage entity={entity} />;
|
||||
case 'system':
|
||||
return <SystemEntityPage entity={entity} />;
|
||||
case 'domain':
|
||||
return <DomainEntityPage entity={entity} />;
|
||||
case 'location':
|
||||
case 'resource':
|
||||
case 'template':
|
||||
default:
|
||||
return <DefaultEntityPage entity={entity} />;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
In order to migrate to the composability API, we need to make this an element instead of a component, which means we're unable to keep the switch statement as is. To help with this, the catalog plugin provides an `EntitySwitch` component, which functions similar to a regular `switch` statement, which the first match being the one that is rendered. The catalog plugin also provides a number of built-in filter functions to use, such as `isKind` and `isComponentType`.
|
||||
|
||||
To migrate the `EntityPage`, we convert the `switch` statement into an `EntitySwitch` element, and each `case` statement into an `EntitySwitch.Case` element. We also move over to use our new element version of the page components, with the result looking like this:
|
||||
|
||||
```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>
|
||||
);
|
||||
```
|
||||
|
||||
Another example is the `ComponentEntityPage`, which is migrated from this:
|
||||
|
||||
```tsx
|
||||
export const ComponentEntityPage = ({ entity }: { entity: Entity }) => {
|
||||
switch (entity?.spec?.type) {
|
||||
case 'service':
|
||||
return <ServiceEntityPage entity={entity} />;
|
||||
case 'website':
|
||||
return <WebsiteEntityPage entity={entity} />;
|
||||
default:
|
||||
return <DefaultEntityPage entity={entity} />;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
To this:
|
||||
|
||||
```tsx
|
||||
const componentPage = (
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isComponentType('service')}>
|
||||
{serviceEntityPage}
|
||||
</EntitySwitch.Case>
|
||||
|
||||
<EntitySwitch.Case if={isComponentType('website')}>
|
||||
{websiteEntityPage}
|
||||
</EntitySwitch.Case>
|
||||
|
||||
<EntitySwitch.Case>{defaultEntityPage}</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
);
|
||||
```
|
||||
|
||||
Note that if you want to conditionally render some piece of content, you can omit the default `EntitySwitch.Case`. If no case is matched in an `EntitySwitch`, nothing will be rendered.
|
||||
@@ -42,10 +42,10 @@
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@octokit/rest": "^18.0.12",
|
||||
"@roadiehq/backstage-plugin-buildkite": "^0.1.3",
|
||||
"@roadiehq/backstage-plugin-github-insights": "^0.3.2",
|
||||
"@roadiehq/backstage-plugin-github-pull-requests": "^0.7.6",
|
||||
"@roadiehq/backstage-plugin-travis-ci": "^0.4.5",
|
||||
"@roadiehq/backstage-plugin-buildkite": "^0.3.0",
|
||||
"@roadiehq/backstage-plugin-github-insights": "^0.3.3",
|
||||
"@roadiehq/backstage-plugin-github-pull-requests": "^0.7.9",
|
||||
"@roadiehq/backstage-plugin-travis-ci": "^0.4.7",
|
||||
"history": "^5.0.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.12.0",
|
||||
|
||||
@@ -48,8 +48,8 @@ import React from 'react';
|
||||
import { hot } from 'react-hot-loader/root';
|
||||
import { Navigate, Route } from 'react-router';
|
||||
import { apis } from './apis';
|
||||
import { EntityPage } from './components/catalog/EntityPage';
|
||||
import { Root } from './components/Root';
|
||||
import { entityPage } from './components/catalog/EntityPage';
|
||||
import { providers } from './identityProviders';
|
||||
import * as plugins from './plugins';
|
||||
|
||||
@@ -96,7 +96,7 @@ const routes = (
|
||||
path="/catalog/:namespace/:kind/:name"
|
||||
element={<CatalogEntityPage />}
|
||||
>
|
||||
<EntityPage />
|
||||
{entityPage}
|
||||
</Route>
|
||||
<Route path="/catalog-import" element={<CatalogImportPage />} />
|
||||
<Route path="/docs" element={<TechdocsPage />} />
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { CICDSwitcher } from './EntityPage';
|
||||
import { UrlPatternDiscovery, ApiProvider, ApiRegistry } from '@backstage/core';
|
||||
import {
|
||||
buildKiteApiRef,
|
||||
BuildkiteApi,
|
||||
} from '@roadiehq/backstage-plugin-buildkite';
|
||||
import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core';
|
||||
import { EntityLayout } from '@backstage/plugin-catalog';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { cicdContent } from './EntityPage';
|
||||
import { githubActionsApiRef } from '@backstage/plugin-github-actions';
|
||||
|
||||
describe('EntityPage Test', () => {
|
||||
const entity = {
|
||||
@@ -29,7 +29,7 @@ describe('EntityPage Test', () => {
|
||||
metadata: {
|
||||
name: 'ExampleComponent',
|
||||
annotations: {
|
||||
'buildkite.com/project-slug': 'exampleProject/examplePipeline',
|
||||
'github.com/project-slug': 'example/project',
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
@@ -39,24 +39,36 @@ describe('EntityPage Test', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const discoveryApi = UrlPatternDiscovery.compile('http://exampleapi.com');
|
||||
const mockedApi = {
|
||||
listWorkflowRuns: jest.fn().mockResolvedValue([]),
|
||||
getWorkflow: jest.fn(),
|
||||
getWorkflowRun: jest.fn(),
|
||||
reRunWorkflow: jest.fn(),
|
||||
downloadJobLogsForWorkflowRun: jest.fn(),
|
||||
} as jest.Mocked<typeof githubActionsApiRef.T>;
|
||||
|
||||
const apis = ApiRegistry.from([
|
||||
[buildKiteApiRef, new BuildkiteApi({ discoveryApi })],
|
||||
]);
|
||||
const apis = ApiRegistry.with(githubActionsApiRef, mockedApi);
|
||||
|
||||
describe('CICDSwitcher Test', () => {
|
||||
it('Should render Buildkite View', async () => {
|
||||
const renderedComponent = await renderWithEffects(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<CICDSwitcher entity={entity} />
|
||||
</ApiProvider>,
|
||||
),
|
||||
describe('cicdContent', () => {
|
||||
it('Should render GitHub Actions View', async () => {
|
||||
const rendered = await renderInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<EntityProvider entity={entity}>
|
||||
<EntityLayout>
|
||||
<EntityLayout.Route path="/ci-cd" title="CI-CD">
|
||||
{cicdContent}
|
||||
</EntityLayout.Route>
|
||||
</EntityLayout>
|
||||
</EntityProvider>
|
||||
</ApiProvider>,
|
||||
);
|
||||
expect(
|
||||
renderedComponent.getByText(/exampleProject\/examplePipeline/),
|
||||
).toBeInTheDocument();
|
||||
|
||||
expect(rendered.getByText('ExampleComponent')).toBeInTheDocument();
|
||||
|
||||
await expect(
|
||||
rendered.findByText('No Workflow Data'),
|
||||
).resolves.toBeInTheDocument();
|
||||
expect(rendered.getByText('Create new Workflow')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,174 +14,96 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ApiEntity,
|
||||
DomainEntity,
|
||||
Entity,
|
||||
GroupEntity,
|
||||
SystemEntity,
|
||||
UserEntity,
|
||||
} from '@backstage/catalog-model';
|
||||
import React, { ReactNode, useMemo, useState } from 'react';
|
||||
import BadgeIcon from '@material-ui/icons/CallToAction';
|
||||
import { EmptyState } from '@backstage/core';
|
||||
import {
|
||||
ApiDefinitionCard,
|
||||
ConsumedApisCard,
|
||||
ConsumingComponentsCard,
|
||||
EntityApiDefinitionCard,
|
||||
EntityConsumingComponentsCard,
|
||||
EntityHasApisCard,
|
||||
ProvidedApisCard,
|
||||
ProvidingComponentsCard,
|
||||
EntityProvidingComponentsCard,
|
||||
EntityProvidedApisCard,
|
||||
EntityConsumedApisCard,
|
||||
} from '@backstage/plugin-api-docs';
|
||||
import { EntityBadgesDialog } from '@backstage/plugin-badges';
|
||||
import {
|
||||
AboutCard,
|
||||
EntityAboutCard,
|
||||
EntityHasComponentsCard,
|
||||
EntityHasSubcomponentsCard,
|
||||
EntityHasSystemsCard,
|
||||
EntityLayout,
|
||||
EntityLinksCard,
|
||||
EntityPageLayout,
|
||||
EntitySystemDiagramCard,
|
||||
EntitySwitch,
|
||||
isComponentType,
|
||||
isKind,
|
||||
} from '@backstage/plugin-catalog';
|
||||
import { EntityProvider, useEntity } from '@backstage/plugin-catalog-react';
|
||||
import {
|
||||
isPluginApplicableToEntity as isCircleCIAvailable,
|
||||
Router as CircleCIRouter,
|
||||
EntityCircleCIContent,
|
||||
isCircleCIAvailable,
|
||||
} from '@backstage/plugin-circleci';
|
||||
import {
|
||||
isPluginApplicableToEntity as isCloudbuildAvailable,
|
||||
Router as CloudbuildRouter,
|
||||
EntityCloudbuildContent,
|
||||
isCloudbuildAvailable,
|
||||
} from '@backstage/plugin-cloudbuild';
|
||||
import {
|
||||
isPluginApplicableToEntity as isGitHubActionsAvailable,
|
||||
RecentWorkflowRunsCard,
|
||||
Router as GitHubActionsRouter,
|
||||
EntityGithubActionsContent,
|
||||
EntityRecentGithubActionsRunsCard,
|
||||
isGithubActionsAvailable,
|
||||
} from '@backstage/plugin-github-actions';
|
||||
import {
|
||||
isPluginApplicableToEntity as isJenkinsAvailable,
|
||||
LatestRunCard as JenkinsLatestRunCard,
|
||||
Router as JenkinsRouter,
|
||||
EntityJenkinsContent,
|
||||
EntityLatestJenkinsRunCard,
|
||||
isJenkinsAvailable,
|
||||
} from '@backstage/plugin-jenkins';
|
||||
import { Router as KafkaRouter } from '@backstage/plugin-kafka';
|
||||
import { Router as KubernetesRouter } from '@backstage/plugin-kubernetes';
|
||||
import { EntityKafkaContent } from '@backstage/plugin-kafka';
|
||||
import { EntityKubernetesContent } from '@backstage/plugin-kubernetes';
|
||||
import {
|
||||
EmbeddedRouter as LighthouseRouter,
|
||||
isPluginApplicableToEntity as isLighthouseAvailable,
|
||||
LastLighthouseAuditCard,
|
||||
EntityLastLighthouseAuditCard,
|
||||
EntityLighthouseContent,
|
||||
isLighthouseAvailable,
|
||||
} from '@backstage/plugin-lighthouse';
|
||||
import {
|
||||
GroupProfileCard,
|
||||
MembersListCard,
|
||||
OwnershipCard,
|
||||
UserProfileCard,
|
||||
EntityGroupProfileCard,
|
||||
EntityMembersListCard,
|
||||
EntityOwnershipCard,
|
||||
EntityUserProfileCard,
|
||||
} from '@backstage/plugin-org';
|
||||
import {
|
||||
isPluginApplicableToEntity as isPagerDutyAvailable,
|
||||
PagerDutyCard,
|
||||
EntityPagerDutyCard,
|
||||
isPagerDutyAvailable,
|
||||
} from '@backstage/plugin-pagerduty';
|
||||
import {
|
||||
EntityRollbarContent,
|
||||
isRollbarAvailable,
|
||||
Router as RollbarRouter,
|
||||
} from '@backstage/plugin-rollbar';
|
||||
import { Router as SentryRouter } from '@backstage/plugin-sentry';
|
||||
import { EmbeddedDocsRouter as DocsRouter } from '@backstage/plugin-techdocs';
|
||||
import { EntitySentryContent } from '@backstage/plugin-sentry';
|
||||
import { EntityTechdocsContent } from '@backstage/plugin-techdocs';
|
||||
import { EntityTodoContent } from '@backstage/plugin-todo';
|
||||
import { Button, Grid } from '@material-ui/core';
|
||||
import {
|
||||
isPluginApplicableToEntity as isBuildkiteAvailable,
|
||||
Router as BuildkiteRouter,
|
||||
} from '@roadiehq/backstage-plugin-buildkite';
|
||||
import {
|
||||
isPluginApplicableToEntity as isGitHubAvailable,
|
||||
LanguagesCard,
|
||||
ReadMeCard,
|
||||
ReleasesCard,
|
||||
Router as GitHubInsightsRouter,
|
||||
} from '@roadiehq/backstage-plugin-github-insights';
|
||||
import {
|
||||
isPluginApplicableToEntity as isPullRequestsAvailable,
|
||||
PullRequestsStatsCard,
|
||||
Router as PullRequestsRouter,
|
||||
} from '@roadiehq/backstage-plugin-github-pull-requests';
|
||||
import {
|
||||
isPluginApplicableToEntity as isTravisCIAvailable,
|
||||
RecentTravisCIBuildsWidget,
|
||||
Router as TravisCIRouter,
|
||||
} from '@roadiehq/backstage-plugin-travis-ci';
|
||||
import React, { ReactNode, useMemo, useState } from 'react';
|
||||
import BadgeIcon from '@material-ui/icons/CallToAction';
|
||||
// import {
|
||||
// EntityBuildkiteContent,
|
||||
// isBuildkiteAvailable,
|
||||
// } from '@roadiehq/backstage-plugin-buildkite';
|
||||
// import {
|
||||
// EntityGitHubInsightsContent,
|
||||
// EntityLanguagesCard,
|
||||
// EntityReadMeCard,
|
||||
// EntityReleasesCard,
|
||||
// isGithubInsightsAvailable,
|
||||
// } from '@roadiehq/backstage-plugin-github-insights';
|
||||
// import {
|
||||
// EntityGithubPullRequestsContent,
|
||||
// EntityGithubPullRequestsOverviewCard,
|
||||
// isGithubPullRequestsAvailable,
|
||||
// } from '@roadiehq/backstage-plugin-github-pull-requests';
|
||||
// import {
|
||||
// EntityTravisCIContent,
|
||||
// EntityTravisCIOverviewCard,
|
||||
// isTravisciAvailable,
|
||||
// } from '@roadiehq/backstage-plugin-travis-ci';
|
||||
|
||||
export const CICDSwitcher = ({ entity }: { entity: Entity }) => {
|
||||
// This component is just an example of how you can implement your company's logic in entity page.
|
||||
// You can for example enforce that all components of type 'service' should use GitHubActions
|
||||
switch (true) {
|
||||
case isJenkinsAvailable(entity):
|
||||
return <JenkinsRouter entity={entity} />;
|
||||
case isBuildkiteAvailable(entity):
|
||||
return <BuildkiteRouter entity={entity} />;
|
||||
case isCircleCIAvailable(entity):
|
||||
return <CircleCIRouter entity={entity} />;
|
||||
case isCloudbuildAvailable(entity):
|
||||
return <CloudbuildRouter entity={entity} />;
|
||||
case isTravisCIAvailable(entity):
|
||||
return <TravisCIRouter entity={entity} />;
|
||||
case isGitHubActionsAvailable(entity):
|
||||
return <GitHubActionsRouter entity={entity} />;
|
||||
default:
|
||||
return (
|
||||
<EmptyState
|
||||
title="No CI/CD available for this entity"
|
||||
missing="info"
|
||||
description="You need to add an annotation to your component if you want to enable CI/CD for it. You can read more about annotations in Backstage by clicking the button below."
|
||||
action={
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
href="https://backstage.io/docs/features/software-catalog/well-known-annotations"
|
||||
>
|
||||
Read more
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const RecentCICDRunsSwitcher = ({ entity }: { entity: Entity }) => {
|
||||
let content: ReactNode;
|
||||
switch (true) {
|
||||
case isJenkinsAvailable(entity):
|
||||
content = <JenkinsLatestRunCard branch="master" variant="gridItem" />;
|
||||
break;
|
||||
case isTravisCIAvailable(entity):
|
||||
content = <RecentTravisCIBuildsWidget entity={entity} />;
|
||||
break;
|
||||
case isGitHubActionsAvailable(entity):
|
||||
content = (
|
||||
<RecentWorkflowRunsCard entity={entity} limit={4} variant="gridItem" />
|
||||
);
|
||||
break;
|
||||
default:
|
||||
content = null;
|
||||
}
|
||||
if (!content) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<Grid item sm={6}>
|
||||
{content}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export const ErrorsSwitcher = ({ entity }: { entity: Entity }) => {
|
||||
switch (true) {
|
||||
case isRollbarAvailable(entity):
|
||||
return <RollbarRouter entity={entity} />;
|
||||
default:
|
||||
return <SentryRouter entity={entity} />;
|
||||
}
|
||||
};
|
||||
|
||||
const EntityPageLayoutWrapper = (props: { children?: React.ReactNode }) => {
|
||||
const EntityLayoutWrapper = (props: { children?: ReactNode }) => {
|
||||
const [badgesDialogOpen, setBadgesDialogOpen] = useState(false);
|
||||
|
||||
const extraMenuItems = useMemo(() => {
|
||||
@@ -196,9 +118,9 @@ const EntityPageLayoutWrapper = (props: { children?: React.ReactNode }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<EntityPageLayout UNSTABLE_extraContextMenuItems={extraMenuItems}>
|
||||
<EntityLayout UNSTABLE_extraContextMenuItems={extraMenuItems}>
|
||||
{props.children}
|
||||
</EntityPageLayout>
|
||||
</EntityLayout>
|
||||
<EntityBadgesDialog
|
||||
open={badgesDialogOpen}
|
||||
onClose={() => setBadgesDialogOpen(false)}
|
||||
@@ -207,350 +129,367 @@ const EntityPageLayoutWrapper = (props: { children?: React.ReactNode }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const ComponentOverviewContent = ({ entity }: { entity: Entity }) => (
|
||||
export const cicdContent = (
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isJenkinsAvailable}>
|
||||
<EntityJenkinsContent />
|
||||
</EntitySwitch.Case>
|
||||
|
||||
{/* <EntitySwitch.Case if={isBuildkiteAvailable}>
|
||||
<EntityBuildkiteContent />
|
||||
</EntitySwitch.Case> */}
|
||||
|
||||
<EntitySwitch.Case if={isCircleCIAvailable}>
|
||||
<EntityCircleCIContent />
|
||||
</EntitySwitch.Case>
|
||||
|
||||
<EntitySwitch.Case if={isCloudbuildAvailable}>
|
||||
<EntityCloudbuildContent />
|
||||
</EntitySwitch.Case>
|
||||
|
||||
{/* <EntitySwitch.Case if={isTravisciAvailable}>
|
||||
<EntityTravisCIContent />
|
||||
</EntitySwitch.Case> */}
|
||||
|
||||
<EntitySwitch.Case if={isGithubActionsAvailable}>
|
||||
<EntityGithubActionsContent />
|
||||
</EntitySwitch.Case>
|
||||
|
||||
<EntitySwitch.Case>
|
||||
<EmptyState
|
||||
title="No CI/CD available for this entity"
|
||||
missing="info"
|
||||
description="You need to add an annotation to your component if you want to enable CI/CD for it. You can read more about annotations in Backstage by clicking the button below."
|
||||
action={
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
href="https://backstage.io/docs/features/software-catalog/well-known-annotations"
|
||||
>
|
||||
Read more
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
);
|
||||
|
||||
const cicdCard = (
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isJenkinsAvailable}>
|
||||
<Grid item sm={6}>
|
||||
<EntityLatestJenkinsRunCard branch="master" variant="gridItem" />
|
||||
</Grid>
|
||||
</EntitySwitch.Case>
|
||||
|
||||
{/* <EntitySwitch.Case if={isTravisciAvailable}>
|
||||
<Grid item sm={6}>
|
||||
<EntityTravisCIOverviewCard />
|
||||
</Grid>
|
||||
</EntitySwitch.Case> */}
|
||||
|
||||
<EntitySwitch.Case if={isGithubActionsAvailable}>
|
||||
<Grid item sm={6}>
|
||||
<EntityRecentGithubActionsRunsCard limit={4} variant="gridItem" />
|
||||
</Grid>
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
);
|
||||
|
||||
const errorsContent = (
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isRollbarAvailable}>
|
||||
<EntityRollbarContent />
|
||||
</EntitySwitch.Case>
|
||||
|
||||
<EntitySwitch.Case>
|
||||
<EntitySentryContent />
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
);
|
||||
|
||||
const overviewContent = (
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item xs={12} md={6}>
|
||||
<AboutCard entity={entity} variant="gridItem" />
|
||||
<Grid item md={6}>
|
||||
<EntityAboutCard variant="gridItem" />
|
||||
</Grid>
|
||||
{isPagerDutyAvailable(entity) && (
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityProvider entity={entity}>
|
||||
<PagerDutyCard />
|
||||
</EntityProvider>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityLinksCard entity={entity} />
|
||||
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isPagerDutyAvailable}>
|
||||
<Grid item md={6}>
|
||||
<EntityPagerDutyCard />
|
||||
</Grid>
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
|
||||
<Grid item md={4} sm={6}>
|
||||
<EntityLinksCard />
|
||||
</Grid>
|
||||
<RecentCICDRunsSwitcher entity={entity} />
|
||||
{isGitHubAvailable(entity) && (
|
||||
<>
|
||||
<Grid item xs={12} md={6}>
|
||||
<LanguagesCard entity={entity} />
|
||||
<ReleasesCard entity={entity} />
|
||||
|
||||
{cicdCard}
|
||||
|
||||
{/* <EntitySwitch>
|
||||
<EntitySwitch.Case if={e => Boolean(isGithubInsightsAvailable(e))}>
|
||||
<Grid item md={6}>
|
||||
<EntityLanguagesCard />
|
||||
<EntityReleasesCard />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<ReadMeCard entity={entity} maxHeight={350} />
|
||||
<Grid item md={6}>
|
||||
<EntityReadMeCard maxHeight={350} />
|
||||
</Grid>
|
||||
</>
|
||||
)}
|
||||
{isLighthouseAvailable(entity) && (
|
||||
<Grid item xs={12} sm={4}>
|
||||
<LastLighthouseAuditCard variant="gridItem" />
|
||||
</Grid>
|
||||
)}
|
||||
{isPullRequestsAvailable(entity) && (
|
||||
<Grid item xs={12} sm={4}>
|
||||
<PullRequestsStatsCard entity={entity} />
|
||||
</Grid>
|
||||
)}
|
||||
<Grid item xs={12} md={6}>
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch> */}
|
||||
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isLighthouseAvailable}>
|
||||
<Grid item sm={4}>
|
||||
<EntityLastLighthouseAuditCard variant="gridItem" />
|
||||
</Grid>
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
|
||||
{/* <EntitySwitch>
|
||||
<EntitySwitch.Case if={e => Boolean(isGithubPullRequestsAvailable(e))}>
|
||||
<Grid item sm={4}>
|
||||
<EntityGithubPullRequestsOverviewCard />
|
||||
</Grid>
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch> */}
|
||||
|
||||
<Grid item md={6}>
|
||||
<EntityHasSubcomponentsCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
const ComponentApisContent = ({ entity }: { entity: Entity }) => (
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item xs={12} md={6}>
|
||||
<ProvidedApisCard entity={entity} />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<ConsumedApisCard entity={entity} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
const serviceEntityPage = (
|
||||
<EntityLayoutWrapper>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
{overviewContent}
|
||||
</EntityLayout.Route>
|
||||
|
||||
const ServiceEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayoutWrapper>
|
||||
<EntityPageLayout.Content
|
||||
path="/"
|
||||
title="Overview"
|
||||
element={<ComponentOverviewContent entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/ci-cd/*"
|
||||
title="CI/CD"
|
||||
element={<CICDSwitcher entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/errors/*"
|
||||
title="Errors"
|
||||
element={<ErrorsSwitcher entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/api/*"
|
||||
title="API"
|
||||
element={<ComponentApisContent entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/docs/*"
|
||||
title="Docs"
|
||||
element={<DocsRouter entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/kubernetes/*"
|
||||
title="Kubernetes"
|
||||
element={<KubernetesRouter entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/pull-requests"
|
||||
title="Pull Requests"
|
||||
element={<PullRequestsRouter entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/code-insights"
|
||||
title="Code Insights"
|
||||
element={<GitHubInsightsRouter entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/kafka/*"
|
||||
title="Kafka"
|
||||
element={<KafkaRouter entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/todos"
|
||||
title="TODOs"
|
||||
element={<EntityTodoContent />}
|
||||
/>
|
||||
</EntityPageLayoutWrapper>
|
||||
);
|
||||
<EntityLayout.Route path="/ci-cd" title="CI/CD">
|
||||
{cicdContent}
|
||||
</EntityLayout.Route>
|
||||
|
||||
const WebsiteEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayoutWrapper>
|
||||
<EntityPageLayout.Content
|
||||
path="/"
|
||||
title="Overview"
|
||||
element={<ComponentOverviewContent entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/ci-cd/*"
|
||||
title="CI/CD"
|
||||
element={<CICDSwitcher entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/lighthouse/*"
|
||||
title="Lighthouse"
|
||||
element={<LighthouseRouter entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/errors/*"
|
||||
title="Errors"
|
||||
element={<ErrorsSwitcher entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/docs/*"
|
||||
title="Docs"
|
||||
element={<DocsRouter entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/kubernetes/*"
|
||||
title="Kubernetes"
|
||||
element={<KubernetesRouter entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/pull-requests"
|
||||
title="Pull Requests"
|
||||
element={<PullRequestsRouter entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/code-insights"
|
||||
title="Code Insights"
|
||||
element={<GitHubInsightsRouter entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/todos"
|
||||
title="TODOs"
|
||||
element={<EntityTodoContent />}
|
||||
/>
|
||||
</EntityPageLayoutWrapper>
|
||||
);
|
||||
<EntityLayout.Route path="/errors" title="Errors">
|
||||
{errorsContent}
|
||||
</EntityLayout.Route>
|
||||
|
||||
const DefaultEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayoutWrapper>
|
||||
<EntityPageLayout.Content
|
||||
path="/*"
|
||||
title="Overview"
|
||||
element={<ComponentOverviewContent entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/docs/*"
|
||||
title="Docs"
|
||||
element={<DocsRouter entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/todos"
|
||||
title="TODOs"
|
||||
element={<EntityTodoContent />}
|
||||
/>
|
||||
</EntityPageLayoutWrapper>
|
||||
);
|
||||
|
||||
export const ComponentEntityPage = ({ entity }: { entity: Entity }) => {
|
||||
switch (entity?.spec?.type) {
|
||||
case 'service':
|
||||
return <ServiceEntityPage entity={entity} />;
|
||||
case 'website':
|
||||
return <WebsiteEntityPage entity={entity} />;
|
||||
default:
|
||||
return <DefaultEntityPage entity={entity} />;
|
||||
}
|
||||
};
|
||||
|
||||
const ApiOverviewContent = ({ entity }: { entity: Entity }) => (
|
||||
<Grid container spacing={3}>
|
||||
<Grid item md={6}>
|
||||
<AboutCard entity={entity} />
|
||||
</Grid>
|
||||
<Grid container item md={12}>
|
||||
<Grid item md={6}>
|
||||
<ProvidingComponentsCard entity={entity} />
|
||||
<EntityLayout.Route path="/api" title="API">
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item md={6}>
|
||||
<EntityProvidedApisCard />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityConsumedApisCard />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<ConsumingComponentsCard entity={entity} />
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/docs" title="Docs">
|
||||
<EntityTechdocsContent />
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/kubernetes" title="Kubernetes">
|
||||
<EntityKubernetesContent />
|
||||
</EntityLayout.Route>
|
||||
|
||||
{/* <EntityLayout.Route path="/pull-requests" title="Pull Requests">
|
||||
<EntityGithubPullRequestsContent />
|
||||
</EntityLayout.Route> */}
|
||||
|
||||
{/* <EntityLayout.Route path="/code-insights" title="Code Insights">
|
||||
<EntityGitHubInsightsContent />
|
||||
</EntityLayout.Route> */}
|
||||
|
||||
<EntityLayout.Route path="/kafka" title="Kafka">
|
||||
<EntityKafkaContent />
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/todos" title="TODOs">
|
||||
<EntityTodoContent />
|
||||
</EntityLayout.Route>
|
||||
</EntityLayoutWrapper>
|
||||
);
|
||||
|
||||
const websiteEntityPage = (
|
||||
<EntityLayoutWrapper>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
{overviewContent}
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/ci-cd" title="CI/CD">
|
||||
{cicdContent}
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/lighthouse" title="Lighthouse">
|
||||
<EntityLighthouseContent />
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/errors" title="Errors">
|
||||
{errorsContent}
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/docs" title="Docs">
|
||||
<EntityTechdocsContent />
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/kubernetes" title="Kubernetes">
|
||||
<EntityKubernetesContent />
|
||||
</EntityLayout.Route>
|
||||
|
||||
{/* <EntityLayout.Route path="/pull-requests" title="Pull Requests">
|
||||
<EntityGithubPullRequestsContent />
|
||||
</EntityLayout.Route> */}
|
||||
|
||||
{/* <EntityLayout.Route path="/code-insights" title="Code Insights">
|
||||
<EntityGithubInsightsContent />
|
||||
</EntityLayout.Route> */}
|
||||
|
||||
<EntityLayout.Route path="/todos" title="TODOs">
|
||||
<EntityTodoContent />
|
||||
</EntityLayout.Route>
|
||||
</EntityLayoutWrapper>
|
||||
);
|
||||
|
||||
const defaultEntityPage = (
|
||||
<EntityLayoutWrapper>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
{overviewContent}
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/docs" title="Docs">
|
||||
<EntityTechdocsContent />
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/todos" title="TODOs">
|
||||
<EntityTodoContent />
|
||||
</EntityLayout.Route>
|
||||
</EntityLayoutWrapper>
|
||||
);
|
||||
|
||||
const componentPage = (
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isComponentType('service')}>
|
||||
{serviceEntityPage}
|
||||
</EntitySwitch.Case>
|
||||
|
||||
<EntitySwitch.Case if={isComponentType('website')}>
|
||||
{websiteEntityPage}
|
||||
</EntitySwitch.Case>
|
||||
|
||||
<EntitySwitch.Case>{defaultEntityPage}</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
);
|
||||
|
||||
const apiPage = (
|
||||
<EntityLayoutWrapper>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
<Grid container spacing={3}>
|
||||
<Grid item md={6}>
|
||||
<EntityAboutCard />
|
||||
</Grid>
|
||||
<Grid container item md={12}>
|
||||
<Grid item md={6}>
|
||||
<EntityProvidingComponentsCard />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityConsumingComponentsCard />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/definition" title="Definition">
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12}>
|
||||
<EntityApiDefinitionCard />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
</EntityLayoutWrapper>
|
||||
);
|
||||
|
||||
const ApiDefinitionContent = ({ entity }: { entity: ApiEntity }) => (
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12}>
|
||||
<ApiDefinitionCard apiEntity={entity} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
const userPage = (
|
||||
<EntityLayoutWrapper>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityUserProfileCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityOwnershipCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
</EntityLayoutWrapper>
|
||||
);
|
||||
|
||||
const ApiEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayoutWrapper>
|
||||
<EntityPageLayout.Content
|
||||
path="/*"
|
||||
title="Overview"
|
||||
element={<ApiOverviewContent entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/definition/*"
|
||||
title="Definition"
|
||||
element={<ApiDefinitionContent entity={entity as ApiEntity} />}
|
||||
/>
|
||||
</EntityPageLayoutWrapper>
|
||||
const groupPage = (
|
||||
<EntityLayoutWrapper>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityGroupProfileCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityOwnershipCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<EntityMembersListCard />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/diagram" title="Diagram">
|
||||
<EntitySystemDiagramCard />
|
||||
</EntityLayout.Route>
|
||||
</EntityLayoutWrapper>
|
||||
);
|
||||
|
||||
const UserOverviewContent = ({ entity }: { entity: UserEntity }) => (
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<UserProfileCard entity={entity} variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<OwnershipCard entity={entity} variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
const systemPage = (
|
||||
<EntityLayoutWrapper>
|
||||
<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>
|
||||
</EntityLayout.Route>
|
||||
</EntityLayoutWrapper>
|
||||
);
|
||||
|
||||
const UserEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayoutWrapper>
|
||||
<EntityPageLayout.Content
|
||||
path="/*"
|
||||
title="Overview"
|
||||
element={<UserOverviewContent entity={entity as UserEntity} />}
|
||||
/>
|
||||
</EntityPageLayoutWrapper>
|
||||
const domainPage = (
|
||||
<EntityLayoutWrapper>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item md={6}>
|
||||
<EntityAboutCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityHasSystemsCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
</EntityLayoutWrapper>
|
||||
);
|
||||
|
||||
const GroupOverviewContent = ({ entity }: { entity: GroupEntity }) => (
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<GroupProfileCard entity={entity} variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<OwnershipCard entity={entity} variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<MembersListCard entity={entity} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
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>
|
||||
);
|
||||
|
||||
const GroupEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayoutWrapper>
|
||||
<EntityPageLayout.Content
|
||||
path="/*"
|
||||
title="Overview"
|
||||
element={<GroupOverviewContent entity={entity as GroupEntity} />}
|
||||
/>
|
||||
</EntityPageLayoutWrapper>
|
||||
);
|
||||
|
||||
const SystemOverviewContent = ({ entity }: { entity: SystemEntity }) => (
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item md={6}>
|
||||
<AboutCard entity={entity} variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityHasComponentsCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityHasApisCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
const SystemEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayoutWrapper>
|
||||
<EntityPageLayout.Content
|
||||
path="/*"
|
||||
title="Overview"
|
||||
element={<SystemOverviewContent entity={entity as SystemEntity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/diagram/*"
|
||||
title="Diagram"
|
||||
element={<EntitySystemDiagramCard />}
|
||||
/>
|
||||
</EntityPageLayoutWrapper>
|
||||
);
|
||||
|
||||
const DomainOverviewContent = ({ entity }: { entity: DomainEntity }) => (
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item md={6}>
|
||||
<AboutCard entity={entity} variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityHasSystemsCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
const DomainEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayoutWrapper>
|
||||
<EntityPageLayout.Content
|
||||
path="/*"
|
||||
title="Overview"
|
||||
element={<DomainOverviewContent entity={entity as DomainEntity} />}
|
||||
/>
|
||||
</EntityPageLayoutWrapper>
|
||||
);
|
||||
|
||||
export const EntityPage = () => {
|
||||
const { entity } = useEntity();
|
||||
|
||||
switch (entity?.kind?.toLocaleLowerCase('en-US')) {
|
||||
case 'component':
|
||||
return <ComponentEntityPage entity={entity} />;
|
||||
case 'api':
|
||||
return <ApiEntityPage entity={entity} />;
|
||||
case 'group':
|
||||
return <GroupEntityPage entity={entity} />;
|
||||
case 'user':
|
||||
return <UserEntityPage entity={entity} />;
|
||||
case 'system':
|
||||
return <SystemEntityPage entity={entity} />;
|
||||
case 'domain':
|
||||
return <DomainEntityPage entity={entity} />;
|
||||
case 'location':
|
||||
case 'resource':
|
||||
case 'template':
|
||||
default:
|
||||
return <DefaultEntityPage entity={entity} />;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@ import { TechRadarPage } from '@backstage/plugin-tech-radar';
|
||||
import { TechdocsPage } from '@backstage/plugin-techdocs';
|
||||
import { UserSettingsPage } from '@backstage/plugin-user-settings';
|
||||
import { apis } from './apis';
|
||||
import { EntityPage } from './components/catalog/EntityPage';
|
||||
import { entityPage } from './components/catalog/EntityPage';
|
||||
import { Root } from './components/Root';
|
||||
import * as plugins from './plugins';
|
||||
|
||||
@@ -47,7 +47,7 @@ const routes = (
|
||||
path="/catalog/:namespace/:kind/:name"
|
||||
element={<CatalogEntityPage />}
|
||||
>
|
||||
<EntityPage />
|
||||
{entityPage}
|
||||
</Route>
|
||||
<Route path="/docs" element={<TechdocsPage />} />
|
||||
<Route path="/create" element={<ScaffolderPage />} />
|
||||
|
||||
+209
-269
@@ -15,308 +15,248 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
import { Button, Grid } from '@material-ui/core';
|
||||
import {
|
||||
ApiEntity,
|
||||
DomainEntity,
|
||||
Entity,
|
||||
GroupEntity,
|
||||
SystemEntity,
|
||||
UserEntity,
|
||||
} from '@backstage/catalog-model';
|
||||
import { EmptyState } from '@backstage/core';
|
||||
import {
|
||||
ApiDefinitionCard,
|
||||
ConsumedApisCard,
|
||||
ConsumingComponentsCard,
|
||||
EntityApiDefinitionCard,
|
||||
EntityConsumedApisCard,
|
||||
EntityConsumingComponentsCard,
|
||||
EntityHasApisCard,
|
||||
ProvidedApisCard,
|
||||
ProvidingComponentsCard,
|
||||
EntityProvidedApisCard,
|
||||
EntityProvidingComponentsCard,
|
||||
} from '@backstage/plugin-api-docs';
|
||||
import {
|
||||
AboutCard,
|
||||
EntityAboutCard,
|
||||
EntitySystemDiagramCard,
|
||||
EntityHasComponentsCard,
|
||||
EntityHasSystemsCard,
|
||||
EntityPageLayout,
|
||||
EntityLayout,
|
||||
EntitySwitch,
|
||||
isComponentType,
|
||||
isKind,
|
||||
} from '@backstage/plugin-catalog';
|
||||
import { useEntity } from '@backstage/plugin-catalog-react';
|
||||
import {
|
||||
isPluginApplicableToEntity as isGitHubActionsAvailable,
|
||||
Router as GitHubActionsRouter,
|
||||
isGithubActionsAvailable,
|
||||
EntityGithubActionsContent,
|
||||
} from '@backstage/plugin-github-actions';
|
||||
import {
|
||||
GroupProfileCard,
|
||||
MembersListCard,
|
||||
OwnershipCard,
|
||||
UserProfileCard,
|
||||
EntityUserProfileCard,
|
||||
EntityGroupProfileCard,
|
||||
EntityMembersListCard,
|
||||
EntityOwnershipCard,
|
||||
} from '@backstage/plugin-org';
|
||||
import { EmbeddedDocsRouter as DocsRouter } from '@backstage/plugin-techdocs';
|
||||
import { EntityTechdocsContent } from '@backstage/plugin-techdocs';
|
||||
|
||||
|
||||
const CICDSwitcher = ({ entity }: { entity: Entity }) => {
|
||||
// This component is just an example of how you can implement your company's logic in entity page.
|
||||
const cicdContent = (
|
||||
// This is an example of how you can implement your company's logic in entity page.
|
||||
// You can for example enforce that all components of type 'service' should use GitHubActions
|
||||
switch (true) {
|
||||
case isGitHubActionsAvailable(entity):
|
||||
return <GitHubActionsRouter entity={entity} />;
|
||||
default:
|
||||
return (
|
||||
<EmptyState
|
||||
title="No CI/CD available for this entity"
|
||||
missing="info"
|
||||
description="You need to add an annotation to your component if you want to enable CI/CD for it. You can read more about annotations in Backstage by clicking the button below."
|
||||
action={
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
href="https://backstage.io/docs/features/software-catalog/well-known-annotations"
|
||||
>
|
||||
Read more
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isGithubActionsAvailable}>
|
||||
<EntityGithubActionsContent />
|
||||
</EntitySwitch.Case>
|
||||
|
||||
const OverviewContent = ({ entity }: { entity: Entity }) => (
|
||||
<EntitySwitch.Case>
|
||||
<EmptyState
|
||||
title="No CI/CD available for this entity"
|
||||
missing="info"
|
||||
description="You need to add an annotation to your component if you want to enable CI/CD for it. You can read more about annotations in Backstage by clicking the button below."
|
||||
action={
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
href="https://backstage.io/docs/features/software-catalog/well-known-annotations"
|
||||
>
|
||||
Read more
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
);
|
||||
|
||||
const overviewContent = (
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item md={6}>
|
||||
<AboutCard entity={entity} variant="gridItem" />
|
||||
<EntityAboutCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
const ComponentApisContent = ({ entity }: { entity: Entity }) => (
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item md={6}>
|
||||
<ProvidedApisCard entity={entity} />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<ConsumedApisCard entity={entity} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
const serviceEntityPage = (
|
||||
<EntityLayout>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
{overviewContent}
|
||||
</EntityLayout.Route>
|
||||
|
||||
const ServiceEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayout>
|
||||
<EntityPageLayout.Content
|
||||
path="/"
|
||||
title="Overview"
|
||||
element={<OverviewContent entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/ci-cd/*"
|
||||
title="CI/CD"
|
||||
element={<CICDSwitcher entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/api/*"
|
||||
title="API"
|
||||
element={<ComponentApisContent entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/docs/*"
|
||||
title="Docs"
|
||||
element={<DocsRouter entity={entity} />}
|
||||
/>
|
||||
</EntityPageLayout>
|
||||
);
|
||||
<EntityLayout.Route path="/ci-cd" title="CI/CD">
|
||||
{cicdContent}
|
||||
</EntityLayout.Route>
|
||||
|
||||
const WebsiteEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayout>
|
||||
<EntityPageLayout.Content
|
||||
path="/"
|
||||
title="Overview"
|
||||
element={<OverviewContent entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/ci-cd/*"
|
||||
title="CI/CD"
|
||||
element={<CICDSwitcher entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/docs/*"
|
||||
title="Docs"
|
||||
element={<DocsRouter entity={entity} />}
|
||||
/>
|
||||
</EntityPageLayout>
|
||||
);
|
||||
|
||||
const DefaultEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayout>
|
||||
<EntityPageLayout.Content
|
||||
path="/*"
|
||||
title="Overview"
|
||||
element={<OverviewContent entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/docs/*"
|
||||
title="Docs"
|
||||
element={<DocsRouter entity={entity} />}
|
||||
/>
|
||||
</EntityPageLayout>
|
||||
);
|
||||
|
||||
export const ComponentEntityPage = ({ entity }: { entity: Entity }) => {
|
||||
switch (entity?.spec?.type) {
|
||||
case 'service':
|
||||
return <ServiceEntityPage entity={entity} />;
|
||||
case 'website':
|
||||
return <WebsiteEntityPage entity={entity} />;
|
||||
default:
|
||||
return <DefaultEntityPage entity={entity} />;
|
||||
}
|
||||
};
|
||||
|
||||
const ApiOverviewContent = ({ entity }: { entity: Entity }) => (
|
||||
<Grid container spacing={3}>
|
||||
<Grid item md={6}>
|
||||
<AboutCard entity={entity} />
|
||||
</Grid>
|
||||
<Grid container item md={12}>
|
||||
<Grid item md={6}>
|
||||
<ProvidingComponentsCard entity={entity} />
|
||||
<EntityLayout.Route path="/api" title="API">
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item md={6}>
|
||||
<EntityProvidedApisCard />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityConsumedApisCard />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<ConsumingComponentsCard entity={entity} />
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/docs" title="Docs">
|
||||
<EntityTechdocsContent />
|
||||
</EntityLayout.Route>
|
||||
</EntityLayout>
|
||||
);
|
||||
|
||||
const websiteEntityPage = (
|
||||
<EntityLayout>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
{overviewContent}
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/ci-cd" title="CI/CD">
|
||||
{cicdContent}
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/docs" title="Docs">
|
||||
<EntityTechdocsContent />
|
||||
</EntityLayout.Route>
|
||||
</EntityLayout>
|
||||
);
|
||||
|
||||
const defaultEntityPage = (
|
||||
<EntityLayout>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
{overviewContent}
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/docs" title="Docs">
|
||||
<EntityTechdocsContent />
|
||||
</EntityLayout.Route>
|
||||
</EntityLayout>
|
||||
);
|
||||
|
||||
const componentPage = (
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isComponentType('service')}>
|
||||
{serviceEntityPage}
|
||||
</EntitySwitch.Case>
|
||||
|
||||
<EntitySwitch.Case if={isComponentType('website')}>
|
||||
{websiteEntityPage}
|
||||
</EntitySwitch.Case>
|
||||
|
||||
<EntitySwitch.Case>{defaultEntityPage}</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
);
|
||||
|
||||
const apiPage = (
|
||||
<EntityLayout>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
<Grid container spacing={3}>
|
||||
<Grid item md={6}>
|
||||
<EntityAboutCard />
|
||||
</Grid>
|
||||
<Grid container item md={12}>
|
||||
<Grid item md={6}>
|
||||
<EntityProvidingComponentsCard />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityConsumingComponentsCard />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/definition" title="Definition">
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12}>
|
||||
<EntityApiDefinitionCard />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
</EntityLayout>
|
||||
);
|
||||
|
||||
const ApiDefinitionContent = ({ entity }: { entity: ApiEntity }) => (
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12}>
|
||||
<ApiDefinitionCard apiEntity={entity} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
const userPage = (
|
||||
<EntityLayout>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityUserProfileCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityOwnershipCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
</EntityLayout>
|
||||
);
|
||||
|
||||
const ApiEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayout>
|
||||
<EntityPageLayout.Content
|
||||
path="/*"
|
||||
title="Overview"
|
||||
element={<ApiOverviewContent entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/definition/*"
|
||||
title="Definition"
|
||||
element={<ApiDefinitionContent entity={entity as ApiEntity} />}
|
||||
/>
|
||||
</EntityPageLayout>
|
||||
const groupPage = (
|
||||
<EntityLayout>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityGroupProfileCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityOwnershipCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<EntityMembersListCard />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/diagram" title="Diagram">
|
||||
<EntitySystemDiagramCard />
|
||||
</EntityLayout.Route>
|
||||
</EntityLayout>
|
||||
);
|
||||
|
||||
const UserOverviewContent = ({ entity }: { entity: UserEntity }) => (
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<UserProfileCard entity={entity} variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<OwnershipCard entity={entity} variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
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>
|
||||
</EntityLayout.Route>
|
||||
</EntityLayout>
|
||||
);
|
||||
|
||||
const UserEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayout>
|
||||
<EntityPageLayout.Content
|
||||
path="/*"
|
||||
title="Overview"
|
||||
element={<UserOverviewContent entity={entity as UserEntity} />}
|
||||
/>
|
||||
</EntityPageLayout>
|
||||
const domainPage = (
|
||||
<EntityLayout>
|
||||
<EntityLayout.Route path="/" title="Overview">
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item md={6}>
|
||||
<EntityAboutCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityHasSystemsCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
</EntityLayout>
|
||||
);
|
||||
|
||||
const GroupOverviewContent = ({ entity }: { entity: GroupEntity }) => (
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<GroupProfileCard entity={entity} variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<OwnershipCard entity={entity} variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<MembersListCard entity={entity} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
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>
|
||||
);
|
||||
|
||||
const GroupEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayout>
|
||||
<EntityPageLayout.Content
|
||||
path="/*"
|
||||
title="Overview"
|
||||
element={<GroupOverviewContent entity={entity as GroupEntity} />}
|
||||
/>
|
||||
</EntityPageLayout>
|
||||
);
|
||||
|
||||
const SystemOverviewContent = ({ entity }: { entity: SystemEntity }) => (
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item md={6}>
|
||||
<AboutCard entity={entity} variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityHasComponentsCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityHasApisCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
const SystemEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayout>
|
||||
<EntityPageLayout.Content
|
||||
path="/*"
|
||||
title="Overview"
|
||||
element={<SystemOverviewContent entity={entity as SystemEntity} />}
|
||||
/>
|
||||
</EntityPageLayout>
|
||||
);
|
||||
|
||||
const DomainOverviewContent = ({ entity }: { entity: DomainEntity }) => (
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item md={6}>
|
||||
<AboutCard entity={entity} variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityHasSystemsCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
const DomainEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayout>
|
||||
<EntityPageLayout.Content
|
||||
path="/*"
|
||||
title="Overview"
|
||||
element={<DomainOverviewContent entity={entity as DomainEntity} />}
|
||||
/>
|
||||
</EntityPageLayout>
|
||||
);
|
||||
|
||||
export const EntityPage = () => {
|
||||
const { entity } = useEntity();
|
||||
|
||||
switch (entity?.kind?.toLocaleLowerCase('en-US')) {
|
||||
case 'component':
|
||||
return <ComponentEntityPage entity={entity} />;
|
||||
case 'api':
|
||||
return <ApiEntityPage entity={entity} />;
|
||||
case 'group':
|
||||
return <GroupEntityPage entity={entity} />;
|
||||
case 'user':
|
||||
return <UserEntityPage entity={entity} />;
|
||||
case 'system':
|
||||
return <SystemEntityPage entity={entity} />;
|
||||
case 'domain':
|
||||
return <DomainEntityPage entity={entity} />;
|
||||
case 'location':
|
||||
case 'resource':
|
||||
case 'template':
|
||||
default:
|
||||
return <DefaultEntityPage entity={entity} />;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1834,194 +1834,6 @@
|
||||
lodash "^4.17.19"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@backstage/catalog-model@^0.2.0":
|
||||
version "0.7.5"
|
||||
dependencies:
|
||||
"@backstage/config" "^0.1.3"
|
||||
"@types/json-schema" "^7.0.5"
|
||||
"@types/yup" "^0.29.8"
|
||||
ajv "^7.0.3"
|
||||
json-schema "^0.2.5"
|
||||
lodash "^4.17.15"
|
||||
uuid "^8.0.0"
|
||||
yup "^0.29.3"
|
||||
|
||||
"@backstage/core@^0.3.0":
|
||||
version "0.7.3"
|
||||
dependencies:
|
||||
"@backstage/config" "^0.1.4"
|
||||
"@backstage/core-api" "^0.2.15"
|
||||
"@backstage/errors" "^0.1.1"
|
||||
"@backstage/theme" "^0.2.5"
|
||||
"@material-ui/core" "^4.11.0"
|
||||
"@material-ui/icons" "^4.9.1"
|
||||
"@material-ui/lab" "4.0.0-alpha.45"
|
||||
"@testing-library/react-hooks" "^3.4.2"
|
||||
"@types/dagre" "^0.7.44"
|
||||
"@types/prop-types" "^15.7.3"
|
||||
"@types/react" "^16.9"
|
||||
"@types/react-sparklines" "^1.7.0"
|
||||
"@types/react-text-truncate" "^0.14.0"
|
||||
classnames "^2.2.6"
|
||||
clsx "^1.1.0"
|
||||
d3-selection "^2.0.0"
|
||||
d3-shape "^2.0.0"
|
||||
d3-zoom "^2.0.0"
|
||||
dagre "^0.8.5"
|
||||
immer "^9.0.1"
|
||||
lodash "^4.17.15"
|
||||
material-table "^1.69.1"
|
||||
prop-types "^15.7.2"
|
||||
qs "^6.9.4"
|
||||
rc-progress "^3.0.0"
|
||||
react "^16.12.0"
|
||||
react-dom "^16.12.0"
|
||||
react-helmet "6.1.0"
|
||||
react-hook-form "^6.6.0"
|
||||
react-markdown "^5.0.2"
|
||||
react-router "6.0.0-beta.0"
|
||||
react-router-dom "6.0.0-beta.0"
|
||||
react-sparklines "^1.7.0"
|
||||
react-syntax-highlighter "^15.4.3"
|
||||
react-text-truncate "^0.16.0"
|
||||
react-use "^15.3.3"
|
||||
remark-gfm "^1.0.0"
|
||||
zen-observable "^0.8.15"
|
||||
|
||||
"@backstage/core@^0.6.0":
|
||||
version "0.7.3"
|
||||
dependencies:
|
||||
"@backstage/config" "^0.1.4"
|
||||
"@backstage/core-api" "^0.2.15"
|
||||
"@backstage/errors" "^0.1.1"
|
||||
"@backstage/theme" "^0.2.5"
|
||||
"@material-ui/core" "^4.11.0"
|
||||
"@material-ui/icons" "^4.9.1"
|
||||
"@material-ui/lab" "4.0.0-alpha.45"
|
||||
"@testing-library/react-hooks" "^3.4.2"
|
||||
"@types/dagre" "^0.7.44"
|
||||
"@types/prop-types" "^15.7.3"
|
||||
"@types/react" "^16.9"
|
||||
"@types/react-sparklines" "^1.7.0"
|
||||
"@types/react-text-truncate" "^0.14.0"
|
||||
classnames "^2.2.6"
|
||||
clsx "^1.1.0"
|
||||
d3-selection "^2.0.0"
|
||||
d3-shape "^2.0.0"
|
||||
d3-zoom "^2.0.0"
|
||||
dagre "^0.8.5"
|
||||
immer "^9.0.1"
|
||||
lodash "^4.17.15"
|
||||
material-table "^1.69.1"
|
||||
prop-types "^15.7.2"
|
||||
qs "^6.9.4"
|
||||
rc-progress "^3.0.0"
|
||||
react "^16.12.0"
|
||||
react-dom "^16.12.0"
|
||||
react-helmet "6.1.0"
|
||||
react-hook-form "^6.6.0"
|
||||
react-markdown "^5.0.2"
|
||||
react-router "6.0.0-beta.0"
|
||||
react-router-dom "6.0.0-beta.0"
|
||||
react-sparklines "^1.7.0"
|
||||
react-syntax-highlighter "^15.4.3"
|
||||
react-text-truncate "^0.16.0"
|
||||
react-use "^15.3.3"
|
||||
remark-gfm "^1.0.0"
|
||||
zen-observable "^0.8.15"
|
||||
|
||||
"@backstage/core@^0.6.1":
|
||||
version "0.7.3"
|
||||
dependencies:
|
||||
"@backstage/config" "^0.1.4"
|
||||
"@backstage/core-api" "^0.2.15"
|
||||
"@backstage/errors" "^0.1.1"
|
||||
"@backstage/theme" "^0.2.5"
|
||||
"@material-ui/core" "^4.11.0"
|
||||
"@material-ui/icons" "^4.9.1"
|
||||
"@material-ui/lab" "4.0.0-alpha.45"
|
||||
"@testing-library/react-hooks" "^3.4.2"
|
||||
"@types/dagre" "^0.7.44"
|
||||
"@types/prop-types" "^15.7.3"
|
||||
"@types/react" "^16.9"
|
||||
"@types/react-sparklines" "^1.7.0"
|
||||
"@types/react-text-truncate" "^0.14.0"
|
||||
classnames "^2.2.6"
|
||||
clsx "^1.1.0"
|
||||
d3-selection "^2.0.0"
|
||||
d3-shape "^2.0.0"
|
||||
d3-zoom "^2.0.0"
|
||||
dagre "^0.8.5"
|
||||
immer "^9.0.1"
|
||||
lodash "^4.17.15"
|
||||
material-table "^1.69.1"
|
||||
prop-types "^15.7.2"
|
||||
qs "^6.9.4"
|
||||
rc-progress "^3.0.0"
|
||||
react "^16.12.0"
|
||||
react-dom "^16.12.0"
|
||||
react-helmet "6.1.0"
|
||||
react-hook-form "^6.6.0"
|
||||
react-markdown "^5.0.2"
|
||||
react-router "6.0.0-beta.0"
|
||||
react-router-dom "6.0.0-beta.0"
|
||||
react-sparklines "^1.7.0"
|
||||
react-syntax-highlighter "^15.4.3"
|
||||
react-text-truncate "^0.16.0"
|
||||
react-use "^15.3.3"
|
||||
remark-gfm "^1.0.0"
|
||||
zen-observable "^0.8.15"
|
||||
|
||||
"@backstage/plugin-catalog@^0.2.1":
|
||||
version "0.5.2"
|
||||
dependencies:
|
||||
"@backstage/catalog-client" "^0.3.9"
|
||||
"@backstage/catalog-model" "^0.7.5"
|
||||
"@backstage/core" "^0.7.3"
|
||||
"@backstage/errors" "^0.1.1"
|
||||
"@backstage/integration" "^0.5.1"
|
||||
"@backstage/integration-react" "^0.1.1"
|
||||
"@backstage/plugin-catalog-react" "^0.1.4"
|
||||
"@backstage/theme" "^0.2.5"
|
||||
"@material-ui/core" "^4.11.0"
|
||||
"@material-ui/icons" "^4.9.1"
|
||||
"@material-ui/lab" "4.0.0-alpha.45"
|
||||
"@types/react" "^16.9"
|
||||
classnames "^2.2.6"
|
||||
git-url-parse "^11.4.4"
|
||||
react "^16.13.1"
|
||||
react-dom "^16.13.1"
|
||||
react-helmet "6.1.0"
|
||||
react-router "6.0.0-beta.0"
|
||||
react-router-dom "6.0.0-beta.0"
|
||||
react-use "^15.3.3"
|
||||
swr "^0.3.0"
|
||||
|
||||
"@backstage/plugin-catalog@^0.3.1":
|
||||
version "0.5.2"
|
||||
dependencies:
|
||||
"@backstage/catalog-client" "^0.3.9"
|
||||
"@backstage/catalog-model" "^0.7.5"
|
||||
"@backstage/core" "^0.7.3"
|
||||
"@backstage/errors" "^0.1.1"
|
||||
"@backstage/integration" "^0.5.1"
|
||||
"@backstage/integration-react" "^0.1.1"
|
||||
"@backstage/plugin-catalog-react" "^0.1.4"
|
||||
"@backstage/theme" "^0.2.5"
|
||||
"@material-ui/core" "^4.11.0"
|
||||
"@material-ui/icons" "^4.9.1"
|
||||
"@material-ui/lab" "4.0.0-alpha.45"
|
||||
"@types/react" "^16.9"
|
||||
classnames "^2.2.6"
|
||||
git-url-parse "^11.4.4"
|
||||
react "^16.13.1"
|
||||
react-dom "^16.13.1"
|
||||
react-helmet "6.1.0"
|
||||
react-router "6.0.0-beta.0"
|
||||
react-router-dom "6.0.0-beta.0"
|
||||
react-use "^15.3.3"
|
||||
swr "^0.3.0"
|
||||
|
||||
"@bcoe/v8-coverage@^0.2.3":
|
||||
version "0.2.3"
|
||||
resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
@@ -4329,6 +4141,11 @@
|
||||
resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-5.3.2.tgz#b8ac43c5c3d00aef61a34cf744e315110c78deb4"
|
||||
integrity sha512-NxF1yfYOUO92rCx3dwvA2onF30Vdlg7YUkMVXkeptqpzA3tRLplThhFleV/UKWFgh7rpKu1yYRbvNDUtzSopKA==
|
||||
|
||||
"@octokit/openapi-types@^6.0.0":
|
||||
version "6.0.0"
|
||||
resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-6.0.0.tgz#7da8d7d5a72d3282c1a3ff9f951c8133a707480d"
|
||||
integrity sha512-CnDdK7ivHkBtJYzWzZm7gEkanA7gKH6a09Eguz7flHw//GacPJLmkHA3f3N++MJmlxD1Fl+mB7B32EEpSCwztQ==
|
||||
|
||||
"@octokit/plugin-enterprise-rest@^6.0.1":
|
||||
version "6.0.1"
|
||||
resolved "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz#e07896739618dab8da7d4077c658003775f95437"
|
||||
@@ -4354,6 +4171,14 @@
|
||||
"@octokit/types" "^6.12.2"
|
||||
deprecation "^2.3.1"
|
||||
|
||||
"@octokit/plugin-rest-endpoint-methods@5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.0.0.tgz#cf2cdeb24ea829c31688216a5b165010b61f9a98"
|
||||
integrity sha512-Jc7CLNUueIshXT+HWt6T+M0sySPjF32mSFQAK7UfAg8qGeRI6OM1GSBxDLwbXjkqy2NVdnqCedJcP1nC785JYg==
|
||||
dependencies:
|
||||
"@octokit/types" "^6.13.0"
|
||||
deprecation "^2.3.1"
|
||||
|
||||
"@octokit/request-error@^2.0.0":
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.2.tgz#0e76b83f5d8fdda1db99027ea5f617c2e6ba9ed0"
|
||||
@@ -4377,7 +4202,7 @@
|
||||
once "^1.4.0"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/rest@^18.0.0", "@octokit/rest@^18.0.12", "@octokit/rest@^18.1.0":
|
||||
"@octokit/rest@^18.0.12", "@octokit/rest@^18.1.0":
|
||||
version "18.3.5"
|
||||
resolved "https://registry.npmjs.org/@octokit/rest/-/rest-18.3.5.tgz#a89903d46e0b4273bd3234674ec2777a651d68ab"
|
||||
integrity sha512-ZPeRms3WhWxQBEvoIh0zzf8xdU2FX0Capa7+lTca8YHmRsO3QNJzf1H3PcuKKsfgp91/xVDRtX91sTe1kexlbw==
|
||||
@@ -4387,6 +4212,16 @@
|
||||
"@octokit/plugin-request-log" "^1.0.2"
|
||||
"@octokit/plugin-rest-endpoint-methods" "4.13.5"
|
||||
|
||||
"@octokit/rest@^18.1.1":
|
||||
version "18.5.2"
|
||||
resolved "https://registry.npmjs.org/@octokit/rest/-/rest-18.5.2.tgz#0369e554b7076e3749005147be94c661c7a5a74b"
|
||||
integrity sha512-Kz03XYfKS0yYdi61BkL9/aJ0pP2A/WK5vF/syhu9/kY30J8He3P68hv9GRpn8bULFx2K0A9MEErn4v3QEdbZcw==
|
||||
dependencies:
|
||||
"@octokit/core" "^3.2.3"
|
||||
"@octokit/plugin-paginate-rest" "^2.6.2"
|
||||
"@octokit/plugin-request-log" "^1.0.2"
|
||||
"@octokit/plugin-rest-endpoint-methods" "5.0.0"
|
||||
|
||||
"@octokit/types@^5.0.0", "@octokit/types@^5.0.1":
|
||||
version "5.5.0"
|
||||
resolved "https://registry.npmjs.org/@octokit/types/-/types-5.5.0.tgz#e5f06e8db21246ca102aa28444cdb13ae17a139b"
|
||||
@@ -4394,13 +4229,20 @@
|
||||
dependencies:
|
||||
"@types/node" ">= 8"
|
||||
|
||||
"@octokit/types@^6.0.0", "@octokit/types@^6.0.1", "@octokit/types@^6.0.3", "@octokit/types@^6.12.2", "@octokit/types@^6.8.2":
|
||||
"@octokit/types@^6.0.0", "@octokit/types@^6.0.1", "@octokit/types@^6.0.3", "@octokit/types@^6.12.2":
|
||||
version "6.12.2"
|
||||
resolved "https://registry.npmjs.org/@octokit/types/-/types-6.12.2.tgz#5b44add079a478b8eb27d78cf384cc47e4411362"
|
||||
integrity sha512-kCkiN8scbCmSq+gwdJV0iLgHc0O/GTPY1/cffo9kECu1MvatLPh9E+qFhfRIktKfHEA6ZYvv6S1B4Wnv3bi3pA==
|
||||
dependencies:
|
||||
"@octokit/openapi-types" "^5.3.2"
|
||||
|
||||
"@octokit/types@^6.13.0":
|
||||
version "6.13.0"
|
||||
resolved "https://registry.npmjs.org/@octokit/types/-/types-6.13.0.tgz#779e5b7566c8dde68f2f6273861dd2f0409480d0"
|
||||
integrity sha512-W2J9qlVIU11jMwKHUp5/rbVUeErqelCsO5vW5PKNb7wAXQVUz87Rc+imjlEvpvbH8yUb+KHmv8NEjVZdsdpyxA==
|
||||
dependencies:
|
||||
"@octokit/openapi-types" "^6.0.0"
|
||||
|
||||
"@open-draft/until@^1.0.3":
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz#db9cc719191a62e7d9200f6e7bab21c5b848adca"
|
||||
@@ -4538,55 +4380,57 @@
|
||||
resolved "https://registry.npmjs.org/@rjsf/material-ui/-/material-ui-2.4.1.tgz#b0dedff8877b114147e298966ca3faba895a7a62"
|
||||
integrity sha512-pZaWL5Dw+km8S0hFLIK1lRHaeNtheMxTF2mZrWhf6HlGWCTGkQJnXta2UgshJN/nKtZPgO1L4FKz42Eun9nnhg==
|
||||
|
||||
"@roadiehq/backstage-plugin-buildkite@^0.1.3":
|
||||
version "0.1.3"
|
||||
resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-buildkite/-/backstage-plugin-buildkite-0.1.3.tgz#5a116bf677dfad22088212dde398cf3e9b48d6e4"
|
||||
integrity sha512-q+cnAvZmjLu0DcqRKJZJhWTVcKaA9j7cM44tx6JcshEyb3UgzrlECLvx4ethnYyrmhM1/FSpMLa+t3N5A1Xz4g==
|
||||
"@roadiehq/backstage-plugin-buildkite@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-buildkite/-/backstage-plugin-buildkite-0.3.0.tgz#60db5e712b88bc9cf3476737a1835f4fc26ae616"
|
||||
integrity sha512-YeATwsR9G93/l3zZmzDN2k0vZzo0Tw0G0pp16B6p1Tz4lBUxiQ40D0anSsVrzep4NR3rxbzqzh7OGZ8Pihfcpw==
|
||||
dependencies:
|
||||
"@backstage/catalog-model" "^0.2.0"
|
||||
"@backstage/core" "^0.3.0"
|
||||
"@backstage/plugin-catalog" "^0.2.1"
|
||||
"@backstage/catalog-model" "^0.7.4"
|
||||
"@backstage/core" "^0.7.3"
|
||||
"@backstage/plugin-catalog" "^0.5.1"
|
||||
"@backstage/theme" "^0.2.5"
|
||||
"@material-ui/core" "^4.11.0"
|
||||
"@material-ui/icons" "^4.9.1"
|
||||
"@material-ui/lab" "4.0.0-alpha.45"
|
||||
history "^5.0.0"
|
||||
moment "^2.27.0"
|
||||
react "^16.13.1"
|
||||
react-dom "^16.13.1"
|
||||
react-lazylog "^4.5.2"
|
||||
react-router "6.0.0-beta.0"
|
||||
react-router-dom "6.0.0-beta.0"
|
||||
react-use "^15.3.3"
|
||||
react-use "^15.3.6"
|
||||
|
||||
"@roadiehq/backstage-plugin-github-insights@^0.3.2":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-insights/-/backstage-plugin-github-insights-0.3.2.tgz#2db83e172ae34738677bd47c3b754c31bb2b5987"
|
||||
integrity sha512-eIhqQS0jTRcdTCu+GxrRCH1tq+kDrTb6mMJpD/6sGnE9QXgj5nKHIm6KHmFYEfIiukQrGxXY4lABNWstvi7hgA==
|
||||
"@roadiehq/backstage-plugin-github-insights@^0.3.3":
|
||||
version "0.3.3"
|
||||
resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-insights/-/backstage-plugin-github-insights-0.3.3.tgz#f2b4aeff76930d4ea4f5ca80bf1ad6f407dd6b74"
|
||||
integrity sha512-sRczrC4JRli8Po1FXL5M6qiCJiUUWpin+kH7XSlo5JJoK5+UdNP05l1qFkMkeCyPdkJp/iVvXArkHPyWnm361g==
|
||||
dependencies:
|
||||
"@backstage/catalog-model" "^0.7.1"
|
||||
"@backstage/core" "^0.6.0"
|
||||
"@backstage/theme" "^0.2.3"
|
||||
"@backstage/catalog-model" "^0.7.4"
|
||||
"@backstage/core" "^0.7.3"
|
||||
"@backstage/theme" "^0.2.5"
|
||||
"@date-io/core" "2.10.7"
|
||||
"@material-ui/core" "^4.11.0"
|
||||
"@material-ui/icons" "^4.9.1"
|
||||
"@material-ui/lab" "4.0.0-alpha.57"
|
||||
"@octokit/rest" "^18.0.0"
|
||||
"@octokit/types" "^6.8.2"
|
||||
"@octokit/rest" "^18.1.1"
|
||||
"@octokit/types" "^6.13.0"
|
||||
history "^5.0.0"
|
||||
react "^16.13.1"
|
||||
react-dom "^16.13.1"
|
||||
react-router "^6.0.0-beta.0"
|
||||
react-use "^17.1.0"
|
||||
react-use "^17.2.1"
|
||||
|
||||
"@roadiehq/backstage-plugin-github-pull-requests@^0.7.6":
|
||||
version "0.7.8"
|
||||
resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-0.7.8.tgz#14a8e512b83de6cb5304b2a8e62c447b2bd6e311"
|
||||
integrity sha512-sgBzIYC4GfZGbFpRixQBinf62laVqefRLHPLaoF2LuTMStXGcjUIGlqySmWNOXvpmGjCv3QIxh1NaxZBp6Z1Vw==
|
||||
"@roadiehq/backstage-plugin-github-pull-requests@^0.7.9":
|
||||
version "0.7.9"
|
||||
resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-0.7.9.tgz#61ea6bc6a50defe0223ef8dff124379673f54c55"
|
||||
integrity sha512-qUyCShhtV4x3QaZewiw13lQBmWLTjybOTsy7x+j4iY6IXkOhol5E2uWVTWifJLxDXg76FsXKWw9eRIqBSOrTRQ==
|
||||
dependencies:
|
||||
"@backstage/catalog-model" "^0.7.1"
|
||||
"@backstage/core" "^0.6.1"
|
||||
"@backstage/catalog-model" "^0.7.4"
|
||||
"@backstage/core" "^0.7.3"
|
||||
"@material-ui/core" "^4.11.0"
|
||||
"@material-ui/icons" "^4.9.1"
|
||||
"@octokit/rest" "^18.0.0"
|
||||
"@octokit/rest" "^18.1.1"
|
||||
"@octokit/types" "^5.0.1"
|
||||
"@types/node-fetch" "^2.5.7"
|
||||
history "^5.0.0"
|
||||
@@ -4597,20 +4441,20 @@
|
||||
react-router "6.0.0-beta.0"
|
||||
react-use "^15.3.6"
|
||||
|
||||
"@roadiehq/backstage-plugin-travis-ci@^0.4.5":
|
||||
version "0.4.5"
|
||||
resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-0.4.5.tgz#c80eb972951badd110173f5521aae65b8a5cfc53"
|
||||
integrity sha512-+y5kFtVaPjXgf6naGVU2E3C33nvoXuaBbfYEmCeByg2t0b5jHMHzsTv2tV5/8zeAcus/5+yIkRCq+F1Tcbwutw==
|
||||
"@roadiehq/backstage-plugin-travis-ci@^0.4.7":
|
||||
version "0.4.7"
|
||||
resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-0.4.7.tgz#ce37ff8b3124975999f0cfe01170b8b5aee55fb3"
|
||||
integrity sha512-hDyOND6/gpCy0GpHLwTDXwNfVWVIBpjh5Ipac0bBa7Yyyj0MKI4UVmLu1K99fRZk1aI6n6TIyLYAJTabLmuYuQ==
|
||||
dependencies:
|
||||
"@backstage/catalog-model" "^0.7.0"
|
||||
"@backstage/core" "^0.6.0"
|
||||
"@backstage/plugin-catalog" "^0.3.1"
|
||||
"@backstage/theme" "^0.2.1"
|
||||
"@backstage/catalog-model" "^0.7.4"
|
||||
"@backstage/core" "^0.7.3"
|
||||
"@backstage/plugin-catalog" "^0.5.1"
|
||||
"@backstage/theme" "^0.2.5"
|
||||
"@material-ui/core" "^4.9.1"
|
||||
"@material-ui/icons" "^4.9.1"
|
||||
"@material-ui/lab" "4.0.0-alpha.45"
|
||||
cross-fetch "^3.0.6"
|
||||
date-fns "^2.16.1"
|
||||
date-fns "^2.18.0"
|
||||
history "^5.0.0"
|
||||
moment "^2.29.1"
|
||||
react "^16.13.1"
|
||||
@@ -11435,6 +11279,11 @@ date-fns@^2.0.0-alpha.27, date-fns@^2.16.1:
|
||||
resolved "https://registry.npmjs.org/date-fns/-/date-fns-2.18.0.tgz#08e50aee300ad0d2c5e054e3f0d10d8f9cdfe09e"
|
||||
integrity sha512-NYyAg4wRmGVU4miKq5ivRACOODdZRY3q5WLmOJSq8djyzftYphU7dTHLcEtLqEvfqMKQ0jVv91P4BAwIjsXIcw==
|
||||
|
||||
date-fns@^2.18.0:
|
||||
version "2.19.0"
|
||||
resolved "https://registry.npmjs.org/date-fns/-/date-fns-2.19.0.tgz#65193348635a28d5d916c43ec7ce6fbd145059e1"
|
||||
integrity sha512-X3bf2iTPgCAQp9wvjOQytnf5vO5rESYRXlPIVcgSbtT5OTScPcsf9eZU+B/YIkKAtYr5WeCii58BgATrNitlWg==
|
||||
|
||||
dateformat@^3.0.0:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
|
||||
@@ -22525,7 +22374,7 @@ react-use@^15.3.3, react-use@^15.3.6:
|
||||
ts-easing "^0.2.0"
|
||||
tslib "^2.0.0"
|
||||
|
||||
react-use@^17.1.0:
|
||||
react-use@^17.2.1:
|
||||
version "17.2.1"
|
||||
resolved "https://registry.npmjs.org/react-use/-/react-use-17.2.1.tgz#c81e12544115ed049c7deba1e3bb3d977dfee9b8"
|
||||
integrity sha512-9r51/at7/Nr/nEP4CsHz+pl800EAqhIY9R6O68m68kaWc8slDAfx1UrIedQqpsb4ImddFYb+6hF1i5Vj4u4Cnw==
|
||||
|
||||
Reference in New Issue
Block a user