From 79afad089a5ede2779fe8a2478728a7dd6f54537 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 19 Dec 2022 16:39:53 +0100 Subject: [PATCH] chore: support initial form data from queryString Signed-off-by: blam --- .../Stepper/Stepper.test.tsx | 32 +++++++++++++++++++ .../TemplateWizardPage/Stepper/Stepper.tsx | 4 ++- .../TemplateWizardPage/Stepper/useFormData.ts | 32 +++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 plugins/scaffolder/src/next/TemplateWizardPage/Stepper/useFormData.ts diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.test.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.test.tsx index 6c02492cd8..c8dbb0cb19 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.test.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.test.tsx @@ -189,6 +189,38 @@ describe('Stepper', () => { expect(getByText('invalid postcode')).toBeInTheDocument(); }); + it('should grab the initial formData from the query', async () => { + const manifest: TemplateParameterSchema = { + steps: [ + { + title: 'Step 1', + schema: { + properties: { + firstName: { + type: 'string', + }, + }, + }, + }, + ], + title: 'initialize formData', + }; + + const mockFormData = { firstName: 'John' }; + + Object.defineProperty(window, 'location', { + value: { + search: `?formData=${JSON.stringify(mockFormData)}`, + }, + }); + + const { getByRole } = await renderInTestApp( + , + ); + + expect(getByRole('textbox', { name: 'firstName' })).toHaveValue('John'); + }); + it('should initialize formState with undefined form values', async () => { const manifest: TemplateParameterSchema = { steps: [ diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx index 7051b197f1..fffacae2f2 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx @@ -38,6 +38,7 @@ import validator from '@rjsf/validator-ajv8'; import { selectedTemplateRouteRef } from '../../../routes'; import type { ErrorTransformer } from '@rjsf/utils'; import { getDefaultFormState } from '@rjsf/utils'; +import { useFormData } from './useFormData'; const useStyles = makeStyles(theme => ({ backButton: { @@ -72,7 +73,8 @@ export const Stepper = (props: StepperProps) => { const { steps } = useTemplateSchema(props.manifest); const apiHolder = useApiHolder(); const [activeStep, setActiveStep] = useState(0); - const [formState, setFormState] = useState>({}); + const [formState, setFormState] = useFormData(); + const [errors, setErrors] = useState< undefined | Record >(); diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/useFormData.ts b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/useFormData.ts new file mode 100644 index 0000000000..1500216688 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/useFormData.ts @@ -0,0 +1,32 @@ +/* + * 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 qs from 'qs'; +import { useState } from 'react'; + +export const useFormData = () => { + return useState>(() => { + const query = qs.parse(window.location.search, { + ignoreQueryPrefix: true, + }); + + try { + return JSON.parse(query.formData as string); + } catch (e) { + return {}; + } + }); +};