Merge pull request #17316 from backstage/blam/scaffolder/next/fixes

scaffolder/next: Added loading indicator for `AsyncValidation`
This commit is contained in:
Ben Lambert
2023-04-11 16:09:47 +02:00
committed by GitHub
3 changed files with 62 additions and 4 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-react': patch
---
Add indication that the validators are running
@@ -237,6 +237,50 @@ describe('Stepper', () => {
expect(getByText('im a custom field extension')).toBeInTheDocument();
});
it('should disable the form with progress when async validators are running', async () => {
const MockComponent = () => {
return <h1>im a custom field extension</h1>;
};
const manifest: TemplateParameterSchema = {
title: 'Custom Fields',
steps: [
{
title: 'Test',
schema: {
properties: {
name: {
type: 'string',
'ui:field': 'Mock',
},
},
},
},
],
};
const { getByRole } = await renderInTestApp(
<Stepper
manifest={manifest}
extensions={[
{
name: 'Mock',
component: MockComponent,
validation: async () => new Promise(r => setTimeout(r, 1000)),
},
]}
onCreate={jest.fn()}
/>,
);
await act(async () => {
await fireEvent.click(getByRole('button', { name: 'Review' }));
expect(getByRole('progressbar')).toBeInTheDocument();
expect(getByRole('button', { name: 'Review' })).toBeDisabled();
});
});
it('should transform default error message', async () => {
const manifest: TemplateParameterSchema = {
steps: [
@@ -21,6 +21,7 @@ import {
StepLabel as MuiStepLabel,
Button,
makeStyles,
LinearProgress,
} from '@material-ui/core';
import { type IChangeEvent } from '@rjsf/core-v5';
import { ErrorSchema } from '@rjsf/utils';
@@ -93,6 +94,7 @@ export const Stepper = (stepperProps: StepperProps) => {
const { steps } = useTemplateSchema(props.manifest);
const apiHolder = useApiHolder();
const [activeStep, setActiveStep] = useState(0);
const [isValidating, setIsValidating] = useState(false);
const [formState, setFormState] = useFormDataFromQuery(props.initialState);
const [errors, setErrors] = useState<undefined | FormValidation>();
@@ -133,12 +135,13 @@ export const Stepper = (stepperProps: StepperProps) => {
}: {
formData?: Record<string, JsonValue>;
}) => {
// TODO(blam): What do we do about loading states, does each field extension get a chance
// to display it's own loading? Or should we grey out the entire form.
setErrors(undefined);
setIsValidating(true);
const returnedValidation = await validation(formData);
setIsValidating(false);
if (hasErrors(returnedValidation)) {
setErrors(returnedValidation);
} else {
@@ -154,6 +157,7 @@ export const Stepper = (stepperProps: StepperProps) => {
return (
<>
{isValidating && <LinearProgress variant="indeterminate" />}
<MuiStepper activeStep={activeStep} alternativeLabel variant="elevation">
{steps.map((step, index) => (
<MuiStep key={index}>
@@ -183,11 +187,16 @@ export const Stepper = (stepperProps: StepperProps) => {
<Button
onClick={handleBack}
className={styles.backButton}
disabled={activeStep < 1}
disabled={activeStep < 1 || isValidating}
>
Back
</Button>
<Button variant="contained" color="primary" type="submit">
<Button
variant="contained"
color="primary"
type="submit"
disabled={isValidating}
>
{activeStep === steps.length - 1 ? reviewButtonText : 'Next'}
</Button>
</div>