Update create-app template for better parity with example app

Fixes #4613

Signed-off-by: Tim Hansen <timbonicus@gmail.com>
This commit is contained in:
Tim Hansen
2021-03-19 15:18:26 -06:00
parent dcb5d5e373
commit f88fe9dd9b
16 changed files with 433 additions and 61 deletions
+41
View File
@@ -0,0 +1,41 @@
---
'@backstage/create-app': patch
---
Adds plugin-org and more capability to the default EntityPage to display Users, Groups and Systems.
To update an existing application, add the org plugin:
```shell
cd packages/app
yarn add @backstage/plugin-org
```
Then add the example systems locations to your `app-config.yaml`:
```diff
catalog:
rules:
- - allow: [Component, API, Group, User, Template, Location]
+ - allow: [Component, System, API, Group, User, Template, Location]
locations:
# Backstage example components
- type: url
target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all-components.yaml
+ # Backstage example systems
+ - type: url
+ target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all-systems.yaml
+
# Backstage example APIs
```
Additionally, the default app sidebar was updated to parity with the Backstage
repo. You can see these changes in the template
[App.tsx](https://github.com/backstage/backstage/blob/master/packages/create-app/templates/default-app/packages/app/src/App.tsx)
referencing a new `Root` component.
Finally, compare your `packages/app/src/components/catalog/EntityPage.tsx` to
[EntityPage](https://github.com/backstage/backstage/blob/master/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx)
from the `@backstage/create-app` default template to pick up additional
changes there.
@@ -75,7 +75,7 @@ const app = createApp({
You may also want to add a link to the catalog index page to your sidebar:
```tsx
// packages/app/src/sidebar.tsx
// packages/app/src/components/Root.tsx
import HomeIcon from '@material-ui/icons/Home';
// Somewhere within the <Sidebar>
@@ -68,8 +68,8 @@ proxy:
In a standard Backstage app created with
[@backstage/create-app](./create-an-app.md), the sidebar is managed inside
`packages/app/src/sidebar.tsx`. The file exports the entire `Sidebar` element of
your app, which you can extend with additional entries by adding new
`packages/app/src/components/Root.tsx`. The file exports the entire `Sidebar`
element of your app, which you can extend with additional entries by adding new
`SidebarItem` elements.
For example, if you install the `api-docs` plugin, a matching `SidebarItem`
+1 -1
View File
@@ -49,7 +49,7 @@ title: Adding Custom Plugin to Existing Monorepo App
Let's add a shortcut.
1. Open and modify `root: packages > app > src > sidebar.tsx` with the
1. Open and modify `root: packages > app > src > components > Root.tsx` with the
following:
```tsx
+1 -1
View File
@@ -49,7 +49,7 @@ 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 { Root } from './components/Root';
import { providers } from './identityProviders';
import * as plugins from './plugins';
+1 -3
View File
@@ -73,7 +73,7 @@ const SidebarLogo = () => {
);
};
const Root = ({ children }: PropsWithChildren<{}>) => (
export const Root = ({ children }: PropsWithChildren<{}>) => (
<SidebarPage>
<Sidebar>
<SidebarLogo />
@@ -98,5 +98,3 @@ const Root = ({ children }: PropsWithChildren<{}>) => (
{children}
</SidebarPage>
);
export default Root;
+1 -1
View File
@@ -14,4 +14,4 @@
* limitations under the License.
*/
export { default } from './Root';
export { Root } from './Root';
+2
View File
@@ -52,6 +52,7 @@ import { version as pluginCircleci } from '../../../../plugins/circleci/package.
import { version as pluginExplore } from '../../../../plugins/explore/package.json';
import { version as pluginGithubActions } from '../../../../plugins/github-actions/package.json';
import { version as pluginLighthouse } from '../../../../plugins/lighthouse/package.json';
import { version as pluginOrg } from '../../../../plugins/org/package.json';
import { version as pluginProxyBackend } from '../../../../plugins/proxy-backend/package.json';
import { version as pluginRollbarBackend } from '../../../../plugins/rollbar-backend/package.json';
import { version as pluginScaffolder } from '../../../../plugins/scaffolder/package.json';
@@ -82,6 +83,7 @@ export const packageVersions = {
'@backstage/plugin-explore': pluginExplore,
'@backstage/plugin-github-actions': pluginGithubActions,
'@backstage/plugin-lighthouse': pluginLighthouse,
'@backstage/plugin-org': pluginOrg,
'@backstage/plugin-proxy-backend': pluginProxyBackend,
'@backstage/plugin-rollbar-backend': pluginRollbarBackend,
'@backstage/plugin-scaffolder': pluginScaffolder,
@@ -79,12 +79,16 @@ scaffolder:
catalog:
rules:
- allow: [Component, API, Group, User, Template, Location]
- allow: [Component, System, API, Group, User, Template, Location]
locations:
# Backstage example components
- type: url
target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all-components.yaml
# Backstage example systems
- type: url
target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all-systems.yaml
# Backstage example APIs
- type: url
target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all-apis.yaml
@@ -4,24 +4,25 @@
"private": true,
"bundled": true,
"dependencies": {
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"@backstage/catalog-model": "^{{version '@backstage/catalog-model'}}",
"@backstage/cli": "^{{version '@backstage/cli'}}",
"@backstage/core": "^{{version '@backstage/core'}}",
"@backstage/integration-react": "^{{version '@backstage/integration-react'}}",
"@backstage/plugin-api-docs": "^{{version '@backstage/plugin-api-docs'}}",
"@backstage/plugin-catalog": "^{{version '@backstage/plugin-catalog'}}",
"@backstage/plugin-catalog-react": "^{{version '@backstage/plugin-catalog-react'}}",
"@backstage/plugin-catalog-import": "^{{version '@backstage/plugin-catalog-import'}}",
"@backstage/plugin-scaffolder": "^{{version '@backstage/plugin-scaffolder'}}",
"@backstage/plugin-techdocs": "^{{version '@backstage/plugin-techdocs'}}",
"@backstage/catalog-model": "^{{version '@backstage/catalog-model'}}",
"@backstage/plugin-tech-radar": "^{{version '@backstage/plugin-tech-radar'}}",
"@backstage/plugin-catalog-react": "^{{version '@backstage/plugin-catalog-react'}}",
"@backstage/plugin-github-actions": "^{{version '@backstage/plugin-github-actions'}}",
"@backstage/plugin-user-settings": "^{{version '@backstage/plugin-user-settings'}}",
"@backstage/plugin-org": "^{{version '@backstage/plugin-org'}}",
"@backstage/plugin-scaffolder": "^{{version '@backstage/plugin-scaffolder'}}",
"@backstage/plugin-search": "^{{version '@backstage/plugin-search'}}",
"@backstage/integration-react": "^{{version '@backstage/integration-react'}}",
"@backstage/plugin-tech-radar": "^{{version '@backstage/plugin-tech-radar'}}",
"@backstage/plugin-techdocs": "^{{version '@backstage/plugin-techdocs'}}",
"@backstage/plugin-user-settings": "^{{version '@backstage/plugin-user-settings'}}",
"@backstage/test-utils": "^{{version '@backstage/test-utils'}}",
"@backstage/theme": "^{{version '@backstage/theme'}}",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"history": "^5.0.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
@@ -1,9 +1,10 @@
import React from 'react';
import { Navigate, Route } from 'react-router';
import {
AlertDisplay,
createApp,
FlatRoutes,
OAuthRequestDialog,
SidebarPage,
} from '@backstage/core';
import { apiDocsPlugin, ApiExplorerPage } from '@backstage/plugin-api-docs';
import {
@@ -17,12 +18,10 @@ import { SearchPage } from '@backstage/plugin-search';
import { TechRadarPage } from '@backstage/plugin-tech-radar';
import { TechdocsPage } from '@backstage/plugin-techdocs';
import { UserSettingsPage } from '@backstage/plugin-user-settings';
import React from 'react';
import { Navigate, Route } from 'react-router';
import { apis } from './apis';
import { EntityPage } from './components/catalog/EntityPage';
import { Root } from './components/Root';
import * as plugins from './plugins';
import { AppSidebar } from './sidebar';
const app = createApp({
apis,
@@ -40,34 +39,35 @@ const app = createApp({
const AppProvider = app.getProvider();
const AppRouter = app.getRouter();
const routes = (
<FlatRoutes>
<Navigate key="/" to="/catalog" />
<Route path="/catalog" element={<CatalogIndexPage />} />
<Route
path="/catalog/:namespace/:kind/:name"
element={<CatalogEntityPage />}
>
<EntityPage />
</Route>
<Route path="/docs" element={<TechdocsPage />} />
<Route path="/create" element={<ScaffolderPage />} />
<Route path="/api-docs" element={<ApiExplorerPage />} />
<Route
path="/tech-radar"
element={<TechRadarPage width={1500} height={800} />}
/>
<Route path="/catalog-import" element={<CatalogImportPage />} />
<Route path="/search" element={<SearchPage />} />
<Route path="/settings" element={<UserSettingsPage />} />
</FlatRoutes>
);
const App = () => (
<AppProvider>
<AlertDisplay />
<OAuthRequestDialog />
<AppRouter>
<SidebarPage>
<AppSidebar />
<FlatRoutes>
<Navigate key="/" to="/catalog" />
<Route path="/catalog" element={<CatalogIndexPage />} />
<Route
path="/catalog/:namespace/:kind/:name"
element={<CatalogEntityPage />}
>
<EntityPage />
</Route>
<Route path="/docs" element={<TechdocsPage />} />
<Route path="/create" element={<ScaffolderPage />} />
<Route path="/api-docs" element={<ApiExplorerPage />} />
<Route
path="/tech-radar"
element={<TechRadarPage width={1500} height={800} />}
/>
<Route path="/catalog-import" element={<CatalogImportPage />} />
<Route path="/search" element={<SearchPage />} />
<Route path="/settings" element={<UserSettingsPage />} />
</FlatRoutes>
</SidebarPage>
<Root>{routes}</Root>
</AppRouter>
</AppProvider>
);
File diff suppressed because one or more lines are too long
@@ -0,0 +1,47 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { makeStyles } from '@material-ui/core';
const useStyles = makeStyles({
svg: {
width: 'auto',
height: 28,
},
path: {
fill: '#7df3e1',
},
});
const LogoIcon = () => {
const classes = useStyles();
return (
<svg
className={classes.svg}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 337.46 428.5"
>
<path
className={classes.path}
d="M303,166.05a80.69,80.69,0,0,0,13.45-10.37c.79-.77,1.55-1.53,2.3-2.3a83.12,83.12,0,0,0,7.93-9.38A63.69,63.69,0,0,0,333,133.23a48.58,48.58,0,0,0,4.35-16.4c1.49-19.39-10-38.67-35.62-54.22L198.56,0,78.3,115.23,0,190.25l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.69,19.16-18.36,25.52-42.12,13.7-61.87a49.22,49.22,0,0,0-6.8-8.87A89.17,89.17,0,0,0,259,178.29h.15a85.08,85.08,0,0,0,31-5.79A80.88,80.88,0,0,0,303,166.05ZM202.45,225.86c-19.32,18.51-50.4,21.23-75.7,5.9L51.61,186.15l67.45-64.64,76.41,46.38C223,184.58,221.49,207.61,202.45,225.86Zm8.93-82.22-70.65-42.89L205.14,39,274.51,81.1c25.94,15.72,29.31,37,10.55,55A60.69,60.69,0,0,1,211.38,143.64Zm29.86,190c-19.57,18.75-46.17,29.09-74.88,29.09a123.73,123.73,0,0,1-64.1-18.2L0,282.52v24.67L108.6,373.1a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A87.27,87.27,0,0,1,241.24,333.68Zm0-39c-19.57,18.75-46.17,29.08-74.88,29.08a123.81,123.81,0,0,1-64.1-18.19L0,243.53v24.68l108.6,65.91a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.5v-1.78A87.27,87.27,0,0,1,241.24,294.7Zm0-39c-19.57,18.76-46.17,29.09-74.88,29.09a123.81,123.81,0,0,1-64.1-18.19L0,204.55v24.68l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.68,12.88-12.35,20-27.13,19.68-41.5v-1.82A86.09,86.09,0,0,1,241.24,255.71Zm83.7,25.74a94.15,94.15,0,0,1-60.2,25.86h0V334a81.6,81.6,0,0,0,51.74-22.37c14-13.38,21.14-28.11,21-42.64v-2.19A94.92,94.92,0,0,1,324.94,281.45Zm-83.7,91.21c-19.57,18.76-46.17,29.09-74.88,29.09a123.73,123.73,0,0,1-64.1-18.2L0,321.5v24.68l108.6,65.9a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.8,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A86.29,86.29,0,0,1,241.24,372.66ZM327,162.45c-.68.69-1.35,1.38-2.05,2.06a94.37,94.37,0,0,1-10.64,8.65,91.35,91.35,0,0,1-11.6,7,94.53,94.53,0,0,1-26.24,8.71,97.69,97.69,0,0,1-14.16,1.57c.5,1.61.9,3.25,1.25,4.9a53.27,53.27,0,0,1,1.14,12V217h.05a84.41,84.41,0,0,0,25.35-5.55,81,81,0,0,0,26.39-16.82c.8-.77,1.5-1.56,2.26-2.34a82.08,82.08,0,0,0,7.93-9.38A63.76,63.76,0,0,0,333,172.17a48.55,48.55,0,0,0,4.32-16.45c.09-1.23.2-2.47.19-3.7V150q-1.08,1.54-2.25,3.09A96.73,96.73,0,0,1,327,162.45Zm0,77.92c-.69.7-1.31,1.41-2,2.1a94.2,94.2,0,0,1-60.2,25.86h0l0,26.67h0a81.6,81.6,0,0,0,51.74-22.37A73.51,73.51,0,0,0,333,250.13a48.56,48.56,0,0,0,4.32-16.44c.09-1.24.2-2.47.19-3.71v-2.19c-.74,1.07-1.46,2.15-2.27,3.21A95.68,95.68,0,0,1,327,240.37Zm0-39c-.69.7-1.31,1.41-2,2.1a93.18,93.18,0,0,1-10.63,8.65,91.63,91.63,0,0,1-11.63,7,95.47,95.47,0,0,1-37.94,10.18h0V256h0a81.65,81.65,0,0,0,51.74-22.37c.8-.77,1.5-1.56,2.26-2.34a82.08,82.08,0,0,0,7.93-9.38A63.76,63.76,0,0,0,333,211.15a48.56,48.56,0,0,0,4.32-16.44c.09-1.24.2-2.48.19-3.71v-2.2c-.74,1.08-1.46,2.16-2.27,3.22A95.68,95.68,0,0,1,327,201.39Z"
/>
</svg>
);
};
export default LogoIcon;
@@ -0,0 +1,92 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useContext, PropsWithChildren } from 'react';
import { Link, makeStyles } from '@material-ui/core';
import HomeIcon from '@material-ui/icons/Home';
import ExtensionIcon from '@material-ui/icons/Extension';
import MapIcon from '@material-ui/icons/MyLocation';
import LibraryBooks from '@material-ui/icons/LibraryBooks';
import CreateComponentIcon from '@material-ui/icons/AddCircleOutline';
import LogoFull from './LogoFull';
import LogoIcon from './LogoIcon';
import {
Sidebar,
SidebarPage,
sidebarConfig,
SidebarContext,
SidebarItem,
SidebarDivider,
SidebarSpace,
} from '@backstage/core';
import { NavLink } from 'react-router-dom';
import { Settings as SidebarSettings } from '@backstage/plugin-user-settings';
import { SidebarSearch } from '@backstage/plugin-search';
const useSidebarLogoStyles = makeStyles({
root: {
width: sidebarConfig.drawerWidthClosed,
height: 3 * sidebarConfig.logoHeight,
display: 'flex',
flexFlow: 'row nowrap',
alignItems: 'center',
marginBottom: -14,
},
link: {
width: sidebarConfig.drawerWidthClosed,
marginLeft: 24,
},
});
const SidebarLogo = () => {
const classes = useSidebarLogoStyles();
const { isOpen } = useContext(SidebarContext);
return (
<div className={classes.root}>
<Link
component={NavLink}
to="/"
underline="none"
className={classes.link}
>
{isOpen ? <LogoFull /> : <LogoIcon />}
</Link>
</div>
);
};
export const Root = ({ children }: PropsWithChildren<{}>) => (
<SidebarPage>
<Sidebar>
<SidebarLogo />
<SidebarSearch />
<SidebarDivider />
{/* Global nav, not org-specific */}
<SidebarItem icon={HomeIcon} to="/catalog" text="Home" />
<SidebarItem icon={ExtensionIcon} to="api-docs" text="APIs" />
<SidebarItem icon={LibraryBooks} to="docs" text="Docs" />
<SidebarItem icon={CreateComponentIcon} to="create" text="Create..." />
{/* End global nav */}
<SidebarDivider />
<SidebarItem icon={MapIcon} to="tech-radar" text="Tech Radar" />
<SidebarSpace />
<SidebarDivider />
<SidebarSettings />
</Sidebar>
{children}
</SidebarPage>
);
@@ -0,0 +1,17 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { Root } from './Root';
@@ -13,27 +13,43 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ApiEntity, Entity } from '@backstage/catalog-model';
import { WarningPanel } from '@backstage/core';
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,
EntityHasApisCard,
ProvidedApisCard,
ProvidingComponentsCard
ProvidingComponentsCard,
} from '@backstage/plugin-api-docs';
import {
AboutCard, EntityPageLayout,
AboutCard,
EntityHasComponentsCard,
EntityHasSystemsCard,
EntityPageLayout,
} from '@backstage/plugin-catalog';
import { useEntity } from '@backstage/plugin-catalog-react';
import {
useEntity
} from '@backstage/plugin-catalog-react';
import {
isPluginApplicableToEntity as isGitHubActionsAvailable, Router as GitHubActionsRouter
isPluginApplicableToEntity as isGitHubActionsAvailable,
Router as GitHubActionsRouter,
} from '@backstage/plugin-github-actions';
import {
GroupProfileCard,
MembersListCard,
OwnershipCard,
UserProfileCard,
} from '@backstage/plugin-org';
import { EmbeddedDocsRouter as DocsRouter } from '@backstage/plugin-techdocs';
import { Grid } from '@material-ui/core';
import React from 'react';
const CICDSwitcher = ({ entity }: { entity: Entity }) => {
@@ -44,17 +60,27 @@ const CICDSwitcher = ({ entity }: { entity: Entity }) => {
return <GitHubActionsRouter entity={entity} />;
default:
return (
<WarningPanel title="CI/CD switcher:">
No CI/CD is available for this entity. Check corresponding
annotations!
</WarningPanel>
<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 OverviewContent = ({ entity }: { entity: Entity }) => (
<Grid container spacing={3} alignItems="stretch">
<Grid item>
<Grid item md={6}>
<AboutCard entity={entity} variant="gridItem" />
</Grid>
</Grid>
@@ -181,6 +207,96 @@ const ApiEntityPage = ({ entity }: { entity: Entity }) => (
</EntityPageLayout>
);
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>
);
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>
);
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();
@@ -189,6 +305,14 @@ export const EntityPage = () => {
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} />;
default:
return <DefaultEntityPage entity={entity} />;
}