Merge pull request #26363 from jboeijenga/feat/support-omitExtraData
Add support for omitExtraData and liveOmit properties in scaffolder.
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-react': minor
|
||||
'@backstage/plugin-scaffolder': minor
|
||||
---
|
||||
|
||||
Added support for `omitExtraData` and `liveOmit` for rjsf in the scaffolder
|
||||
@@ -128,7 +128,12 @@ export interface FieldExtensionUiSchema<TFieldReturnValue, TUiOptions>
|
||||
// @public
|
||||
export type FormProps = Pick<
|
||||
FormProps_2,
|
||||
'transformErrors' | 'noHtml5Validate' | 'uiSchema' | 'formContext'
|
||||
| 'transformErrors'
|
||||
| 'noHtml5Validate'
|
||||
| 'uiSchema'
|
||||
| 'formContext'
|
||||
| 'omitExtraData'
|
||||
| 'liveOmit'
|
||||
>;
|
||||
|
||||
// @public
|
||||
|
||||
@@ -32,7 +32,12 @@ export type TemplateGroupFilter = {
|
||||
*/
|
||||
export type FormProps = Pick<
|
||||
SchemaFormProps,
|
||||
'transformErrors' | 'noHtml5Validate' | 'uiSchema' | 'formContext'
|
||||
| 'transformErrors'
|
||||
| 'noHtml5Validate'
|
||||
| 'uiSchema'
|
||||
| 'formContext'
|
||||
| 'omitExtraData'
|
||||
| 'liveOmit'
|
||||
>;
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,16 +13,17 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
import { act, fireEvent, waitFor } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import { LayoutTemplate } from '../../../layouts';
|
||||
import { SecretsContextProvider } from '../../../secrets';
|
||||
import { TemplateParameterSchema } from '../../../types';
|
||||
import { Stepper } from './Stepper';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { act, fireEvent } from '@testing-library/react';
|
||||
|
||||
import type { RJSFValidationError } from '@rjsf/utils';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
import { FieldExtensionComponentProps } from '../../../extensions';
|
||||
import { SecretsContextProvider } from '../../../secrets';
|
||||
import { LayoutTemplate } from '../../../layouts';
|
||||
|
||||
describe('Stepper', () => {
|
||||
it('should render the step titles for each step of the manifest', async () => {
|
||||
@@ -63,7 +64,7 @@ describe('Stepper', () => {
|
||||
expect(getByRole('button', { name: 'Next' })).toBeInTheDocument();
|
||||
|
||||
await act(async () => {
|
||||
await fireEvent.click(getByRole('button', { name: 'Next' }));
|
||||
fireEvent.click(getByRole('button', { name: 'Next' }));
|
||||
});
|
||||
|
||||
expect(getByRole('button', { name: 'Review' })).toBeInTheDocument();
|
||||
@@ -102,16 +103,15 @@ describe('Stepper', () => {
|
||||
</SecretsContextProvider>,
|
||||
);
|
||||
|
||||
await fireEvent.change(getByRole('textbox', { name: 'name' }), {
|
||||
target: { value: 'im a test value' },
|
||||
await act(async () => {
|
||||
fireEvent.change(getByRole('textbox', { name: 'name' }), {
|
||||
target: { value: 'im a test value' },
|
||||
});
|
||||
fireEvent.click(getByRole('button', { name: 'Next' }));
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await fireEvent.click(getByRole('button', { name: 'Next' }));
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await fireEvent.click(getByRole('button', { name: 'Back' }));
|
||||
fireEvent.click(getByRole('button', { name: 'Back' }));
|
||||
});
|
||||
|
||||
expect(getByRole('textbox', { name: 'name' })).toHaveValue(
|
||||
@@ -152,16 +152,15 @@ describe('Stepper', () => {
|
||||
</SecretsContextProvider>,
|
||||
);
|
||||
|
||||
await fireEvent.change(getByRole('textbox', { name: 'name' }), {
|
||||
target: { value: 'im a test value' },
|
||||
await act(async () => {
|
||||
fireEvent.change(getByRole('textbox', { name: 'name' }), {
|
||||
target: { value: 'im a test value' },
|
||||
});
|
||||
fireEvent.click(getByRole('button', { name: 'Next' }));
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await fireEvent.click(getByRole('button', { name: 'Next' }));
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await fireEvent.click(getByLabelText('Step 1'));
|
||||
fireEvent.click(getByLabelText('Step 1'));
|
||||
});
|
||||
|
||||
expect(getByRole('textbox', { name: 'name' })).toHaveValue(
|
||||
@@ -169,38 +168,107 @@ describe('Stepper', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should merge nested formData correctly in multiple steps', async () => {
|
||||
const Repo = ({
|
||||
onChange,
|
||||
}: FieldExtensionComponentProps<{ repository: string }, any>) => (
|
||||
<input
|
||||
aria-label="repo"
|
||||
type="text"
|
||||
onChange={e => onChange({ repository: e.target.value })}
|
||||
defaultValue=""
|
||||
/>
|
||||
it('should omit properties that are no longer pertinent to the current step', async () => {
|
||||
const manifest: TemplateParameterSchema = {
|
||||
title: 'Conditional Input Form',
|
||||
steps: [
|
||||
{
|
||||
title: 'Conditional Input step',
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
moreInfo: {
|
||||
type: 'boolean',
|
||||
title: 'More info',
|
||||
},
|
||||
},
|
||||
dependencies: {
|
||||
moreInfo: {
|
||||
oneOf: [
|
||||
{
|
||||
properties: {
|
||||
moreInfo: {
|
||||
const: true,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
title: 'Description',
|
||||
},
|
||||
},
|
||||
required: ['description'],
|
||||
},
|
||||
{
|
||||
properties: {
|
||||
moreInfo: {
|
||||
not: {
|
||||
const: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const onCreate = jest.fn();
|
||||
|
||||
const { getByRole, queryByRole } = await renderInTestApp(
|
||||
<SecretsContextProvider>
|
||||
<Stepper
|
||||
manifest={manifest}
|
||||
onCreate={onCreate}
|
||||
extensions={[]}
|
||||
formProps={{ omitExtraData: true, liveOmit: true }}
|
||||
/>
|
||||
</SecretsContextProvider>,
|
||||
);
|
||||
|
||||
const Owner = ({
|
||||
onChange,
|
||||
}: FieldExtensionComponentProps<{ owner: string }, any>) => (
|
||||
<input
|
||||
aria-label="owner"
|
||||
type="text"
|
||||
onChange={e => onChange({ owner: e.target.value })}
|
||||
defaultValue=""
|
||||
/>
|
||||
);
|
||||
await act(async () => {
|
||||
fireEvent.click(getByRole('checkbox', { name: 'More info' }));
|
||||
fireEvent.change(getByRole('textbox', { name: 'Description' }), {
|
||||
target: { value: 'My Test Description' },
|
||||
});
|
||||
fireEvent.click(getByRole('button', { name: 'Review' }));
|
||||
});
|
||||
|
||||
expect(
|
||||
getByRole('cell', { name: 'My Test Description' }),
|
||||
).toBeInTheDocument();
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(getByRole('button', { name: 'Back' }));
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(getByRole('checkbox', { name: 'More info' }));
|
||||
fireEvent.click(getByRole('button', { name: 'Review' }));
|
||||
});
|
||||
|
||||
expect(
|
||||
queryByRole('cell', { name: 'My Test Description' }),
|
||||
).not.toBeInTheDocument();
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(getByRole('button', { name: 'Create' }));
|
||||
});
|
||||
|
||||
expect(onCreate).toHaveBeenCalledWith({ moreInfo: false });
|
||||
});
|
||||
|
||||
it('should merge and overwrite nested formData correctly', async () => {
|
||||
const manifest: TemplateParameterSchema = {
|
||||
steps: [
|
||||
{
|
||||
title: 'Step 1',
|
||||
schema: {
|
||||
properties: {
|
||||
first: {
|
||||
type: 'object',
|
||||
'ui:field': 'Repo',
|
||||
foo: {
|
||||
type: 'string',
|
||||
title: 'Foo - 1',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -209,9 +277,13 @@ describe('Stepper', () => {
|
||||
title: 'Step 2',
|
||||
schema: {
|
||||
properties: {
|
||||
second: {
|
||||
type: 'object',
|
||||
'ui:field': 'Owner',
|
||||
foo: {
|
||||
type: 'string',
|
||||
title: 'Foo - 2',
|
||||
},
|
||||
bar: {
|
||||
type: 'string',
|
||||
title: 'Bar - 2',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -220,47 +292,39 @@ describe('Stepper', () => {
|
||||
title: 'React JSON Schema Form Test',
|
||||
};
|
||||
|
||||
const onCreate = jest.fn(async (values: Record<string, JsonValue>) => {
|
||||
expect(values).toEqual({
|
||||
first: { repository: 'Repo' },
|
||||
second: { owner: 'Owner' },
|
||||
});
|
||||
});
|
||||
const onCreate = jest.fn();
|
||||
|
||||
const { getByRole } = await renderInTestApp(
|
||||
<SecretsContextProvider>
|
||||
<Stepper
|
||||
manifest={manifest}
|
||||
onCreate={onCreate}
|
||||
extensions={[
|
||||
{ name: 'Repo', component: Repo },
|
||||
{ name: 'Owner', component: Owner },
|
||||
]}
|
||||
/>
|
||||
<Stepper manifest={manifest} onCreate={onCreate} extensions={[]} />
|
||||
</SecretsContextProvider>,
|
||||
);
|
||||
|
||||
await fireEvent.change(getByRole('textbox', { name: 'repo' }), {
|
||||
target: { value: 'Repo' },
|
||||
await act(async () => {
|
||||
fireEvent.change(getByRole('textbox', { name: 'Foo - 1' }), {
|
||||
target: { value: 'value 1' },
|
||||
});
|
||||
fireEvent.click(getByRole('button', { name: 'Next' }));
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await fireEvent.click(getByRole('button', { name: 'Next' }));
|
||||
});
|
||||
|
||||
await fireEvent.change(getByRole('textbox', { name: 'owner' }), {
|
||||
target: { value: 'Owner' },
|
||||
fireEvent.change(getByRole('textbox', { name: 'Foo - 2' }), {
|
||||
target: { value: 'value 2' },
|
||||
});
|
||||
fireEvent.change(getByRole('textbox', { name: 'Bar - 2' }), {
|
||||
target: { value: 'value 2' },
|
||||
});
|
||||
fireEvent.click(getByRole('button', { name: 'Review' }));
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await fireEvent.click(getByRole('button', { name: 'Review' }));
|
||||
fireEvent.click(getByRole('button', { name: 'Create' }));
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await fireEvent.click(getByRole('button', { name: 'Create' }));
|
||||
expect(onCreate).toHaveBeenCalledWith({
|
||||
foo: 'value 2',
|
||||
bar: 'value 2',
|
||||
});
|
||||
|
||||
expect(onCreate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should render custom field extensions properly', async () => {
|
||||
@@ -335,13 +399,11 @@ describe('Stepper', () => {
|
||||
/>
|
||||
</SecretsContextProvider>,
|
||||
);
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(getByRole('button', { name: 'Review' }));
|
||||
fireEvent.click(getByRole('button', { name: 'Review' }));
|
||||
await waitFor(() => {
|
||||
expect(getByRole('progressbar')).toBeInTheDocument(); // Check if progress bar is rendered
|
||||
expect(getByRole('button', { name: 'Review' })).toBeDisabled(); // Check if the button is disabled
|
||||
});
|
||||
|
||||
expect(getByRole('progressbar')).toBeInTheDocument();
|
||||
expect(getByRole('button', { name: 'Review' })).toBeDisabled();
|
||||
});
|
||||
|
||||
it('should transform default error message', async () => {
|
||||
@@ -381,12 +443,11 @@ describe('Stepper', () => {
|
||||
</SecretsContextProvider>,
|
||||
);
|
||||
|
||||
await fireEvent.change(getByRole('textbox', { name: 'postcode' }), {
|
||||
target: { value: 'invalid' },
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await fireEvent.click(getByRole('button', { name: 'Review' }));
|
||||
fireEvent.change(getByRole('textbox', { name: 'postcode' }), {
|
||||
target: { value: 'invalid' },
|
||||
});
|
||||
fireEvent.click(getByRole('button', { name: 'Review' }));
|
||||
});
|
||||
|
||||
expect(getByText('invalid postcode')).toBeInTheDocument();
|
||||
@@ -421,12 +482,12 @@ describe('Stepper', () => {
|
||||
</SecretsContextProvider>,
|
||||
);
|
||||
|
||||
await fireEvent.change(getByRole('textbox', { name: 'postcode' }), {
|
||||
target: { value: 'invalid' },
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await fireEvent.click(getByRole('button', { name: 'Review' }));
|
||||
fireEvent.change(getByRole('textbox', { name: 'postcode' }), {
|
||||
target: { value: 'invalid' },
|
||||
});
|
||||
|
||||
fireEvent.click(getByRole('button', { name: 'Review' }));
|
||||
});
|
||||
|
||||
expect(getByText('invalid postcode')).toBeInTheDocument();
|
||||
@@ -494,13 +555,13 @@ describe('Stepper', () => {
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
await fireEvent.click(getByRole('button', { name: 'Review' }));
|
||||
fireEvent.click(getByRole('button', { name: 'Review' }));
|
||||
});
|
||||
|
||||
expect(getByRole('button', { name: 'Create' })).toBeInTheDocument();
|
||||
|
||||
await act(async () => {
|
||||
await fireEvent.click(getByRole('button', { name: 'Create' }));
|
||||
fireEvent.click(getByRole('button', { name: 'Create' }));
|
||||
});
|
||||
|
||||
// flush promises
|
||||
@@ -539,13 +600,13 @@ describe('Stepper', () => {
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
await fireEvent.click(getByRole('button', { name: 'Inspect' }));
|
||||
fireEvent.click(getByRole('button', { name: 'Inspect' }));
|
||||
});
|
||||
|
||||
expect(getByRole('button', { name: 'Make' })).toBeInTheDocument();
|
||||
|
||||
await act(async () => {
|
||||
await fireEvent.click(getByRole('button', { name: 'Make' }));
|
||||
fireEvent.click(getByRole('button', { name: 'Make' }));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -115,11 +115,16 @@ export const Stepper = (stepperProps: StepperProps) => {
|
||||
const apiHolder = useApiHolder();
|
||||
const [activeStep, setActiveStep] = useState(0);
|
||||
const [isValidating, setIsValidating] = useState(false);
|
||||
const [formState, setFormState] = useFormDataFromQuery(props.initialState);
|
||||
const [initialState] = useFormDataFromQuery(props.initialState);
|
||||
const [formState, setFormState] = useState<{
|
||||
[step: string]: Record<string, JsonValue>;
|
||||
}>();
|
||||
|
||||
const [errors, setErrors] = useState<undefined | FormValidation>();
|
||||
const styles = useStyles();
|
||||
|
||||
const makeStepKey = (step: string | number) => `step-${step}`;
|
||||
|
||||
const backLabel =
|
||||
presentation?.buttonLabels?.backButtonText ?? backButtonText;
|
||||
const createLabel =
|
||||
@@ -155,16 +160,15 @@ export const Stepper = (stepperProps: StepperProps) => {
|
||||
};
|
||||
|
||||
const handleChange = useCallback(
|
||||
(e: IChangeEvent) =>
|
||||
setFormState(current => ({ ...current, ...e.formData })),
|
||||
[setFormState],
|
||||
(e: IChangeEvent) => {
|
||||
setFormState(current => ({
|
||||
...current,
|
||||
[makeStepKey(activeStep)]: e.formData,
|
||||
}));
|
||||
},
|
||||
[setFormState, activeStep],
|
||||
);
|
||||
|
||||
const handleCreate = useCallback(() => {
|
||||
props.onCreate(formState);
|
||||
analytics.captureEvent('click', `${createLabel}`);
|
||||
}, [props, formState, analytics, createLabel]);
|
||||
|
||||
const currentStep = useTransformSchemaToProps(steps[activeStep], { layouts });
|
||||
|
||||
const handleNext = async ({
|
||||
@@ -191,7 +195,10 @@ export const Stepper = (stepperProps: StepperProps) => {
|
||||
return stepNum;
|
||||
});
|
||||
}
|
||||
setFormState(current => ({ ...current, ...formData }));
|
||||
setFormState(current => ({
|
||||
...current,
|
||||
[makeStepKey(activeStep)]: formData,
|
||||
}));
|
||||
};
|
||||
|
||||
const {
|
||||
@@ -202,6 +209,24 @@ export const Stepper = (stepperProps: StepperProps) => {
|
||||
|
||||
const mergedUiSchema = merge({}, propUiSchema, currentStep?.uiSchema);
|
||||
|
||||
const mergedState = useMemo(() => {
|
||||
if (!formState) {
|
||||
return initialState;
|
||||
}
|
||||
const { [makeStepKey(activeStep)]: activeState, ...historicalState } =
|
||||
formState;
|
||||
const chronologicalState = {
|
||||
...historicalState,
|
||||
[makeStepKey(activeStep)]: activeState,
|
||||
};
|
||||
return merge({}, ...Object.values(chronologicalState));
|
||||
}, [formState, activeStep, initialState]);
|
||||
|
||||
const handleCreate = useCallback(() => {
|
||||
props.onCreate(mergedState);
|
||||
analytics.captureEvent('click', `${createLabel}`);
|
||||
}, [props, mergedState, analytics, createLabel]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{isValidating && <LinearProgress variant="indeterminate" />}
|
||||
@@ -237,8 +262,8 @@ export const Stepper = (stepperProps: StepperProps) => {
|
||||
<Form
|
||||
validator={validator}
|
||||
extraErrors={errors as unknown as ErrorSchema}
|
||||
formData={formState}
|
||||
formContext={{ ...propFormContext, formData: formState }}
|
||||
formData={mergedState}
|
||||
formContext={{ ...propFormContext, formData: mergedState }}
|
||||
schema={currentStep.schema}
|
||||
uiSchema={mergedUiSchema}
|
||||
onSubmit={handleNext}
|
||||
@@ -274,7 +299,7 @@ export const Stepper = (stepperProps: StepperProps) => {
|
||||
ReviewStepComponent ? (
|
||||
<ReviewStepComponent
|
||||
disableButtons={isValidating}
|
||||
formData={formState}
|
||||
formData={mergedState}
|
||||
handleBack={handleBack}
|
||||
handleReset={() => {}}
|
||||
steps={steps}
|
||||
@@ -282,7 +307,7 @@ export const Stepper = (stepperProps: StepperProps) => {
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<ReviewStateComponent formState={formState} schemas={steps} />
|
||||
<ReviewStateComponent formState={mergedState} schemas={steps} />
|
||||
<div className={styles.footer}>
|
||||
<Button
|
||||
onClick={handleBack}
|
||||
|
||||
@@ -166,6 +166,7 @@ export const Router = (props: PropsWithChildren<RouterProps>) => {
|
||||
<TemplateEditorPage
|
||||
customFieldExtensions={fieldExtensions}
|
||||
layouts={customLayouts}
|
||||
formProps={props.formProps}
|
||||
/>
|
||||
</SecretsContextProvider>
|
||||
}
|
||||
|
||||
@@ -15,7 +15,10 @@
|
||||
*/
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import React, { useState } from 'react';
|
||||
import type { LayoutOptions } from '@backstage/plugin-scaffolder-react';
|
||||
import type {
|
||||
FormProps,
|
||||
LayoutOptions,
|
||||
} from '@backstage/plugin-scaffolder-react';
|
||||
import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react';
|
||||
import { TemplateDirectoryAccess } from '../../lib/filesystem';
|
||||
import { DirectoryEditorProvider } from './DirectoryEditorContext';
|
||||
@@ -60,6 +63,7 @@ export const TemplateEditor = (props: {
|
||||
fieldExtensions?: FieldExtensionOptions<any, any>[];
|
||||
layouts?: LayoutOptions[];
|
||||
onClose?: () => void;
|
||||
formProps?: FormProps;
|
||||
}) => {
|
||||
const classes = useStyles();
|
||||
|
||||
@@ -80,6 +84,7 @@ export const TemplateEditor = (props: {
|
||||
setErrorText={setErrorText}
|
||||
fieldExtensions={props.fieldExtensions}
|
||||
layouts={props.layouts}
|
||||
formProps={props.formProps}
|
||||
/>
|
||||
</section>
|
||||
<section className={classes.results}>
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
LayoutOptions,
|
||||
TemplateParameterSchema,
|
||||
FieldExtensionOptions,
|
||||
FormProps,
|
||||
} from '@backstage/plugin-scaffolder-react';
|
||||
import {
|
||||
Stepper,
|
||||
@@ -87,6 +88,7 @@ interface TemplateEditorFormProps {
|
||||
onDryRun?: (data: JsonObject) => Promise<void>;
|
||||
fieldExtensions?: FieldExtensionOptions<any, any>[];
|
||||
layouts?: LayoutOptions[];
|
||||
formProps?: FormProps;
|
||||
}
|
||||
|
||||
function isJsonObject(value: JsonValue | undefined): value is JsonObject {
|
||||
@@ -195,6 +197,7 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) {
|
||||
await onDryRun?.(options);
|
||||
}}
|
||||
layouts={layouts}
|
||||
formProps={props.formProps}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
@@ -206,7 +209,7 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) {
|
||||
export function TemplateEditorFormDirectoryEditorDryRun(
|
||||
props: Pick<
|
||||
TemplateEditorFormProps,
|
||||
'setErrorText' | 'fieldExtensions' | 'layouts'
|
||||
'setErrorText' | 'fieldExtensions' | 'layouts' | 'formProps'
|
||||
>,
|
||||
) {
|
||||
const { setErrorText, fieldExtensions = [], layouts } = props;
|
||||
@@ -245,6 +248,7 @@ export function TemplateEditorFormDirectoryEditorDryRun(
|
||||
setErrorText={setErrorText}
|
||||
content={content}
|
||||
layouts={layouts}
|
||||
formProps={props.formProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import { TemplateEditor } from './TemplateEditor';
|
||||
import { TemplateFormPreviewer } from './TemplateFormPreviewer';
|
||||
import {
|
||||
FieldExtensionOptions,
|
||||
FormProps,
|
||||
type LayoutOptions,
|
||||
} from '@backstage/plugin-scaffolder-react';
|
||||
import { TemplateEditorIntro } from './TemplateEditorIntro';
|
||||
@@ -54,6 +55,7 @@ interface TemplateEditorPageProps {
|
||||
defaultPreviewTemplate?: string;
|
||||
customFieldExtensions?: FieldExtensionOptions<any, any>[];
|
||||
layouts?: LayoutOptions[];
|
||||
formProps?: FormProps;
|
||||
}
|
||||
|
||||
export function TemplateEditorPage(props: TemplateEditorPageProps) {
|
||||
@@ -79,6 +81,7 @@ export function TemplateEditorPage(props: TemplateEditorPageProps) {
|
||||
fieldExtensions={props.customFieldExtensions}
|
||||
onClose={() => setSelection(undefined)}
|
||||
layouts={props.layouts}
|
||||
formProps={props.formProps}
|
||||
/>
|
||||
);
|
||||
} else if (selection?.type === 'form') {
|
||||
@@ -88,6 +91,7 @@ export function TemplateEditorPage(props: TemplateEditorPageProps) {
|
||||
customFieldExtensions={props.customFieldExtensions}
|
||||
onClose={() => setSelection(undefined)}
|
||||
layouts={props.layouts}
|
||||
formProps={props.formProps}
|
||||
/>
|
||||
);
|
||||
} else if (selection?.type === 'field-explorer') {
|
||||
|
||||
@@ -33,6 +33,7 @@ import yaml from 'yaml';
|
||||
import {
|
||||
LayoutOptions,
|
||||
FieldExtensionOptions,
|
||||
FormProps,
|
||||
} from '@backstage/plugin-scaffolder-react';
|
||||
import { TemplateEditorForm } from './TemplateEditorForm';
|
||||
import { TemplateEditorTextArea } from './TemplateEditorTextArea';
|
||||
@@ -114,11 +115,13 @@ export const TemplateFormPreviewer = ({
|
||||
customFieldExtensions = [],
|
||||
onClose,
|
||||
layouts = [],
|
||||
formProps,
|
||||
}: {
|
||||
defaultPreviewTemplate?: string;
|
||||
customFieldExtensions?: FieldExtensionOptions<any, any>[];
|
||||
onClose?: () => void;
|
||||
layouts?: LayoutOptions[];
|
||||
formProps?: FormProps;
|
||||
}) => {
|
||||
const classes = useStyles();
|
||||
const { t } = useTranslationRef(scaffolderTranslationRef);
|
||||
@@ -213,6 +216,7 @@ export const TemplateFormPreviewer = ({
|
||||
fieldExtensions={customFieldExtensions}
|
||||
setErrorText={setErrorText}
|
||||
layouts={layouts}
|
||||
formProps={formProps}
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user