diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 125a0bbbf6..c83e1a046a 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -28,8 +28,13 @@ import { import { useElementFilter } from '@backstage/core-plugin-api'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateGroupFilter } from '../TemplateListPage/TemplateGroups'; -import { nextSelectedTemplateRouteRef } from '../../routes'; +import { + nextScaffolderTaskRouteRef, + nextSelectedTemplateRouteRef, +} from '../../routes'; import { SecretsContextProvider } from '../../components/secrets/SecretsContext'; +import { TaskPage } from '../TaskPage'; +import { ErrorPage } from '@backstage/core-components'; /** * The Props for the Scaffolder Router @@ -87,7 +92,6 @@ export const Router = (props: PropsWithChildren) => { /> } /> - ) => { } /> + } /> + } + /> ); }; diff --git a/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx b/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx new file mode 100644 index 0000000000..ff0f4cd820 --- /dev/null +++ b/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx @@ -0,0 +1,33 @@ +/* + * 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 React from 'react'; +import { Page, Header, Content } from '@backstage/core-components'; + +export const TaskPage = () => { + return ( + +
+ +

Hey

+
+ + ); +}; diff --git a/plugins/scaffolder/src/next/TaskPage/index.ts b/plugins/scaffolder/src/next/TaskPage/index.ts new file mode 100644 index 0000000000..b129601766 --- /dev/null +++ b/plugins/scaffolder/src/next/TaskPage/index.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ +export { TaskPage } from './TaskPage'; diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.test.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.test.tsx index f605e9c114..12ad05ab75 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.test.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.test.tsx @@ -30,7 +30,7 @@ describe('Stepper', () => { }; const { getByText } = await renderInTestApp( - , + , ); for (const step of manifest.steps) { @@ -48,7 +48,7 @@ describe('Stepper', () => { }; const { getByRole } = await renderInTestApp( - , + , ); expect(getByRole('button', { name: 'Next' })).toBeInTheDocument(); @@ -88,7 +88,7 @@ describe('Stepper', () => { }; const { getByRole } = await renderInTestApp( - , + , ); await fireEvent.change(getByRole('textbox', { name: 'name' }), { @@ -134,6 +134,7 @@ describe('Stepper', () => { , ); diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx index 97f21111d3..fe055433b4 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { useApiHolder } from '@backstage/core-plugin-api'; -import { JsonObject } from '@backstage/types'; +import { useApi, useApiHolder } from '@backstage/core-plugin-api'; +import { JsonObject, JsonValue } from '@backstage/types'; import { Stepper as MuiStepper, Step as MuiStep, @@ -31,6 +31,7 @@ import { createAsyncValidators } from './createAsyncValidators'; import { useTemplateSchema } from './useTemplateSchema'; import { ReviewState } from './ReviewState'; import validator from '@rjsf/validator-ajv8'; +import { scaffolderApiRef } from '../../../api'; const useStyles = makeStyles(theme => ({ backButton: { @@ -50,6 +51,7 @@ const useStyles = makeStyles(theme => ({ export interface StepperProps { manifest: TemplateParameterSchema; extensions: NextFieldExtensionOptions[]; + onComplete: (values: Record) => Promise; } // TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly @@ -109,10 +111,6 @@ export const Stepper = (props: StepperProps) => { setFormState(current => ({ ...current, ...formData })); }; - const handleCreate = () => { - // TODO(blam): Create the template in a modal with the ability to view the logs etc. - }; - return ( <> @@ -161,7 +159,10 @@ export const Stepper = (props: StepperProps) => { > Back - diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index f6739e6389..f9dc97f32b 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { useEffect } from 'react'; +import React, { useContext, useEffect } from 'react'; import { Page, Header, @@ -23,7 +23,7 @@ import { MarkdownContent, } from '@backstage/core-components'; import { NextFieldExtensionOptions } from '../../extensions'; -import { Navigate } from 'react-router'; +import { Navigate, useNavigate } from 'react-router'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { errorApiRef, @@ -36,7 +36,13 @@ import useAsync from 'react-use/lib/useAsync'; import { makeStyles } from '@material-ui/core'; import { Stepper } from './Stepper'; import { BackstageTheme } from '@backstage/theme'; -import { nextRouteRef, selectedTemplateRouteRef } from '../../routes'; +import { + nextRouteRef, + nextScaffolderTaskRouteRef, + selectedTemplateRouteRef, +} from '../../routes'; +import { SecretsContext } from '../../components/secrets/SecretsContext'; +import { JsonValue } from '@backstage/types'; export interface TemplateWizardPageProps { customFieldExtensions: NextFieldExtensionOptions[]; @@ -67,17 +73,31 @@ const useTemplateParameterSchema = (templateRef: string) => { export const TemplateWizardPage = (props: TemplateWizardPageProps) => { const styles = useStyles(); const rootRef = useRouteRef(nextRouteRef); + const nextTemplateRef = useRouteRef(nextScaffolderTaskRouteRef); + const { secrets } = useContext(SecretsContext) ?? {}; + const scaffolderApi = useApi(scaffolderApiRef); + const navigate = useNavigate(); const { templateName, namespace } = useRouteRefParams( selectedTemplateRouteRef, ); + const templateRef = stringifyEntityRef({ + kind: 'Template', + namespace, + name: templateName, + }); + const errorApi = useApi(errorApiRef); - const { loading, manifest, error } = useTemplateParameterSchema( - stringifyEntityRef({ - kind: 'Template', - namespace, - name: templateName, - }), - ); + const { loading, manifest, error } = useTemplateParameterSchema(templateRef); + + const onComplete = async (values: Record) => { + const { taskId } = await scaffolderApi.scaffold({ + templateRef, + values, + secrets, + }); + + navigate(nextTemplateRef({ taskId })); + }; useEffect(() => { if (error) { @@ -113,6 +133,7 @@ export const TemplateWizardPage = (props: TemplateWizardPageProps) => { )} diff --git a/plugins/scaffolder/src/routes.ts b/plugins/scaffolder/src/routes.ts index 2ef6583b08..5e2d191443 100644 --- a/plugins/scaffolder/src/routes.ts +++ b/plugins/scaffolder/src/routes.ts @@ -65,6 +65,12 @@ export const scaffolderTaskRouteRef = createSubRouteRef({ path: '/tasks/:taskId', }); +export const nextScaffolderTaskRouteRef = createSubRouteRef({ + id: 'scaffolder/next/task', + parent: nextRouteRef, + path: '/tasks/:taskId', +}); + export const scaffolderListTaskRouteRef = createSubRouteRef({ id: 'scaffolder/list-tasks', parent: rootRouteRef,