From f88fe9dd9bdb4e72e6db4aa7cfe5d28fb92a4e47 Mon Sep 17 00:00:00 2001 From: Tim Hansen Date: Fri, 19 Mar 2021 15:18:26 -0600 Subject: [PATCH] Update create-app template for better parity with example app Fixes #4613 Signed-off-by: Tim Hansen --- .changeset/five-eagles-flow.md | 41 +++++ .../features/software-catalog/installation.md | 2 +- .../configure-app-with-plugins.md | 4 +- docs/tutorials/quickstart-app-plugin.md | 2 +- packages/app/src/App.tsx | 2 +- packages/app/src/components/Root/Root.tsx | 4 +- packages/app/src/components/Root/index.ts | 2 +- packages/create-app/src/lib/versions.ts | 2 + .../templates/default-app/app-config.yaml.hbs | 6 +- .../default-app/packages/app/package.json.hbs | 19 ++- .../default-app/packages/app/src/App.tsx | 54 +++--- .../app/src/components/Root/LogoFull.tsx | 46 ++++++ .../app/src/components/Root/LogoIcon.tsx | 47 ++++++ .../packages/app/src/components/Root/Root.tsx | 92 +++++++++++ .../packages/app/src/components/Root/index.ts | 17 ++ .../app/src/components/catalog/EntityPage.tsx | 154 ++++++++++++++++-- 16 files changed, 433 insertions(+), 61 deletions(-) create mode 100644 .changeset/five-eagles-flow.md create mode 100644 packages/create-app/templates/default-app/packages/app/src/components/Root/LogoFull.tsx create mode 100644 packages/create-app/templates/default-app/packages/app/src/components/Root/LogoIcon.tsx create mode 100644 packages/create-app/templates/default-app/packages/app/src/components/Root/Root.tsx create mode 100644 packages/create-app/templates/default-app/packages/app/src/components/Root/index.ts diff --git a/.changeset/five-eagles-flow.md b/.changeset/five-eagles-flow.md new file mode 100644 index 0000000000..e05e6afa04 --- /dev/null +++ b/.changeset/five-eagles-flow.md @@ -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. diff --git a/docs/features/software-catalog/installation.md b/docs/features/software-catalog/installation.md index 0f10005b0e..1eacada830 100644 --- a/docs/features/software-catalog/installation.md +++ b/docs/features/software-catalog/installation.md @@ -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 diff --git a/docs/getting-started/configure-app-with-plugins.md b/docs/getting-started/configure-app-with-plugins.md index cf7806a5d2..964987c4a7 100644 --- a/docs/getting-started/configure-app-with-plugins.md +++ b/docs/getting-started/configure-app-with-plugins.md @@ -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` diff --git a/docs/tutorials/quickstart-app-plugin.md b/docs/tutorials/quickstart-app-plugin.md index 6208fbe30d..f1efcf0745 100644 --- a/docs/tutorials/quickstart-app-plugin.md +++ b/docs/tutorials/quickstart-app-plugin.md @@ -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 diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 7acde03953..4c2a86c206 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -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'; diff --git a/packages/app/src/components/Root/Root.tsx b/packages/app/src/components/Root/Root.tsx index 7c33113e83..454c0d2e84 100644 --- a/packages/app/src/components/Root/Root.tsx +++ b/packages/app/src/components/Root/Root.tsx @@ -73,7 +73,7 @@ const SidebarLogo = () => { ); }; -const Root = ({ children }: PropsWithChildren<{}>) => ( +export const Root = ({ children }: PropsWithChildren<{}>) => ( @@ -98,5 +98,3 @@ const Root = ({ children }: PropsWithChildren<{}>) => ( {children} ); - -export default Root; diff --git a/packages/app/src/components/Root/index.ts b/packages/app/src/components/Root/index.ts index e997e09c18..ab65cb2451 100644 --- a/packages/app/src/components/Root/index.ts +++ b/packages/app/src/components/Root/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './Root'; +export { Root } from './Root'; diff --git a/packages/create-app/src/lib/versions.ts b/packages/create-app/src/lib/versions.ts index 10f07bef02..2a133b4bf8 100644 --- a/packages/create-app/src/lib/versions.ts +++ b/packages/create-app/src/lib/versions.ts @@ -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, diff --git a/packages/create-app/templates/default-app/app-config.yaml.hbs b/packages/create-app/templates/default-app/app-config.yaml.hbs index 6ba1c273d8..e7e44c9961 100644 --- a/packages/create-app/templates/default-app/app-config.yaml.hbs +++ b/packages/create-app/templates/default-app/app-config.yaml.hbs @@ -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 diff --git a/packages/create-app/templates/default-app/packages/app/package.json.hbs b/packages/create-app/templates/default-app/packages/app/package.json.hbs index 62690114bd..97ff521a89 100644 --- a/packages/create-app/templates/default-app/packages/app/package.json.hbs +++ b/packages/create-app/templates/default-app/packages/app/package.json.hbs @@ -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", diff --git a/packages/create-app/templates/default-app/packages/app/src/App.tsx b/packages/create-app/templates/default-app/packages/app/src/App.tsx index b2c9d10eb0..1cd7b77965 100644 --- a/packages/create-app/templates/default-app/packages/app/src/App.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/App.tsx @@ -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 = ( + + + } /> + } + > + + + } /> + } /> + } /> + } + /> + } /> + } /> + } /> + +); + const App = () => ( - - - - - } /> - } - > - - - } /> - } /> - } /> - } - /> - } /> - } /> - } /> - - + {routes} ); diff --git a/packages/create-app/templates/default-app/packages/app/src/components/Root/LogoFull.tsx b/packages/create-app/templates/default-app/packages/app/src/components/Root/LogoFull.tsx new file mode 100644 index 0000000000..2fb767465b --- /dev/null +++ b/packages/create-app/templates/default-app/packages/app/src/components/Root/LogoFull.tsx @@ -0,0 +1,46 @@ +/* + * 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: 30, + }, + path: { + fill: '#7df3e1', + }, +}); +const LogoFull = () => { + const classes = useStyles(); + + return ( + + + + ); +}; + +export default LogoFull; diff --git a/packages/create-app/templates/default-app/packages/app/src/components/Root/LogoIcon.tsx b/packages/create-app/templates/default-app/packages/app/src/components/Root/LogoIcon.tsx new file mode 100644 index 0000000000..507e47ddb9 --- /dev/null +++ b/packages/create-app/templates/default-app/packages/app/src/components/Root/LogoIcon.tsx @@ -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 ( + + + + ); +}; + +export default LogoIcon; diff --git a/packages/create-app/templates/default-app/packages/app/src/components/Root/Root.tsx b/packages/create-app/templates/default-app/packages/app/src/components/Root/Root.tsx new file mode 100644 index 0000000000..9c07e0c5e2 --- /dev/null +++ b/packages/create-app/templates/default-app/packages/app/src/components/Root/Root.tsx @@ -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 ( +
+ + {isOpen ? : } + +
+ ); +}; + +export const Root = ({ children }: PropsWithChildren<{}>) => ( + + + + + + {/* Global nav, not org-specific */} + + + + + {/* End global nav */} + + + + + + + {children} + +); diff --git a/packages/create-app/templates/default-app/packages/app/src/components/Root/index.ts b/packages/create-app/templates/default-app/packages/app/src/components/Root/index.ts new file mode 100644 index 0000000000..ab65cb2451 --- /dev/null +++ b/packages/create-app/templates/default-app/packages/app/src/components/Root/index.ts @@ -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'; diff --git a/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx b/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx index b1884ac1c6..372379abd5 100644 --- a/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx @@ -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 ; default: return ( - - No CI/CD is available for this entity. Check corresponding - annotations! - + + Read more + + } + /> ); } }; const OverviewContent = ({ entity }: { entity: Entity }) => ( - + @@ -181,6 +207,96 @@ const ApiEntityPage = ({ entity }: { entity: Entity }) => ( ); +const UserOverviewContent = ({ entity }: { entity: UserEntity }) => ( + + + + + + + + +); + +const UserEntityPage = ({ entity }: { entity: Entity }) => ( + + } + /> + +); + +const GroupOverviewContent = ({ entity }: { entity: GroupEntity }) => ( + + + + + + + + + + + +); + +const GroupEntityPage = ({ entity }: { entity: Entity }) => ( + + } + /> + +); + +const SystemOverviewContent = ({ entity }: { entity: SystemEntity }) => ( + + + + + + + + + + + +); + +const SystemEntityPage = ({ entity }: { entity: Entity }) => ( + + } + /> + +); + +const DomainOverviewContent = ({ entity }: { entity: DomainEntity }) => ( + + + + + + + + +); + +const DomainEntityPage = ({ entity }: { entity: Entity }) => ( + + } + /> + +); + export const EntityPage = () => { const { entity } = useEntity(); @@ -189,6 +305,14 @@ export const EntityPage = () => { return ; case 'api': return ; + case 'group': + return ; + case 'user': + return ; + case 'system': + return ; + case 'domain': + return ; default: return ; }