diff --git a/.changeset/late-frogs-yell.md b/.changeset/late-frogs-yell.md new file mode 100644 index 0000000000..b3e45785e3 --- /dev/null +++ b/.changeset/late-frogs-yell.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-app-api': patch +--- + +Add support for serving the app with a base path other than `/`, which is enabled by including the path in `app.baseUrl`. diff --git a/.changeset/neat-meals-arrive.md b/.changeset/neat-meals-arrive.md new file mode 100644 index 0000000000..292d98de26 --- /dev/null +++ b/.changeset/neat-meals-arrive.md @@ -0,0 +1,12 @@ +--- +'@backstage/create-app': patch +--- + +Updated the index page redirect to work with apps served on a different base path than `/`. + +To apply this change to an existing app, remove the `/` prefix from the target route in the `Navigate` element in `packages/app/src/App.tsx`: + +```diff +- ++ +``` diff --git a/.changeset/sharp-donkeys-push.md b/.changeset/sharp-donkeys-push.md new file mode 100644 index 0000000000..fd6304118e --- /dev/null +++ b/.changeset/sharp-donkeys-push.md @@ -0,0 +1,12 @@ +--- +'@backstage/create-app': patch +--- + +Removed the `/` prefix in the catalog `SidebarItem` element, as it is no longer needed. + +To apply this change to an existing app, remove the `/` prefix from the catalog and any other sidebar items in `packages/app/src/components/Root/Root.ts`: + +```diff +- ++ +``` diff --git a/.changeset/violet-bobcats-wave.md b/.changeset/violet-bobcats-wave.md new file mode 100644 index 0000000000..339d7e0e74 --- /dev/null +++ b/.changeset/violet-bobcats-wave.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Fix for `SidebarItem` matching the active route too broadly. diff --git a/docs/features/software-catalog/catalog-customization.md b/docs/features/software-catalog/catalog-customization.md index 8d209cc8f0..07258a55cb 100644 --- a/docs/features/software-catalog/catalog-customization.md +++ b/docs/features/software-catalog/catalog-customization.md @@ -187,7 +187,7 @@ new `CustomCatalogIndexPage`. # packages/app/src/App.tsx const routes = ( - + - } /> + } /> ``` diff --git a/docs/overview/stability-index.md b/docs/overview/stability-index.md index 2b730024fd..ee2628a893 100644 --- a/docs/overview/stability-index.md +++ b/docs/overview/stability-index.md @@ -312,14 +312,6 @@ configuration. Stability: `1` -### `register-component` [GitHub](https://github.com/backstage/backstage/tree/master/plugins/register-component/) - -A frontend plugin that allows the user to register entity locations in the -catalog. - -Stability: `0`. This plugin is likely to be replaced by a generic entity import -plugin instead. - ### `scaffolder` [GitHub](https://github.com/backstage/backstage/tree/master/plugins/scaffolder/) The frontend scaffolder plugin where one can browse templates and initiate diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index de62971f96..13bdcbd2e6 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -98,7 +98,7 @@ const AppRouter = app.getRouter(); const routes = ( - + } /> ) => ( {/* Global nav, not org-specific */} - + diff --git a/packages/core-app-api/src/app/App.tsx b/packages/core-app-api/src/app/App.tsx index a95554709a..f9fe3fd26e 100644 --- a/packages/core-app-api/src/app/App.tsx +++ b/packages/core-app-api/src/app/App.tsx @@ -107,6 +107,20 @@ export function generateBoundRoutes(bindRoutes: AppOptions['bindRoutes']) { return result; } +/** + * Get the app base path from the configured app baseUrl. + * + * The returned path does not have a trailing slash. + */ +function getBasePath(configApi: Config) { + let { pathname } = new URL( + configApi.getOptionalString('app.baseUrl') ?? '/', + 'http://dummy.dev', // baseUrl can be specified as just a path + ); + pathname = pathname.replace(/\/*$/, ''); + return pathname; +} + type FullAppOptions = { apis: Iterable; icons: NonNullable; @@ -302,6 +316,7 @@ export class PrivateAppImpl implements BackstageApp { routeParents={routeParents} routeObjects={routeObjects} routeBindings={generateBoundRoutes(this.bindRoutes)} + basePath={getBasePath(loadedConfig.api)} > {children} @@ -339,14 +354,7 @@ export class PrivateAppImpl implements BackstageApp { const AppRouter = ({ children }: PropsWithChildren<{}>) => { const configApi = useApi(configApiRef); - - let { pathname } = new URL( - configApi.getOptionalString('app.baseUrl') ?? '/', - 'http://dummy.dev', // baseUrl can be specified as just a path - ); - if (pathname.endsWith('/')) { - pathname = pathname.replace(/\/$/, ''); - } + const mountPath = `${getBasePath(configApi)}/*`; // If the app hasn't configured a sign-in page, we just continue as guest. if (!SignInPageComponent) { @@ -361,7 +369,7 @@ export class PrivateAppImpl implements BackstageApp { return ( - {children}} /> + {children}} /> ); @@ -371,7 +379,7 @@ export class PrivateAppImpl implements BackstageApp { - {children}} /> + {children}} /> diff --git a/packages/core-app-api/src/routing/RouteResolver.test.ts b/packages/core-app-api/src/routing/RouteResolver.test.ts index b47a18ecce..1b7eb10003 100644 --- a/packages/core-app-api/src/routing/RouteResolver.test.ts +++ b/packages/core-app-api/src/routing/RouteResolver.test.ts @@ -65,7 +65,7 @@ const externalRef4 = createExternalRouteRef({ describe('RouteResolver', () => { it('should not resolve anything with an empty resolver', () => { - const r = new RouteResolver(new Map(), new Map(), [], new Map()); + const r = new RouteResolver(new Map(), new Map(), [], new Map(), ''); expect(r.resolve(ref1, '/')?.()).toBe(undefined); expect(r.resolve(ref2, '/')?.({ x: '1x' })).toBe(undefined); @@ -85,6 +85,7 @@ describe('RouteResolver', () => { new Map(), [{ routeRefs: new Set([ref1]), path: '/my-route', ...rest }], new Map(), + '', ); expect(r.resolve(ref1, '/')?.()).toBe('/my-route'); @@ -99,6 +100,29 @@ describe('RouteResolver', () => { expect(r.resolve(externalRef4, '/')?.({ x: '6x' })).toBe(undefined); }); + it('should resolve an absolute route and an app base path', () => { + const r = new RouteResolver( + new Map([[ref1, '/my-route']]), + new Map(), + [{ routeRefs: new Set([ref1]), path: '/my-route', ...rest }], + new Map(), + '/base', + ); + + expect(r.resolve(ref1, '/')?.()).toBe('/base/my-route'); + expect(r.resolve(ref2, '/')?.({ x: '1x' })).toBe(undefined); + expect(r.resolve(subRef1, '/')?.()).toBe('/base/my-route/foo'); + expect(r.resolve(subRef2, '/')?.({ a: '2a' })).toBe( + '/base/my-route/foo/2a', + ); + expect(r.resolve(subRef3, '/')?.({ x: '3x' })).toBe(undefined); + expect(r.resolve(subRef4, '/')?.({ x: '4x', a: '4a' })).toBe(undefined); + expect(r.resolve(externalRef1, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef2, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef3, '/')?.({ x: '5x' })).toBe(undefined); + expect(r.resolve(externalRef4, '/')?.({ x: '6x' })).toBe(undefined); + }); + it('should resolve an absolute route with a param and with a parent', () => { const r = new RouteResolver( new Map([ @@ -122,6 +146,7 @@ describe('RouteResolver', () => { [externalRef3, ref2], [externalRef4, subRef3], ]), + '', ); expect(r.resolve(ref1, '/')?.()).toBe('/my-route'); @@ -179,6 +204,7 @@ describe('RouteResolver', () => { }, ], new Map(), + '', ); expect(r.resolve(ref2, '/')?.({ x: 'x' })).toBe('/root/x'); @@ -232,6 +258,7 @@ describe('RouteResolver', () => { [externalRef3, ref2], [externalRef4, subRef3], ]), + '', ); const l = '/my-grandparent/my-y/my-parent/my-x'; diff --git a/packages/core-app-api/src/routing/RouteResolver.ts b/packages/core-app-api/src/routing/RouteResolver.ts index e09da28df8..b5be5f893e 100644 --- a/packages/core-app-api/src/routing/RouteResolver.ts +++ b/packages/core-app-api/src/routing/RouteResolver.ts @@ -187,6 +187,7 @@ export class RouteResolver { ExternalRouteRef, RouteRef | SubRouteRef >, + private readonly appBasePath: string, // base path without a trailing slash ) {} resolve( @@ -209,13 +210,15 @@ export class RouteResolver { // Next we figure out the base path, which is the combination of the common parent path // between our current location and our target location, as well as the additional path // that is the difference between the parent path and the base of our target location. - const basePath = resolveBasePath( - targetRef, - sourceLocation, - this.routePaths, - this.routeParents, - this.routeObjects, - ); + const basePath = + this.appBasePath + + resolveBasePath( + targetRef, + sourceLocation, + this.routePaths, + this.routeParents, + this.routeObjects, + ); const routeFunc: RouteFunc = (...[params]) => { return basePath + generatePath(targetPath, params); diff --git a/packages/core-app-api/src/routing/RoutingProvider.test.tsx b/packages/core-app-api/src/routing/RoutingProvider.test.tsx index 499b81a743..c5a070ac68 100644 --- a/packages/core-app-api/src/routing/RoutingProvider.test.tsx +++ b/packages/core-app-api/src/routing/RoutingProvider.test.tsx @@ -152,6 +152,7 @@ function withRoutingProvider( routeParents={routeParents} routeObjects={routeObjects} routeBindings={new Map(routeBindings)} + basePath="" > {root} @@ -367,6 +368,7 @@ describe('v1 consumer', () => { routeParents={new Map()} routeObjects={[]} routeBindings={new Map()} + basePath="/base" children={children} /> ), @@ -375,8 +377,8 @@ describe('v1 consumer', () => { expect(renderedHook.result.current).toBe(undefined); renderedHook.rerender({ routeRef: routeRef2 }); - expect(renderedHook.result.current?.()).toBe('/foo'); + expect(renderedHook.result.current?.()).toBe('/base/foo'); renderedHook.rerender({ routeRef: routeRef3 }); - expect(renderedHook.result.current?.({ x: 'my-x' })).toBe('/bar/my-x'); + expect(renderedHook.result.current?.({ x: 'my-x' })).toBe('/base/bar/my-x'); }); }); diff --git a/packages/core-app-api/src/routing/RoutingProvider.tsx b/packages/core-app-api/src/routing/RoutingProvider.tsx index ea8e8f76f8..2192f5df26 100644 --- a/packages/core-app-api/src/routing/RoutingProvider.tsx +++ b/packages/core-app-api/src/routing/RoutingProvider.tsx @@ -38,6 +38,7 @@ type ProviderProps = { routeParents: Map; routeObjects: BackstageRouteObject[]; routeBindings: Map; + basePath?: string; children: ReactNode; }; @@ -46,6 +47,7 @@ export const RoutingProvider = ({ routeParents, routeObjects, routeBindings, + basePath = '', children, }: ProviderProps) => { const resolver = new RouteResolver( @@ -53,6 +55,7 @@ export const RoutingProvider = ({ routeParents, routeObjects, routeBindings, + basePath, ); const versionedValue = createVersionedValueMap({ 1: resolver }); diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index b930c455b5..1068a877bd 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -34,7 +34,12 @@ import React, { useContext, useState, } from 'react'; -import { NavLink, NavLinkProps } from 'react-router-dom'; +import { + Link, + NavLinkProps, + useLocation, + useResolvedPath, +} from 'react-router-dom'; import { sidebarConfig, SidebarContext } from './config'; const useStyles = makeStyles(theme => { @@ -147,6 +152,54 @@ function isButtonItem( return (props as SidebarItemLinkProps).to === undefined; } +// TODO(Rugvip): Remove this once NavLink is updated in react-router-dom. +// This is needed because react-router doesn't handle the path comparison +// properly yet, matching for example /foobar with /foo. +export const WorkaroundNavLink = React.forwardRef< + HTMLAnchorElement, + NavLinkProps +>(function WorkaroundNavLinkWithRef( + { + to, + end, + style, + className, + activeStyle, + caseSensitive, + activeClassName = 'active', + 'aria-current': ariaCurrentProp = 'page', + ...rest + }, + ref, +) { + let { pathname: locationPathname } = useLocation(); + let { pathname: toPathname } = useResolvedPath(to); + + if (!caseSensitive) { + locationPathname = locationPathname.toLowerCase(); + toPathname = toPathname.toLowerCase(); + } + + let isActive = locationPathname === toPathname; + if (!isActive && !end) { + // This is the behavior that is different from the original NavLink + isActive = locationPathname.startsWith(`${toPathname}/`); + } + + const ariaCurrent = isActive ? ariaCurrentProp : undefined; + + return ( + + ); +}); + export const SidebarItem = forwardRef((props, ref) => { const { icon: Icon, @@ -211,7 +264,7 @@ export const SidebarItem = forwardRef((props, ref) => { } return ( - ((props, ref) => { {...navLinkProps} > {content} - + ); }); 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 6306b1a685..9b77cf6a95 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 @@ -42,7 +42,7 @@ const AppRouter = app.getRouter(); const routes = ( - + } /> ) => ( {/* Global nav, not org-specific */} - + diff --git a/plugins/catalog/README.md b/plugins/catalog/README.md index 8527c8da7c..ef7b0a2863 100644 --- a/plugins/catalog/README.md +++ b/plugins/catalog/README.md @@ -80,7 +80,7 @@ sidebar: export const Root = ({ children }: PropsWithChildren<{}>) => ( -+ ++ ... ``` diff --git a/plugins/register-component/.eslintrc.js b/plugins/register-component/.eslintrc.js deleted file mode 100644 index 13573efa9c..0000000000 --- a/plugins/register-component/.eslintrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: [require.resolve('@backstage/cli/config/eslint')], -}; diff --git a/plugins/register-component/CHANGELOG.md b/plugins/register-component/CHANGELOG.md deleted file mode 100644 index b4123e326f..0000000000 --- a/plugins/register-component/CHANGELOG.md +++ /dev/null @@ -1,342 +0,0 @@ -# @backstage/plugin-register-component - -## 0.2.22 - -### Patch Changes - -- Updated dependencies - - @backstage/core-components@0.3.0 - - @backstage/core-plugin-api@0.1.5 - - @backstage/plugin-catalog-react@0.4.1 - -## 0.2.21 - -### Patch Changes - -- 9d40fcb1e: - Bumping `material-ui/core` version to at least `4.12.2` as they made some breaking changes in later versions which broke `Pagination` of the `Table`. - - Switching out `material-table` to `@material-table/core` for support for the later versions of `material-ui/core` - - This causes a minor API change to `@backstage/core-components` as the interface for `Table` re-exports the `prop` from the underlying `Table` components. - - `onChangeRowsPerPage` has been renamed to `onRowsPerPageChange` - - `onChangePage` has been renamed to `onPageChange` - - Migration guide is here: https://material-table-core.com/docs/breaking-changes -- Updated dependencies - - @backstage/core-components@0.2.0 - - @backstage/plugin-catalog-react@0.4.0 - - @backstage/core-plugin-api@0.1.4 - - @backstage/theme@0.2.9 - -## 0.2.20 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-catalog-react@0.3.0 - -## 0.2.19 - -### Patch Changes - -- Updated dependencies - - @backstage/core-components@0.1.5 - - @backstage/catalog-model@0.9.0 - - @backstage/plugin-catalog-react@0.2.6 - -## 0.2.18 - -### Patch Changes - -- b47fc34bc: Update "service catalog" references to "software catalog" -- Updated dependencies - - @backstage/plugin-catalog-react@0.2.5 - - @backstage/core-components@0.1.4 - -## 0.2.17 - -### Patch Changes - -- 48c9fcd33: Migrated to use the new `@backstage/core-*` packages rather than `@backstage/core`. -- Updated dependencies - - @backstage/core-plugin-api@0.1.3 - - @backstage/catalog-model@0.8.4 - - @backstage/plugin-catalog-react@0.2.4 - -## 0.2.16 - -### Patch Changes - -- Updated dependencies [add62a455] -- Updated dependencies [cc592248b] -- Updated dependencies [17c497b81] -- Updated dependencies [704875e26] - - @backstage/catalog-model@0.8.0 - - @backstage/core@0.7.11 - - @backstage/plugin-catalog-react@0.2.0 - -## 0.2.15 - -### Patch Changes - -- 062bbf90f: chore: bump `@testing-library/user-event` from 12.8.3 to 13.1.8 -- 675a569a9: chore: bump `react-use` dependency in all packages -- Updated dependencies [062bbf90f] -- Updated dependencies [10c008a3a] -- Updated dependencies [889d89b6e] -- Updated dependencies [16be1d093] -- Updated dependencies [3f988cb63] -- Updated dependencies [675a569a9] - - @backstage/core@0.7.9 - - @backstage/plugin-catalog-react@0.1.6 - - @backstage/catalog-model@0.7.9 - -## 0.2.14 - -### Patch Changes - -- c614ede9a: Updated README to have up-to-date install instructions. -- Updated dependencies [9afcac5af] -- Updated dependencies [e0c9ed759] -- Updated dependencies [6eaecbd81] - - @backstage/core@0.7.7 - -## 0.2.13 - -### Patch Changes - -- 676ede643: Added the `getOriginLocationByEntity` and `removeLocationById` methods to the catalog client -- Updated dependencies [9f48b548c] -- Updated dependencies [8488a1a96] - - @backstage/plugin-catalog-react@0.1.4 - - @backstage/catalog-model@0.7.5 - -## 0.2.12 - -### Patch Changes - -- Updated dependencies [12d8f27a6] -- Updated dependencies [40c0fdbaa] -- Updated dependencies [2a271d89e] -- Updated dependencies [bece09057] -- Updated dependencies [169f48deb] -- Updated dependencies [8a1566719] -- Updated dependencies [9d455f69a] -- Updated dependencies [4c049a1a1] -- Updated dependencies [02816ecd7] - - @backstage/catalog-model@0.7.3 - - @backstage/core@0.7.0 - - @backstage/plugin-catalog-react@0.1.1 - -## 0.2.11 - -### Patch Changes - -- Updated dependencies [3a58084b6] -- Updated dependencies [e799e74d4] -- Updated dependencies [d0760ecdf] -- Updated dependencies [1407b34c6] -- Updated dependencies [88f1f1b60] -- Updated dependencies [bad21a085] -- Updated dependencies [9615e68fb] -- Updated dependencies [49f9b7346] -- Updated dependencies [5c2e2863f] -- Updated dependencies [3a58084b6] -- Updated dependencies [2c1f2a7c2] - - @backstage/core@0.6.3 - - @backstage/plugin-catalog-react@0.1.0 - - @backstage/catalog-model@0.7.2 - -## 0.2.10 - -### Patch Changes - -- Updated dependencies [fd3f2a8c0] -- Updated dependencies [d34d26125] -- Updated dependencies [0af242b6d] -- Updated dependencies [f4c2bcf54] -- Updated dependencies [10a0124e0] -- Updated dependencies [07e226872] -- Updated dependencies [f62e7abe5] -- Updated dependencies [96f378d10] -- Updated dependencies [688b73110] - - @backstage/core@0.6.2 - - @backstage/plugin-catalog-react@0.0.4 - -## 0.2.9 - -### Patch Changes - -- 9ec66c345: Migrated to new composability API, exporting the plugin instance as `registerComponentPlugin`, and page as `RegisterComponentPage`. -- Updated dependencies [19d354c78] -- Updated dependencies [b51ee6ece] - - @backstage/plugin-catalog-react@0.0.3 - - @backstage/core@0.6.1 - -## 0.2.8 - -### Patch Changes - -- 019fe39a0: Switch dependency from `@backstage/plugin-catalog` to `@backstage/plugin-catalog-react`. -- Updated dependencies [12ece98cd] -- Updated dependencies [d82246867] -- Updated dependencies [7fc89bae2] -- Updated dependencies [c810082ae] -- Updated dependencies [5fa3bdb55] -- Updated dependencies [6e612ce25] -- Updated dependencies [025e122c3] -- Updated dependencies [21e624ba9] -- Updated dependencies [da9f53c60] -- Updated dependencies [32c95605f] -- Updated dependencies [7881f2117] -- Updated dependencies [54c7d02f7] -- Updated dependencies [11cb5ef94] - - @backstage/core@0.6.0 - - @backstage/plugin-catalog-react@0.0.2 - - @backstage/theme@0.2.3 - - @backstage/catalog-model@0.7.1 - -## 0.2.7 - -### Patch Changes - -- Updated dependencies [def2307f3] -- Updated dependencies [efd6ef753] -- Updated dependencies [593632f07] -- Updated dependencies [33846acfc] -- Updated dependencies [a187b8ad0] -- Updated dependencies [f04db53d7] -- Updated dependencies [a93f42213] - - @backstage/catalog-model@0.7.0 - - @backstage/core@0.5.0 - - @backstage/plugin-catalog@0.2.12 - -## 0.2.6 - -### Patch Changes - -- 1517876fd: Register component plugin is deprecated in favor of @backstage/plugin-catalog-import -- Updated dependencies [a08c32ced] -- Updated dependencies [7e0b8cac5] -- Updated dependencies [87c0c53c2] - - @backstage/core@0.4.3 - - @backstage/plugin-catalog@0.2.9 - -## 0.2.5 - -### Patch Changes - -- Updated dependencies [c911061b7] -- Updated dependencies [8ef71ed32] -- Updated dependencies [0e6298f7e] -- Updated dependencies [ac3560b42] - - @backstage/catalog-model@0.6.0 - - @backstage/core@0.4.1 - - @backstage/plugin-catalog@0.2.7 - -## 0.2.4 - -### Patch Changes - -- Updated dependencies [2527628e1] -- Updated dependencies [6011b7d3e] -- Updated dependencies [1c69d4716] -- Updated dependencies [83b6e0c1f] -- Updated dependencies [1665ae8bb] -- Updated dependencies [04f26f88d] -- Updated dependencies [ff243ce96] - - @backstage/core@0.4.0 - - @backstage/plugin-catalog@0.2.6 - - @backstage/catalog-model@0.5.0 - - @backstage/theme@0.2.2 - -## 0.2.3 - -### Patch Changes - -- Updated dependencies [08835a61d] -- Updated dependencies [a9fd599f7] -- Updated dependencies [bcc211a08] -- Updated dependencies [ebf37bbae] - - @backstage/catalog-model@0.4.0 - - @backstage/plugin-catalog@0.2.5 - -## 0.2.2 - -### Patch Changes - -- 2a71f4bab: Remove catalog link on validate popup -- Updated dependencies [475fc0aaa] -- Updated dependencies [1166fcc36] -- Updated dependencies [1185919f3] - - @backstage/core@0.3.2 - - @backstage/catalog-model@0.3.0 - - @backstage/plugin-catalog@0.2.3 - -## 0.2.1 - -### Patch Changes - -- Updated dependencies [7b37d65fd] -- Updated dependencies [4aca74e08] -- Updated dependencies [e8f69ba93] -- Updated dependencies [0c0798f08] -- Updated dependencies [0c0798f08] -- Updated dependencies [199237d2f] -- Updated dependencies [6627b626f] -- Updated dependencies [4577e377b] -- Updated dependencies [2d0bd1be7] - - @backstage/core@0.3.0 - - @backstage/theme@0.2.1 - - @backstage/plugin-catalog@0.2.1 - -## 0.2.0 - -### Minor Changes - -- 28edd7d29: Create backend plugin through CLI -- 2ebcfac8d: Add a validate button to the register-component page - - This allows the user to validate his location before adding it. - -### Patch Changes - -- 8b9c8196f: Locations registered through the catalog client now default to the 'url' type. The type selection dropdown in the register-component form has been removed. -- Updated dependencies [28edd7d29] -- Updated dependencies [819a70229] -- Updated dependencies [3a4236570] -- Updated dependencies [ae5983387] -- Updated dependencies [0d4459c08] -- Updated dependencies [482b6313d] -- Updated dependencies [e0be86b6f] -- Updated dependencies [f70a52868] -- Updated dependencies [12b5fe940] -- Updated dependencies [368fd8243] -- Updated dependencies [1c60f716e] -- Updated dependencies [144c66d50] -- Updated dependencies [a768a07fb] -- Updated dependencies [b79017fd3] -- Updated dependencies [6d97d2d6f] -- Updated dependencies [5adfc005e] -- Updated dependencies [f0aa01bcc] -- Updated dependencies [0aecfded0] -- Updated dependencies [93a3fa3ae] -- Updated dependencies [782f3b354] -- Updated dependencies [8b9c8196f] -- Updated dependencies [2713f28f4] -- Updated dependencies [406015b0d] -- Updated dependencies [82759d3e4] -- Updated dependencies [60d40892c] -- Updated dependencies [ac8d5d5c7] -- Updated dependencies [2ebcfac8d] -- Updated dependencies [fa56f4615] -- Updated dependencies [ebca83d48] -- Updated dependencies [aca79334f] -- Updated dependencies [c0d5242a0] -- Updated dependencies [b3d57961c] -- Updated dependencies [0b956f21b] -- Updated dependencies [97c2cb19b] -- Updated dependencies [3beb5c9fc] -- Updated dependencies [754e31db5] -- Updated dependencies [1611c6dbc] - - @backstage/plugin-catalog@0.2.0 - - @backstage/core@0.2.0 - - @backstage/catalog-model@0.2.0 - - @backstage/theme@0.2.0 diff --git a/plugins/register-component/README.md b/plugins/register-component/README.md deleted file mode 100644 index 47db1a7a55..0000000000 --- a/plugins/register-component/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# Register component plugin - -> This plugin is deprecated in favor of [`@backstage/catalog-import`](https://github.com/backstage/backstage/tree/master/plugins/catalog-import), and will be soon removed from the project. - -Welcome to the register-component plugin! - -This plugin allows you to submit your Backstage component using your software's YAML config. - -When installed it is accessible on [localhost:3000/register-component](localhost:3000/register-component). - - - - - - - -## Standalone setup - -1. Install plugin and its dependency `plugin-catalog` - -```bash -# From your Backstage root directory -cd packages/app -yarn add @backstage/plugin-register-component -``` - -2. Add the `RegisterComponentPage` extension to your `App.tsx`: - -```tsx -// packages/app/src/App.tsx -import { RegisterComponentPage } from '@backstage/plugin-cost-insights'; - - - ... - } /> - ... -; -``` - -## Running - -Just run the backstage. - -``` -yarn start && yarn --cwd packages/backend start -``` - -## Usage - -Pretty straightforward, navigate to [localhost:3000/register-component](localhost:3000/register-component) and enter your component's YAML config URL. diff --git a/plugins/register-component/api-report.md b/plugins/register-component/api-report.md deleted file mode 100644 index 39aeb39505..0000000000 --- a/plugins/register-component/api-report.md +++ /dev/null @@ -1,42 +0,0 @@ -## API Report File for "@backstage/plugin-register-component" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -/// - -import { BackstagePlugin } from '@backstage/core-plugin-api'; -import { RouteRef } from '@backstage/core-plugin-api'; - -// Warning: (ae-missing-release-tag) "RegisterComponentPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const RegisterComponentPage: ({ - catalogRouteRef, -}: { - catalogRouteRef: RouteRef; -}) => JSX.Element; - -// Warning: (ae-missing-release-tag) "registerComponentPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -const registerComponentPlugin: BackstagePlugin< - { - root: RouteRef; - }, - {} ->; -export { registerComponentPlugin as plugin }; -export { registerComponentPlugin }; - -// Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public @deprecated -export const Router: ({ - catalogRouteRef, -}: { - catalogRouteRef: RouteRef; -}) => JSX.Element; - -// (No @packageDocumentation comment for this package) -``` diff --git a/plugins/register-component/dev/index.tsx b/plugins/register-component/dev/index.tsx deleted file mode 100644 index e93e4f1ed7..0000000000 --- a/plugins/register-component/dev/index.tsx +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { createDevApp } from '@backstage/dev-utils'; -import { registerComponentPlugin } from '../src/plugin'; - -createDevApp().registerPlugin(registerComponentPlugin).render(); diff --git a/plugins/register-component/package.json b/plugins/register-component/package.json deleted file mode 100644 index bfc765944d..0000000000 --- a/plugins/register-component/package.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "name": "@backstage/plugin-register-component", - "version": "0.2.22", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", - "private": false, - "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts" - }, - "homepage": "https://backstage.io", - "repository": { - "type": "git", - "url": "https://github.com/backstage/backstage", - "directory": "plugins/register-component" - }, - "keywords": [ - "backstage" - ], - "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" - }, - "dependencies": { - "@backstage/catalog-model": "^0.9.0", - "@backstage/core-components": "^0.3.0", - "@backstage/core-plugin-api": "^0.1.5", - "@backstage/plugin-catalog-react": "^0.4.1", - "@backstage/theme": "^0.2.9", - "@material-ui/core": "^4.12.2", - "@material-ui/icons": "^4.9.1", - "@material-ui/lab": "4.0.0-alpha.45", - "react": "^16.13.1", - "react-dom": "^16.13.1", - "react-hook-form": "^6.15.4", - "react-router": "6.0.0-beta.0", - "react-router-dom": "6.0.0-beta.0", - "react-use": "^17.2.4" - }, - "devDependencies": { - "@backstage/cli": "^0.7.7", - "@backstage/core-app-api": "^0.1.7", - "@backstage/dev-utils": "^0.2.5", - "@backstage/test-utils": "^0.1.16", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^11.2.5", - "@testing-library/user-event": "^13.1.8", - "@types/jest": "^26.0.7", - "@types/node": "^14.14.32", - "cross-fetch": "^3.0.6", - "msw": "^0.29.0" - }, - "files": [ - "dist" - ] -} diff --git a/plugins/register-component/src/assets/screenshot-1.png b/plugins/register-component/src/assets/screenshot-1.png deleted file mode 100644 index ffaebbb2f5..0000000000 Binary files a/plugins/register-component/src/assets/screenshot-1.png and /dev/null differ diff --git a/plugins/register-component/src/assets/screenshot-2.png b/plugins/register-component/src/assets/screenshot-2.png deleted file mode 100644 index e4e5dc579c..0000000000 Binary files a/plugins/register-component/src/assets/screenshot-2.png and /dev/null differ diff --git a/plugins/register-component/src/assets/screenshot-3.png b/plugins/register-component/src/assets/screenshot-3.png deleted file mode 100644 index 4bbac74d82..0000000000 Binary files a/plugins/register-component/src/assets/screenshot-3.png and /dev/null differ diff --git a/plugins/register-component/src/assets/screenshot-4.png b/plugins/register-component/src/assets/screenshot-4.png deleted file mode 100644 index f45f333135..0000000000 Binary files a/plugins/register-component/src/assets/screenshot-4.png and /dev/null differ diff --git a/plugins/register-component/src/assets/screenshot-5.png b/plugins/register-component/src/assets/screenshot-5.png deleted file mode 100644 index a50decd748..0000000000 Binary files a/plugins/register-component/src/assets/screenshot-5.png and /dev/null differ diff --git a/plugins/register-component/src/components/RegisterComponentForm/RegisterComponentForm.test.tsx b/plugins/register-component/src/components/RegisterComponentForm/RegisterComponentForm.test.tsx deleted file mode 100644 index 499290493f..0000000000 --- a/plugins/register-component/src/components/RegisterComponentForm/RegisterComponentForm.test.tsx +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { act, render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React from 'react'; -import { RegisterComponentForm } from './RegisterComponentForm'; - -describe('RegisterComponentForm', () => { - it('should initially render disabled buttons', async () => { - render(); - - expect( - await screen.findByText(/Enter the full path to the catalog-info.yaml/), - ).toBeInTheDocument(); - - expect(screen.getByText('Validate').closest('button')).toBeDisabled(); - expect(screen.getByText('Register').closest('button')).toBeDisabled(); - }); - - it('should enable the submit buttons when the target url is set', async () => { - render(); - - await act(async () => { - await userEvent.type( - await screen.findByLabelText('Entity file URL', { exact: false }), - 'https://example.com/blob/master/component.yaml', - ); - }); - - expect(screen.getByText('Validate').closest('button')).not.toBeDisabled(); - expect(screen.getByText('Register').closest('button')).not.toBeDisabled(); - }); - - it('should show spinner while submitting', async () => { - render(); - - expect(screen.getByTestId('loading-progress')).toBeInTheDocument(); - }); -}); diff --git a/plugins/register-component/src/components/RegisterComponentForm/RegisterComponentForm.tsx b/plugins/register-component/src/components/RegisterComponentForm/RegisterComponentForm.tsx deleted file mode 100644 index 8dceaeafca..0000000000 --- a/plugins/register-component/src/components/RegisterComponentForm/RegisterComponentForm.tsx +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { BackstageTheme } from '@backstage/theme'; -import { - Button, - FormControl, - FormHelperText, - LinearProgress, - TextField, -} from '@material-ui/core'; -import { makeStyles } from '@material-ui/core/styles'; -import React from 'react'; -import { useForm } from 'react-hook-form'; -import { ComponentIdValidators } from '../../util/validate'; - -const useStyles = makeStyles(theme => ({ - form: { - alignItems: 'flex-start', - display: 'flex', - flexFlow: 'column nowrap', - }, - buttonSpacing: { - marginLeft: theme.spacing(1), - }, - buttons: { - marginTop: theme.spacing(2), - }, - select: { - minWidth: 120, - }, -})); - -export type Props = { - onSubmit: (formData: Record) => Promise; - submitting?: boolean; -}; - -export const RegisterComponentForm = ({ onSubmit, submitting }: Props) => { - const { register, handleSubmit, errors, formState } = useForm({ - mode: 'onChange', - }); - const classes = useStyles(); - const hasErrors = !!errors.entityLocation; - const dirty = formState?.isDirty; - - const onSubmitValidate = handleSubmit(data => { - data.mode = 'validate'; - onSubmit(data); - }); - - const onSubmitRegister = handleSubmit(data => { - data.mode = 'register'; - onSubmit(data); - }); - - return submitting ? ( - - ) : ( -
- - - - {errors.entityLocation && ( - - {errors.entityLocation.message} - - )} - - -
- - -
-
- ); -}; diff --git a/plugins/register-component/src/components/RegisterComponentForm/index.ts b/plugins/register-component/src/components/RegisterComponentForm/index.ts deleted file mode 100644 index b864bacaad..0000000000 --- a/plugins/register-component/src/components/RegisterComponentForm/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { RegisterComponentForm } from './RegisterComponentForm'; diff --git a/plugins/register-component/src/components/RegisterComponentPage/RegisterComponentPage.test.tsx b/plugins/register-component/src/components/RegisterComponentPage/RegisterComponentPage.test.tsx deleted file mode 100644 index 2874e77eb6..0000000000 --- a/plugins/register-component/src/components/RegisterComponentPage/RegisterComponentPage.test.tsx +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; -import { lightTheme } from '@backstage/theme'; -import { ThemeProvider } from '@material-ui/core'; -import React from 'react'; -import { RegisterComponentPage } from './RegisterComponentPage'; - -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; -import { createRouteRef, errorApiRef } from '@backstage/core-plugin-api'; - -const errorApi: jest.Mocked = { - post: jest.fn(), - error$: jest.fn(), -}; - -const catalogApi: jest.Mocked = { - /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ - addLocation: jest.fn(_a => new Promise(() => {})), - getEntities: jest.fn(), - getOriginLocationByEntity: jest.fn(), - getLocationByEntity: jest.fn(), - getLocationById: jest.fn(), - removeLocationById: jest.fn(), - removeEntityByUid: jest.fn(), - getEntityByName: jest.fn(), -}; - -const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - - {children} - -); - -describe('RegisterComponentPage', () => { - it('should render', async () => { - const { getByText } = await renderInTestApp( - - - , - ); - - expect(getByText('Register existing component')).toBeInTheDocument(); - }); -}); diff --git a/plugins/register-component/src/components/RegisterComponentPage/RegisterComponentPage.tsx b/plugins/register-component/src/components/RegisterComponentPage/RegisterComponentPage.tsx deleted file mode 100644 index 27ed7346ea..0000000000 --- a/plugins/register-component/src/components/RegisterComponentPage/RegisterComponentPage.tsx +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { Entity, Location } from '@backstage/catalog-model'; -import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { Grid, makeStyles } from '@material-ui/core'; -import React, { useState } from 'react'; -import { useMountedState } from 'react-use'; -import { RegisterComponentForm } from '../RegisterComponentForm'; -import { RegisterComponentResultDialog } from '../RegisterComponentResultDialog'; - -import { - Content, - ContentHeader, - Header, - InfoCard, - Page, - SupportButton, -} from '@backstage/core-components'; -import { errorApiRef, RouteRef, useApi } from '@backstage/core-plugin-api'; - -const useStyles = makeStyles(theme => ({ - dialogPaper: { - minHeight: 250, - minWidth: 600, - }, - icon: { - width: 20, - marginRight: theme.spacing(1), - }, - contentText: { - paddingBottom: theme.spacing(2), - }, -})); - -const FormStates = { - Idle: 'idle', - Success: 'success', - Submitting: 'submitting', -} as const; - -type ValuesOf = T extends Record ? V : never; - -export const RegisterComponentPage = ({ - catalogRouteRef, -}: { - catalogRouteRef: RouteRef; -}) => { - const classes = useStyles(); - const catalogApi = useApi(catalogApiRef); - const [formState, setFormState] = useState>( - FormStates.Idle, - ); - const isMounted = useMountedState(); - - const errorApi = useApi(errorApiRef); - - const [result, setResult] = useState<{ - data: { - entities: Entity[]; - location: Location; - } | null; - error: null | Error; - dryRun: boolean; - }>({ - data: null, - error: null, - dryRun: false, - }); - - const handleSubmit = async (formData: Record) => { - setFormState(FormStates.Submitting); - const { entityLocation: target, mode } = formData; - const dryRun = mode === 'validate'; - try { - const data = await catalogApi.addLocation({ target, dryRun }); - - if (!isMounted()) return; - - setResult({ error: null, data, dryRun }); - setFormState(FormStates.Success); - } catch (e) { - errorApi.post(e); - - if (!isMounted()) return; - - setResult({ error: e, data: null, dryRun }); - setFormState(FormStates.Idle); - } - }; - - return ( - -
- - - - Start tracking your component in Backstage. TODO: Add more - information about what this is. - - - - - - - - - - - {formState === FormStates.Success && ( - setFormState(FormStates.Idle)} - classes={{ paper: classes.dialogPaper }} - catalogRouteRef={catalogRouteRef} - /> - )} - - ); -}; diff --git a/plugins/register-component/src/components/RegisterComponentPage/index.ts b/plugins/register-component/src/components/RegisterComponentPage/index.ts deleted file mode 100644 index 982d277451..0000000000 --- a/plugins/register-component/src/components/RegisterComponentPage/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { RegisterComponentPage } from './RegisterComponentPage'; diff --git a/plugins/register-component/src/components/RegisterComponentResultDialog/RegisterComponentResultDialog.test.tsx b/plugins/register-component/src/components/RegisterComponentResultDialog/RegisterComponentResultDialog.test.tsx deleted file mode 100644 index 0cc36c98bc..0000000000 --- a/plugins/register-component/src/components/RegisterComponentResultDialog/RegisterComponentResultDialog.test.tsx +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { Entity } from '@backstage/catalog-model'; -import { lightTheme } from '@backstage/theme'; -import { ThemeProvider } from '@material-ui/core'; -import { render, screen } from '@testing-library/react'; -import React from 'react'; -import { MemoryRouter } from 'react-router-dom'; -import { RegisterComponentResultDialog } from './RegisterComponentResultDialog'; -import { createRouteRef } from '@backstage/core-plugin-api'; - -const Wrapper = ({ children }: { children?: React.ReactNode }) => ( - - {children} - -); - -describe('RegisterComponentResultDialog', () => { - it('should render', () => { - render( - {}} - entities={[]} - catalogRouteRef={createRouteRef({ - path: '/catalog', - title: 'Software Catalog', - })} - />, - { wrapper: Wrapper }, - ); - - expect(screen.getByText('Registration Result')).toBeInTheDocument(); - }); - - it('should show a list of components if success', async () => { - const entities: Entity[] = [ - { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Component', - metadata: { - name: 'Component1', - }, - spec: { - type: 'website', - }, - }, - { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Component', - metadata: { - name: 'Component2', - }, - spec: { - type: 'service', - }, - }, - ]; - - render( - {}} - entities={entities} - catalogRouteRef={createRouteRef({ - path: '/catalog', - title: 'Software Catalog', - })} - />, - { wrapper: Wrapper }, - ); - - expect( - screen.getByText( - 'The following entities have been successfully created:', - ), - ).toBeInTheDocument(); - expect(screen.getByText('Component1')).toBeInTheDocument(); - expect(screen.getByText('Component2')).toBeInTheDocument(); - }); -}); diff --git a/plugins/register-component/src/components/RegisterComponentResultDialog/RegisterComponentResultDialog.tsx b/plugins/register-component/src/components/RegisterComponentResultDialog/RegisterComponentResultDialog.tsx deleted file mode 100644 index e13f2ac229..0000000000 --- a/plugins/register-component/src/components/RegisterComponentResultDialog/RegisterComponentResultDialog.tsx +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { Entity } from '@backstage/catalog-model'; -import { - entityRoute, - entityRouteParams, -} from '@backstage/plugin-catalog-react'; -import { - Button, - Dialog, - DialogActions, - DialogContent, - DialogContentText, - DialogTitle, - Divider, - Link, - List, - ListItem, -} from '@material-ui/core'; -import React, { useState } from 'react'; -import { generatePath, resolvePath } from 'react-router'; -import { Link as RouterLink } from 'react-router-dom'; - -import { RouteRef } from '@backstage/core-plugin-api'; -import { StructuredMetadataTable } from '@backstage/core-components'; - -type Props = { - onClose: () => void; - classes?: Record; - entities: Entity[]; - dryRun?: boolean; - catalogRouteRef: RouteRef; -}; - -const getEntityCatalogPath = ({ - entity, - catalogRouteRef, -}: { - entity: Entity; - catalogRouteRef: RouteRef; -}) => { - const relativeEntityPathInsideCatalog = generatePath( - entityRoute.path, - entityRouteParams(entity), - ); - - const resolvedAbsolutePath = resolvePath( - relativeEntityPathInsideCatalog, - catalogRouteRef.path, - )?.pathname; - - return resolvedAbsolutePath; -}; - -export const RegisterComponentResultDialog = ({ - onClose, - classes, - entities, - dryRun, - catalogRouteRef, -}: Props) => { - const [open, setOpen] = useState(true); - const handleClose = () => { - setOpen(false); - }; - - return ( - - - {dryRun ? 'Validation Result' : 'Registration Result'} - - - - {dryRun - ? 'The following entities would be created:' - : 'The following entities have been successfully created:'} - - - {entities.map((entity: any, index: number) => { - const entityPath = getEntityCatalogPath({ - entity, - catalogRouteRef, - }); - return ( - - - - {entityPath} - - ), - }} - /> - - {index < entities.length - 1 && } - - ); - })} - - - - {dryRun && ( - - )} - {!dryRun && ( - - )} - - - ); -}; diff --git a/plugins/register-component/src/components/RegisterComponentResultDialog/index.ts b/plugins/register-component/src/components/RegisterComponentResultDialog/index.ts deleted file mode 100644 index 933125fd40..0000000000 --- a/plugins/register-component/src/components/RegisterComponentResultDialog/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { RegisterComponentResultDialog } from './RegisterComponentResultDialog'; diff --git a/plugins/register-component/src/components/Router.tsx b/plugins/register-component/src/components/Router.tsx deleted file mode 100644 index 88f8d22f38..0000000000 --- a/plugins/register-component/src/components/Router.tsx +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { Route, Routes } from 'react-router'; -import { RegisterComponentPage } from './RegisterComponentPage'; -import { RouteRef } from '@backstage/core-plugin-api'; - -// As we don't know which path the catalog's router mounted on -// We need to inject this from the app - -/** - * Provides a router for registering a component. - * - * @deprecated The router for this component is deprecated and replaced with the `catalog-import` plugin. - * @see https://github.com/backstage/backstage/tree/master/plugins/catalog-import - */ -export const Router = ({ catalogRouteRef }: { catalogRouteRef: RouteRef }) => ( - - } - /> - -); diff --git a/plugins/register-component/src/index.ts b/plugins/register-component/src/index.ts deleted file mode 100644 index 309893679e..0000000000 --- a/plugins/register-component/src/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { - registerComponentPlugin, - registerComponentPlugin as plugin, - RegisterComponentPage, -} from './plugin'; -export { Router } from './components/Router'; diff --git a/plugins/register-component/src/plugin.test.ts b/plugins/register-component/src/plugin.test.ts deleted file mode 100644 index c09499beda..0000000000 --- a/plugins/register-component/src/plugin.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { registerComponentPlugin } from './plugin'; - -describe('register-component', () => { - it('should export plugin', () => { - expect(registerComponentPlugin).toBeDefined(); - }); -}); diff --git a/plugins/register-component/src/plugin.ts b/plugins/register-component/src/plugin.ts deleted file mode 100644 index 61e998c94f..0000000000 --- a/plugins/register-component/src/plugin.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { - createPlugin, - createRoutableExtension, - createRouteRef, -} from '@backstage/core-plugin-api'; - -const rootRouteRef = createRouteRef({ - title: 'Register Component', -}); - -export const registerComponentPlugin = createPlugin({ - id: 'register-component', - routes: { - root: rootRouteRef, - }, -}); - -export const RegisterComponentPage = registerComponentPlugin.provide( - createRoutableExtension({ - component: () => - import('./components/RegisterComponentPage').then( - m => m.RegisterComponentPage, - ), - mountPoint: rootRouteRef, - }), -); diff --git a/plugins/register-component/src/setupTests.ts b/plugins/register-component/src/setupTests.ts deleted file mode 100644 index 963c0f188b..0000000000 --- a/plugins/register-component/src/setupTests.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 '@testing-library/jest-dom'; diff --git a/plugins/register-component/src/util/validate.test.ts b/plugins/register-component/src/util/validate.test.ts deleted file mode 100644 index 576dc9f367..0000000000 --- a/plugins/register-component/src/util/validate.test.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { ComponentIdValidators } from './validate'; - -describe('ComponentIdValidators', () => { - describe('httpsValidator validator', () => { - const errorMessage = 'Must start with https://.'; - test.each([ - [true, 'https://example.com'], - [errorMessage, 'http://example.com'], - [errorMessage, 'example.com'], - [errorMessage, 'www.example.com'], - [errorMessage, ''], - [errorMessage, undefined], - ])('should return %p for %s', (expected: string | boolean, arg: any) => { - expect(ComponentIdValidators.httpsValidator(arg)).toBe(expected); - }); - }); - describe('yamlValidator', () => { - const errorMessage = "Must contain '.yaml'."; - test.each([ - [true, '.yaml'], - [true, 'http://example.com/blob/master/service.yaml'], - [true, 'https://example.yaml'], - [true, 'https://example.com?path=abc.yaml&c=1'], - [errorMessage, 'https://example.com?path=abc_yaml&c=1'], - [errorMessage, '.yml'], - [errorMessage, 'http://example.com/blob/master/service'], - [errorMessage, undefined], - ])('should return %p for %s', (expected: string | boolean, arg: any) => { - expect(ComponentIdValidators.yamlValidator(arg)).toBe(expected); - }); - }); -}); diff --git a/plugins/register-component/src/util/validate.ts b/plugins/register-component/src/util/validate.ts deleted file mode 100644 index 0b3a6f6940..0000000000 --- a/plugins/register-component/src/util/validate.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 const ComponentIdValidators = { - httpsValidator: (value: any) => - (typeof value === 'string' && value.match(/^https:\/\//) !== null) || - 'Must start with https://.', - yamlValidator: (value: any) => - (typeof value === 'string' && value.match(/\.yaml/) !== null) || - "Must contain '.yaml'.", -}; diff --git a/plugins/register-component/tsconfig.json b/plugins/register-component/tsconfig.json deleted file mode 100644 index b663b01fa2..0000000000 --- a/plugins/register-component/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "include": ["src", "dev"], - "compilerOptions": {} -} diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index d61d244ff3..0866099e18 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -36,7 +36,7 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", - "color": "^3.1.2", + "color": "^4.0.1", "d3-force": "^2.0.1", "prop-types": "^15.7.2", "react": "^16.13.1", diff --git a/yarn.lock b/yarn.lock index 1789bb182b..139a77028a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10501,10 +10501,10 @@ color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4: resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-string@^1.5.2, color-string@^1.5.4: - version "1.5.4" - resolved "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz#dd51cd25cfee953d138fe4002372cc3d0e504cb6" - integrity sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw== +color-string@^1.5.2, color-string@^1.5.4, color-string@^1.6.0: + version "1.6.0" + resolved "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz#c3915f61fe267672cb7e1e064c9d692219f6c312" + integrity sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" @@ -10517,7 +10517,7 @@ color@3.0.x: color-convert "^1.9.1" color-string "^1.5.2" -color@^3.0.0, color@^3.1.2: +color@^3.0.0: version "3.1.3" resolved "https://registry.npmjs.org/color/-/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e" integrity sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ== @@ -10525,6 +10525,14 @@ color@^3.0.0, color@^3.1.2: color-convert "^1.9.1" color-string "^1.5.4" +color@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/color/-/color-4.0.1.tgz#21df44cd10245a91b1ccf5ba031609b0e10e7d67" + integrity sha512-rpZjOKN5O7naJxkH2Rx1sZzzBgaiWECc6BYXjeCE6kF0kcASJYbUq02u7JqIHwCb/j3NhV+QhRL2683aICeGZA== + dependencies: + color-convert "^2.0.1" + color-string "^1.6.0" + colorette@1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b"