Merge pull request #16942 from backstage/blam/scaffolder-simplify-routing

scaffolder/next: simplify routing in the plugin
This commit is contained in:
Ben Lambert
2023-03-17 15:23:00 +01:00
committed by GitHub
16 changed files with 59 additions and 125 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder': minor
---
scaffolder/next: removing the `routeRefs` and exporting the originals on `scaffolderPlugin.routes.x` instead
-16
View File
@@ -8,12 +8,9 @@
import { Entity } from '@backstage/catalog-model';
import { FormProps as FormProps_2 } from '@backstage/plugin-scaffolder-react/alpha';
import type { FormProps as FormProps_3 } from '@rjsf/core-v5';
import { PathParams } from '@backstage/core-plugin-api';
import { PropsWithChildren } from 'react';
import { default as React_2 } from 'react';
import { RouteRef } from '@backstage/core-plugin-api';
import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react';
import { SubRouteRef } from '@backstage/core-plugin-api';
import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';
// @alpha @deprecated
@@ -22,9 +19,6 @@ export type FormProps = Pick<
'transformErrors' | 'noHtml5Validate'
>;
// @alpha (undocumented)
export const nextRouteRef: RouteRef<undefined>;
// @alpha
export type NextRouterProps = {
components?: {
@@ -50,16 +44,6 @@ export const NextScaffolderPage: (
props: PropsWithChildren<NextRouterProps>,
) => JSX.Element;
// @alpha (undocumented)
export const nextScaffolderTaskRouteRef: SubRouteRef<
PathParams<'/tasks/:taskId'>
>;
// @alpha (undocumented)
export const nextSelectedTemplateRouteRef: SubRouteRef<
PathParams<'/templates/:namespace/:templateName'>
>;
// @alpha (undocumented)
export type TemplateGroupFilter = {
title?: React_2.ReactNode;
+3
View File
@@ -425,6 +425,9 @@ export const scaffolderPlugin: BackstagePlugin<
PathParams<'/templates/:namespace/:templateName'>
>;
ongoingTask: SubRouteRef<PathParams<'/tasks/:taskId'>>;
actions: SubRouteRef<undefined>;
listTasks: SubRouteRef<undefined>;
edit: SubRouteRef<undefined>;
},
{
registerComponent: ExternalRouteRef<undefined, true>;
-3
View File
@@ -16,9 +16,6 @@
export { NextScaffolderPage } from './plugin';
export {
nextRouteRef,
nextScaffolderTaskRouteRef,
nextSelectedTemplateRouteRef,
type TemplateGroupFilter,
type NextRouterProps,
type FormProps,
@@ -19,7 +19,7 @@ import React from 'react';
import { renderInTestApp, TestApiProvider } from '@backstage/test-utils';
import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react';
import { act, fireEvent, waitFor } from '@testing-library/react';
import { nextRouteRef } from '../routes';
import { rootRouteRef } from '../../routes';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
@@ -59,7 +59,7 @@ describe('OngoingTask', () => {
<TestApiProvider apis={[[scaffolderApiRef, mockScaffolderApi]]}>
<OngoingTask />
</TestApiProvider>,
{ mountedRoutes: { '/': nextRouteRef } },
{ mountedRoutes: { '/': rootRouteRef } },
);
const { getByText, getByTestId } = rendered;
@@ -21,7 +21,7 @@ import {
ScaffolderTaskOutput,
useTaskEventStream,
} from '@backstage/plugin-scaffolder-react';
import { nextSelectedTemplateRouteRef } from '../routes';
import { selectedTemplateRouteRef } from '../../routes';
import { useRouteRef } from '@backstage/core-plugin-api';
import qs from 'qs';
import { ContextMenu } from './ContextMenu';
@@ -45,7 +45,7 @@ export const OngoingTask = (props: {
}) => {
// todo(blam): check that task Id actually exists, and that it's valid. otherwise redirect to something more useful.
const { taskId } = useParams();
const templateRouteRef = useRouteRef(nextSelectedTemplateRouteRef);
const templateRouteRef = useRouteRef(selectedTemplateRouteRef);
const navigate = useNavigate();
const taskStream = useTaskEventStream(taskId!);
const classes = useStyles();
+11 -11
View File
@@ -33,12 +33,12 @@ import { TemplateGroupFilter } from '../TemplateListPage/TemplateGroups';
import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default';
import {
nextActionsRouteRef,
nextEditRouteRef,
nextScaffolderListTaskRouteRef,
nextScaffolderTaskRouteRef,
nextSelectedTemplateRouteRef,
} from '../routes';
actionsRouteRef,
editRouteRef,
scaffolderListTaskRouteRef,
scaffolderTaskRouteRef,
selectedTemplateRouteRef,
} from '../../routes';
import { ErrorPage } from '@backstage/core-components';
import { OngoingTask } from '../OngoingTask';
import { ActionsPage } from '../../components/ActionsPage';
@@ -115,7 +115,7 @@ export const Router = (props: PropsWithChildren<NextRouterProps>) => {
}
/>
<Route
path={nextSelectedTemplateRouteRef.path}
path={selectedTemplateRouteRef.path}
element={
<SecretsContextProvider>
<TemplateWizardPage
@@ -127,7 +127,7 @@ export const Router = (props: PropsWithChildren<NextRouterProps>) => {
}
/>
<Route
path={nextScaffolderTaskRouteRef.path}
path={scaffolderTaskRouteRef.path}
element={
<TaskPageComponent
TemplateOutputsComponent={TemplateOutputsComponent}
@@ -135,7 +135,7 @@ export const Router = (props: PropsWithChildren<NextRouterProps>) => {
}
/>
<Route
path={nextEditRouteRef.path}
path={editRouteRef.path}
element={
<SecretsContextProvider>
<TemplateEditorPage
@@ -146,9 +146,9 @@ export const Router = (props: PropsWithChildren<NextRouterProps>) => {
}
/>
<Route path={nextActionsRouteRef.path} element={<ActionsPage />} />
<Route path={actionsRouteRef.path} element={<ActionsPage />} />
<Route
path={nextScaffolderListTaskRouteRef.path}
path={scaffolderListTaskRouteRef.path}
element={<ListTasksPage />}
/>
<Route
@@ -30,10 +30,10 @@ import MoreVert from '@material-ui/icons/MoreVert';
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import {
nextActionsRouteRef,
nextEditRouteRef,
nextScaffolderListTaskRouteRef,
} from '../routes';
actionsRouteRef,
editRouteRef,
scaffolderListTaskRouteRef,
} from '../../routes';
const useStyles = makeStyles((theme: BackstageTheme) => ({
button: {
@@ -50,9 +50,9 @@ export type ScaffolderPageContextMenuProps = {
export function ContextMenu(props: ScaffolderPageContextMenuProps) {
const classes = useStyles();
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement>();
const editLink = useRouteRef(nextEditRouteRef);
const actionsLink = useRouteRef(nextActionsRouteRef);
const tasksLink = useRouteRef(nextScaffolderListTaskRouteRef);
const editLink = useRouteRef(editRouteRef);
const actionsLink = useRouteRef(actionsRouteRef);
const tasksLink = useRouteRef(scaffolderListTaskRouteRef);
const navigate = useNavigate();
@@ -28,7 +28,7 @@ import { TemplateGroups } from './TemplateGroups';
import { renderInTestApp, TestApiProvider } from '@backstage/test-utils';
import { errorApiRef } from '@backstage/core-plugin-api';
import { TemplateGroup } from '@backstage/plugin-scaffolder-react/alpha';
import { nextRouteRef } from '../routes';
import { rootRouteRef } from '../../routes';
describe('TemplateGroups', () => {
beforeEach(() => jest.clearAllMocks());
@@ -42,7 +42,7 @@ describe('TemplateGroups', () => {
</TestApiProvider>,
{
mountedRoutes: {
'/next': nextRouteRef,
'/create': rootRouteRef,
},
},
);
@@ -64,7 +64,7 @@ describe('TemplateGroups', () => {
</TestApiProvider>,
{
mountedRoutes: {
'/next': nextRouteRef,
'/create': rootRouteRef,
},
},
);
@@ -85,7 +85,7 @@ describe('TemplateGroups', () => {
</TestApiProvider>,
{
mountedRoutes: {
'/next': nextRouteRef,
'/create': rootRouteRef,
},
},
);
@@ -106,7 +106,7 @@ describe('TemplateGroups', () => {
</TestApiProvider>,
{
mountedRoutes: {
'/next': nextRouteRef,
'/create': rootRouteRef,
},
},
);
@@ -146,7 +146,7 @@ describe('TemplateGroups', () => {
</TestApiProvider>,
{
mountedRoutes: {
'/next': nextRouteRef,
'/create': rootRouteRef,
},
},
);
@@ -195,7 +195,7 @@ describe('TemplateGroups', () => {
</TestApiProvider>,
{
mountedRoutes: {
'/next': nextRouteRef,
'/create': rootRouteRef,
},
},
);
@@ -31,8 +31,7 @@ import {
useRouteRef,
} from '@backstage/core-plugin-api';
import { TemplateGroup } from '@backstage/plugin-scaffolder-react/alpha';
import { viewTechDocRouteRef } from '../../routes';
import { nextSelectedTemplateRouteRef } from '../routes';
import { viewTechDocRouteRef, selectedTemplateRouteRef } from '../../routes';
import { useNavigate } from 'react-router-dom';
/**
@@ -56,7 +55,7 @@ export const TemplateGroups = (props: TemplateGroupsProps) => {
const errorApi = useApi(errorApiRef);
const app = useApp();
const viewTechDocsLink = useRouteRef(viewTechDocRouteRef);
const templateRoute = useRouteRef(nextSelectedTemplateRouteRef);
const templateRoute = useRouteRef(selectedTemplateRouteRef);
const navigate = useNavigate();
const onSelected = useCallback(
(template: TemplateEntityV1beta3) => {
@@ -25,7 +25,7 @@ import {
TestApiProvider,
} from '@backstage/test-utils';
import React from 'react';
import { nextRouteRef } from '../routes';
import { rootRouteRef } from '../../routes';
import { TemplateListPage } from './TemplateListPage';
describe('TemplateListPage', () => {
@@ -63,7 +63,7 @@ describe('TemplateListPage', () => {
>
<TemplateListPage />
</TestApiProvider>,
{ mountedRoutes: { '/': nextRouteRef } },
{ mountedRoutes: { '/': rootRouteRef } },
);
expect(getByPlaceholderText('Search')).toBeInTheDocument();
@@ -85,7 +85,7 @@ describe('TemplateListPage', () => {
>
<TemplateListPage />
</TestApiProvider>,
{ mountedRoutes: { '/': nextRouteRef } },
{ mountedRoutes: { '/': rootRouteRef } },
);
expect(getByRole('menuitem', { name: /All/ })).toBeInTheDocument();
@@ -108,7 +108,7 @@ describe('TemplateListPage', () => {
>
<TemplateListPage />
</TestApiProvider>,
{ mountedRoutes: { '/': nextRouteRef } },
{ mountedRoutes: { '/': rootRouteRef } },
);
expect(getByText('Categories')).toBeInTheDocument();
@@ -29,7 +29,6 @@ import {
} from '@backstage/plugin-scaffolder-react';
import { TemplateWizardPage } from './TemplateWizardPage';
import { rootRouteRef } from '../../routes';
import { nextRouteRef } from '../routes';
jest.mock('react-router-dom', () => {
return {
@@ -84,8 +83,7 @@ describe('TemplateWizardPage', () => {
</ApiProvider>,
{
mountedRoutes: {
'/create': nextRouteRef,
'/create-legacy': rootRouteRef,
'/create': rootRouteRef,
},
},
);
@@ -34,11 +34,12 @@ import {
} from '@backstage/plugin-scaffolder-react/alpha';
import { JsonValue } from '@backstage/types';
import { Header, Page } from '@backstage/core-components';
import {
nextRouteRef,
nextScaffolderTaskRouteRef,
nextSelectedTemplateRouteRef,
} from '../routes';
rootRouteRef,
scaffolderTaskRouteRef,
selectedTemplateRouteRef,
} from '../../routes';
export type TemplateWizardPageProps = {
customFieldExtensions: NextFieldExtensionOptions<any, any>[];
@@ -47,13 +48,13 @@ export type TemplateWizardPageProps = {
};
export const TemplateWizardPage = (props: TemplateWizardPageProps) => {
const rootRef = useRouteRef(nextRouteRef);
const taskRoute = useRouteRef(nextScaffolderTaskRouteRef);
const rootRef = useRouteRef(rootRouteRef);
const taskRoute = useRouteRef(scaffolderTaskRouteRef);
const { secrets } = useTemplateSecrets();
const scaffolderApi = useApi(scaffolderApiRef);
const navigate = useNavigate();
const { templateName, namespace } = useRouteRefParams(
nextSelectedTemplateRouteRef,
selectedTemplateRouteRef,
);
const templateRef = stringifyEntityRef({
-1
View File
@@ -17,4 +17,3 @@ export * from './Router';
export * from './TemplateListPage';
export * from './TemplateWizardPage';
export * from './types';
export * from './routes';
-57
View File
@@ -1,57 +0,0 @@
/*
* Copyright 2022 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 { createRouteRef, createSubRouteRef } from '@backstage/core-plugin-api';
/** @alpha */
export const nextRouteRef = createRouteRef({
id: 'scaffolder/next',
});
/** @alpha */
export const nextSelectedTemplateRouteRef = createSubRouteRef({
id: 'scaffolder/next/selected-template',
parent: nextRouteRef,
path: '/templates/:namespace/:templateName',
});
/** @alpha */
export const nextScaffolderTaskRouteRef = createSubRouteRef({
id: 'scaffolder/next/task',
parent: nextRouteRef,
path: '/tasks/:taskId',
});
/** @alpha */
export const nextScaffolderListTaskRouteRef = createSubRouteRef({
id: 'scaffolder/next/list-tasks',
parent: nextRouteRef,
path: '/tasks',
});
/** @alpha */
export const nextActionsRouteRef = createSubRouteRef({
id: 'scaffolder/next/actions',
parent: nextRouteRef,
path: '/actions',
});
/** @alpha */
export const nextEditRouteRef = createSubRouteRef({
id: 'scaffolder/next/edit',
parent: nextRouteRef,
path: '/edit',
});
+7 -2
View File
@@ -60,8 +60,10 @@ import {
viewTechDocRouteRef,
selectedTemplateRouteRef,
scaffolderTaskRouteRef,
scaffolderListTaskRouteRef,
actionsRouteRef,
editRouteRef,
} from './routes';
import { nextRouteRef } from './next';
/**
* The main plugin export for the scaffolder.
@@ -91,6 +93,9 @@ export const scaffolderPlugin = createPlugin({
root: rootRouteRef,
selectedTemplate: selectedTemplateRouteRef,
ongoingTask: scaffolderTaskRouteRef,
actions: actionsRouteRef,
listTasks: scaffolderListTaskRouteRef,
edit: editRouteRef,
},
externalRoutes: {
registerComponent: registerComponentRouteRef,
@@ -199,6 +204,6 @@ export const NextScaffolderPage = scaffolderPlugin.provide(
createRoutableExtension({
name: 'NextScaffolderPage',
component: () => import('./next/Router').then(m => m.Router),
mountPoint: nextRouteRef,
mountPoint: rootRouteRef,
}),
);