Merge pull request #2345 from spotify/shmidt-i/fix-register-component-plugin-catalog-link

Fix link to catalog after component was registered
This commit is contained in:
Ivan Shmidt
2020-09-09 14:58:00 +02:00
committed by GitHub
10 changed files with 124 additions and 43 deletions
@@ -16,10 +16,15 @@
import React from 'react';
import { render, cleanup } from '@testing-library/react';
import RegisterComponentPage from './RegisterComponentPage';
import { RegisterComponentPage } from './RegisterComponentPage';
import { ThemeProvider } from '@material-ui/core';
import { lightTheme } from '@backstage/theme';
import { errorApiRef, ApiProvider, ApiRegistry } from '@backstage/core';
import {
errorApiRef,
ApiProvider,
ApiRegistry,
createRouteRef,
} from '@backstage/core';
import { catalogApiRef } from '@backstage/plugin-catalog';
import { MemoryRouter } from 'react-router-dom';
@@ -45,7 +50,12 @@ const setup = () => ({
])}
>
<ThemeProvider theme={lightTheme}>
<RegisterComponentPage />
<RegisterComponentPage
catalogRouteRef={createRouteRef({
path: '/catalog',
title: 'Service Catalog',
})}
/>
</ThemeProvider>
</ApiProvider>
</MemoryRouter>,
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import React, { FC, useState } from 'react';
import React, { useState } from 'react';
import { Grid, makeStyles } from '@material-ui/core';
import {
InfoCard,
@@ -26,6 +26,7 @@ import {
Header,
SupportButton,
ContentHeader,
RouteRef,
} from '@backstage/core';
import RegisterComponentForm from '../RegisterComponentForm';
import { catalogApiRef } from '@backstage/plugin-catalog';
@@ -54,7 +55,11 @@ const FormStates = {
} as const;
type ValuesOf<T> = T extends Record<any, infer V> ? V : never;
const RegisterComponentPage: FC<{}> = () => {
export const RegisterComponentPage = ({
catalogRouteRef,
}: {
catalogRouteRef: RouteRef;
}) => {
const classes = useStyles();
const catalogApi = useApi(catalogApiRef);
const [formState, setFormState] = useState<ValuesOf<typeof FormStates>>(
@@ -130,10 +135,9 @@ const RegisterComponentPage: FC<{}> = () => {
entities={result.data!.entities}
onClose={() => setFormState(FormStates.Idle)}
classes={{ paper: classes.dialogPaper }}
catalogRouteRef={catalogRouteRef}
/>
)}
</Page>
);
};
export default RegisterComponentPage;
@@ -14,4 +14,4 @@
* limitations under the License.
*/
export { default } from './RegisterComponentPage';
export { RegisterComponentPage } from './RegisterComponentPage';
@@ -20,6 +20,7 @@ import { cleanup, render } from '@testing-library/react';
import React, { ComponentProps } from 'react';
import { MemoryRouter } from 'react-router-dom';
import { RegisterComponentResultDialog } from './RegisterComponentResultDialog';
import { createRouteRef } from '@backstage/core';
const setup = (
props?: Partial<ComponentProps<typeof RegisterComponentResultDialog>>,
@@ -30,6 +31,10 @@ const setup = (
<RegisterComponentResultDialog
onClose={() => {}}
entities={[]}
catalogRouteRef={createRouteRef({
path: '/catalog',
title: 'Service Catalog',
})}
{...props}
/>
</ThemeProvider>
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import React, { FC } from 'react';
import React from 'react';
import {
Dialog,
DialogTitle,
@@ -28,25 +28,50 @@ import {
Button,
} from '@material-ui/core';
import { Entity } from '@backstage/catalog-model';
import { StructuredMetadataTable } from '@backstage/core';
import { generatePath } from 'react-router';
import {
entityRoute,
rootRoute as catalogRootRoute,
} from '@backstage/plugin-catalog';
import { StructuredMetadataTable, RouteRef } from '@backstage/core';
import { generatePath, resolvePath } from 'react-router';
import { entityRoute } from '@backstage/plugin-catalog';
import { Link as RouterLink } from 'react-router-dom';
type Props = {
onClose: () => void;
classes?: Record<string, string>;
entities: Entity[];
catalogRouteRef: RouteRef;
};
export const RegisterComponentResultDialog: FC<Props> = ({
const getEntityCatalogPath = ({
entity,
catalogRouteRef,
}: {
entity: Entity;
catalogRouteRef: RouteRef;
}) => {
const optionalNamespaceAndName = [
entity.metadata.namespace,
entity.metadata.name,
]
.filter(Boolean)
.join(':');
const relativeEntityPathInsideCatalog = generatePath(entityRoute.path, {
optionalNamespaceAndName,
kind: entity.kind,
});
const resolvedAbsolutePath = resolvePath(
relativeEntityPathInsideCatalog,
catalogRouteRef.path,
)?.pathname;
return resolvedAbsolutePath;
};
export const RegisterComponentResultDialog = ({
onClose,
classes,
entities,
}) => (
catalogRouteRef,
}: Props) => (
<Dialog open onClose={onClose} classes={classes}>
<DialogTitle>Component Registration Result</DialogTitle>
<DialogContent>
@@ -55,17 +80,7 @@ export const RegisterComponentResultDialog: FC<Props> = ({
</DialogContentText>
<List>
{entities.map((entity: any, index: number) => {
const entityPath = generatePath(entityRoute.path, {
optionalNamespaceAndName: [
entity.metadata.namespace,
entity.metadata.name,
]
.filter(Boolean)
.join(':'),
kind: entity.kind,
selectedTabId: 'overview',
});
const entityPath = getEntityCatalogPath({ entity, catalogRouteRef });
return (
<React.Fragment
key={`${entity.metadata.namespace}-${entity.metadata.name}`}
@@ -91,7 +106,11 @@ export const RegisterComponentResultDialog: FC<Props> = ({
</List>
</DialogContent>
<DialogActions>
<Button component={RouterLink} to={catalogRootRoute.path} color="default">
<Button
component={RouterLink}
to={`/${catalogRouteRef.path}`}
color="default"
>
To Catalog
</Button>
</DialogActions>
@@ -0,0 +1,29 @@
/*
* 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 { Route, Routes } from 'react-router';
import { RegisterComponentPage } from './RegisterComponentPage';
import { RouteRef } from '@backstage/core';
// As we don't know which path the catalog's router mounted on
// We need to inject this from the app
export const Router = ({ catalogRouteRef }: { catalogRouteRef: RouteRef }) => (
<Routes>
<Route
element={<RegisterComponentPage catalogRouteRef={catalogRouteRef} />}
/>
</Routes>
);
+2 -1
View File
@@ -14,4 +14,5 @@
* limitations under the License.
*/
export { plugin, rootRoute } from './plugin';
export { plugin } from './plugin';
export { Router } from './components/Router';
+1 -11
View File
@@ -14,18 +14,8 @@
* limitations under the License.
*/
import { createPlugin, createRouteRef } from '@backstage/core';
import RegisterComponentPage from './components/RegisterComponentPage';
export const rootRoute = createRouteRef({
icon: () => null,
path: '/register-component',
title: 'Register component',
});
import { createPlugin } from '@backstage/core';
export const plugin = createPlugin({
id: 'register-component',
register({ router }) {
router.addRoute(rootRoute, RegisterComponentPage);
},
});