From 579a5456498862d4ddd1c3590dcc5dea677a3870 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Mon, 15 Feb 2021 11:57:27 +0100 Subject: [PATCH] Refactor scaffolder routes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: blam Co-authored-by: Patrik Oldsberg --- packages/app/src/App.tsx | 19 +++++++++++++- packages/core-api/src/app/types.ts | 2 +- plugins/catalog/package.json | 1 - .../components/CatalogPage/CatalogPage.tsx | 7 ++--- plugins/catalog/src/plugin.ts | 4 +++ plugins/catalog/src/routes.ts | 21 +++++++++++++++ .../components/TemplateCard/TemplateCard.tsx | 9 +++---- .../TemplatePage/TemplatePage.test.tsx | 3 +-- .../components/TemplatePage/TemplatePage.tsx | 15 ++++++----- plugins/scaffolder/src/index.ts | 1 - plugins/scaffolder/src/plugin.ts | 26 ++++++++----------- plugins/scaffolder/src/routes.ts | 10 +++---- 12 files changed, 77 insertions(+), 41 deletions(-) create mode 100644 plugins/catalog/src/routes.ts diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 70fceb8a01..d0f248c78b 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -22,12 +22,21 @@ import { OAuthRequestDialog, SignInPage, } from '@backstage/core'; -import { Router as CatalogRouter } from '@backstage/plugin-catalog'; +import { + catalogPlugin, + Router as CatalogRouter, +} from '@backstage/plugin-catalog'; import { CatalogImportPage } from '@backstage/plugin-catalog-import'; import { ExplorePage } from '@backstage/plugin-explore'; import { Router as GraphiQLRouter } from '@backstage/plugin-graphiql'; import { Router as LighthouseRouter } from '@backstage/plugin-lighthouse'; import { Router as RegisterComponentRouter } from '@backstage/plugin-register-component'; +import { + TemplateIndexPage, + TemplatePage, + TaskPage, + scaffolderPlugin, +} from '@backstage/plugin-scaffolder'; import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar'; import { Router as DocsRouter } from '@backstage/plugin-techdocs'; import { Router as SettingsRouter } from '@backstage/plugin-user-settings'; @@ -55,6 +64,11 @@ const app = createApp({ ); }, }, + bindRoutes({ bind }) { + bind(catalogPlugin.externalRoutes, { + createComponent: scaffolderPlugin.routes.templateIndex, + }); + }, }); const AppProvider = app.getProvider(); @@ -75,6 +89,9 @@ const routes = ( element={} /> } /> + } /> + } /> + } /> } /> { CatalogFilterType >(); const orgName = configApi.getOptionalString('organization.name') ?? 'Company'; - + const createComponentLink = useRouteRef(createComponentRouteRef); const addMockData = useCallback(async () => { try { const promises: Promise[] = []; @@ -166,7 +167,7 @@ const CatalogPageContents = () => { component={RouterLink} variant="contained" color="primary" - to={scaffolderRootRoute.path} + to={createComponentLink()} > Create Component diff --git a/plugins/catalog/src/plugin.ts b/plugins/catalog/src/plugin.ts index c6944a318a..a2d7fe3c31 100644 --- a/plugins/catalog/src/plugin.ts +++ b/plugins/catalog/src/plugin.ts @@ -29,6 +29,7 @@ import { entityRouteRef, } from '@backstage/plugin-catalog-react'; import { CatalogClientWrapper } from './CatalogClientWrapper'; +import { createComponentRouteRef } from './routes'; export const catalogPlugin = createPlugin({ id: 'catalog', @@ -47,6 +48,9 @@ export const catalogPlugin = createPlugin({ catalogIndex: catalogRouteRef, catalogEntity: entityRouteRef, }, + externalRoutes: { + createComponent: createComponentRouteRef, + }, }); export const CatalogIndexPage = catalogPlugin.provide( diff --git a/plugins/catalog/src/routes.ts b/plugins/catalog/src/routes.ts new file mode 100644 index 0000000000..40e1784235 --- /dev/null +++ b/plugins/catalog/src/routes.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2021 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 { createExternalRouteRef } from '@backstage/core'; + +export const createComponentRouteRef = createExternalRouteRef({ + id: 'create-component', +}); diff --git a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx index 732b5f3e44..328da7e371 100644 --- a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Button } from '@backstage/core'; +import { Button, useRouteRef } from '@backstage/core'; import { BackstageTheme, pageTheme } from '@backstage/theme'; import { Card, @@ -23,8 +23,7 @@ import { useTheme, } from '@material-ui/core'; import React from 'react'; -import { generatePath } from 'react-router-dom'; -import { templateRoute } from '../../routes'; +import { templateRouteRef } from '../../routes'; const useStyles = makeStyles(theme => ({ header: { @@ -68,7 +67,7 @@ export const TemplateCard = ({ const themeId = pageTheme[type] ? type : 'other'; const theme = backstageTheme.getPageTheme({ themeId }); const classes = useStyles({ backgroundImage: theme.backgroundImage }); - const href = generatePath(templateRoute.path, { templateName: name }); + const templateLink = useRouteRef(templateRouteRef); return ( @@ -84,7 +83,7 @@ export const TemplateCard = ({ {description}
-
diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx index f3f97be877..c5c8367994 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx @@ -22,7 +22,6 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import { MemoryRouter, Route } from 'react-router'; import { ScaffolderApi, scaffolderApiRef } from '../../api'; -import { rootRoute } from '../../routes'; import { TemplatePage } from './TemplatePage'; const templateMock = { @@ -134,7 +133,7 @@ describe('TemplatePage', () => { - This is root} /> + This is root} /> , diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx index 7c25829e5e..ad19af2c7c 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx @@ -29,11 +29,11 @@ import { LinearProgress } from '@material-ui/core'; import { IChangeEvent } from '@rjsf/core'; import parseGitUrl from 'git-url-parse'; import React, { useCallback, useState } from 'react'; -import { Navigate, useNavigate } from 'react-router'; +import { useNavigate } from 'react-router'; import { useParams } from 'react-router-dom'; import { useAsync } from 'react-use'; import { scaffolderApiRef } from '../../api'; -import { rootRoute, taskRoute } from '../../routes'; +import { taskRouteRef, templateIndexRouteRef } from '../../routes'; import { MultistepJsonForm } from '../MultistepJsonForm'; const useTemplate = ( @@ -78,7 +78,8 @@ export const TemplatePage = () => { const scaffolderApi = useApi(scaffolderApiRef); const { templateName } = useParams(); const navigate = useNavigate(); - const tasks = useRouteRef(taskRoute); + const tasksLink = useRouteRef(taskRouteRef); + const templateIndexLink = useRouteRef(templateIndexRouteRef); const { template, loading } = useTemplate(templateName, catalogApi); const [formState, setFormState] = useState({}); const handleFormReset = () => setFormState({}); @@ -91,7 +92,7 @@ export const TemplatePage = () => { const handleCreate = async () => { try { const id = await scaffolderApi.scaffold(templateName, formState); - navigate(tasks({ taskId: id })); + navigate(tasksLink({ taskId: id })); } catch (e) { errorApi.post(e); } @@ -99,7 +100,8 @@ export const TemplatePage = () => { if (!loading && !template) { errorApi.post(new Error('Template was not found.')); - return ; + navigate(templateIndexLink()); + return <>{null}; } if (template && !template?.spec?.schema) { @@ -108,7 +110,8 @@ export const TemplatePage = () => { 'Template schema is corrupted, please check the template.yaml file.', ), ); - return ; + navigate(templateIndexLink()); + return <>{null}; } return ( diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index 4a86c2e935..f731ebde40 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -23,4 +23,3 @@ export { } from './plugin'; export type { ScaffolderApi } from './api'; export { ScaffolderClient, scaffolderApiRef } from './api'; -export { rootRoute, templateRoute, taskRoute } from './routes'; diff --git a/plugins/scaffolder/src/plugin.ts b/plugins/scaffolder/src/plugin.ts index abb75355d0..c62117c996 100644 --- a/plugins/scaffolder/src/plugin.ts +++ b/plugins/scaffolder/src/plugin.ts @@ -21,10 +21,11 @@ import { identityApiRef, createRoutableExtension, } from '@backstage/core'; -import { ScaffolderPage as ScaffolderPageComponent } from './components/ScaffolderPage'; -import { TemplatePage as TemplatePageComponent } from './components/TemplatePage'; -import { TaskPage as TaskPageComponent } from './components/TaskPage'; -import { rootRoute, templateRoute, taskRoute } from './routes'; +import { + templateIndexRouteRef, + templateRouteRef, + taskRouteRef, +} from './routes'; import { scaffolderApiRef, ScaffolderClient } from './api'; export const scaffolderPlugin = createPlugin({ @@ -37,15 +38,10 @@ export const scaffolderPlugin = createPlugin({ new ScaffolderClient({ discoveryApi, identityApi }), }), ], - register({ router }) { - router.addRoute(rootRoute, ScaffolderPageComponent); - router.addRoute(templateRoute, TemplatePageComponent); - router.addRoute(taskRoute, TaskPageComponent); - }, routes: { - templateIndex: rootRoute, - template: templateRoute, - task: taskRoute, + templateIndex: templateIndexRouteRef, + template: templateRouteRef, + task: taskRouteRef, }, }); @@ -53,7 +49,7 @@ export const TemplateIndexPage = scaffolderPlugin.provide( createRoutableExtension({ component: () => import('./components/ScaffolderPage').then(m => m.ScaffolderPage), - mountPoint: rootRoute, + mountPoint: templateIndexRouteRef, }), ); @@ -61,13 +57,13 @@ export const TemplatePage = scaffolderPlugin.provide( createRoutableExtension({ component: () => import('./components/TemplatePage').then(m => m.TemplatePage), - mountPoint: templateRoute, + mountPoint: templateRouteRef, }), ); export const TaskPage = scaffolderPlugin.provide( createRoutableExtension({ component: () => import('./components/TaskPage').then(m => m.TaskPage), - mountPoint: taskRoute, + mountPoint: taskRouteRef, }), ); diff --git a/plugins/scaffolder/src/routes.ts b/plugins/scaffolder/src/routes.ts index 08f9f3bfa3..4884c1f83d 100644 --- a/plugins/scaffolder/src/routes.ts +++ b/plugins/scaffolder/src/routes.ts @@ -15,18 +15,16 @@ */ import { createRouteRef } from '@backstage/core'; -export const rootRoute = createRouteRef({ - path: '/create', +export const templateIndexRouteRef = createRouteRef({ title: 'Create new entity', }); -export const templateRoute = createRouteRef({ - path: '/create/:templateName', +export const templateRouteRef = createRouteRef({ title: 'Entity creation', + params: ['templateName'], }); -export const taskRoute = createRouteRef({ - path: '/scaffolder/tasks/:taskId', +export const taskRouteRef = createRouteRef({ title: 'Task information', params: ['taskId'], });