chore: improve the implementation a little bit
Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
@@ -24,7 +24,7 @@ import {
|
||||
LinearProgress,
|
||||
} from '@material-ui/core';
|
||||
import { type IChangeEvent } from '@rjsf/core';
|
||||
import { ErrorSchema } from '@rjsf/utils';
|
||||
import { ErrorSchema, ValidatorType } from '@rjsf/utils';
|
||||
import React, {
|
||||
useCallback,
|
||||
useMemo,
|
||||
@@ -49,6 +49,7 @@ import {
|
||||
LayoutOptions,
|
||||
FieldExtensionOptions,
|
||||
FormProps,
|
||||
useTemplateSecrets,
|
||||
} from '@backstage/plugin-scaffolder-react';
|
||||
import { ReviewStepProps } from '@backstage/plugin-scaffolder-react';
|
||||
|
||||
@@ -102,6 +103,7 @@ export const Stepper = (stepperProps: StepperProps) => {
|
||||
reviewButtonText = 'Review',
|
||||
} = components;
|
||||
const analytics = useAnalytics();
|
||||
const { secrets } = useTemplateSecrets();
|
||||
const { presentation, steps } = useTemplateSchema(props.manifest);
|
||||
const apiHolder = useApiHolder();
|
||||
const [activeStep, setActiveStep] = useState(0);
|
||||
@@ -111,6 +113,31 @@ export const Stepper = (stepperProps: StepperProps) => {
|
||||
const [errors, setErrors] = useState<undefined | FormValidation>();
|
||||
const styles = useStyles();
|
||||
|
||||
const stringifiedSecrets = JSON.stringify(secrets);
|
||||
|
||||
// Because secrets can be defined in the schema, we need to make sure that they
|
||||
// are included in the validation process. So we merge the secrets and the formData
|
||||
// together in validation.
|
||||
const customValidator = useMemo<ValidatorType>(
|
||||
() => ({
|
||||
isValid: (schema, formData, rootSchema) =>
|
||||
validator.isValid(schema, { ...formData, ...secrets }, rootSchema),
|
||||
rawValidation: (schema, formData) =>
|
||||
validator.rawValidation(schema, { ...formData, ...secrets }),
|
||||
validateFormData: (formData, schema, customFormats, transformErrors) =>
|
||||
validator.validateFormData(
|
||||
{ ...formData, ...secrets },
|
||||
schema,
|
||||
customFormats,
|
||||
transformErrors,
|
||||
),
|
||||
// @deprecated
|
||||
toErrorList: validator.toErrorList,
|
||||
}),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[secrets, stringifiedSecrets],
|
||||
);
|
||||
|
||||
const extensions = useMemo(() => {
|
||||
return Object.fromEntries(
|
||||
props.extensions.map(({ name, component }) => [name, component]),
|
||||
@@ -220,7 +247,7 @@ export const Stepper = (stepperProps: StepperProps) => {
|
||||
{/* eslint-disable-next-line no-nested-ternary */}
|
||||
{activeStep < steps.length ? (
|
||||
<Form
|
||||
validator={validator}
|
||||
validator={customValidator}
|
||||
extraErrors={errors as unknown as ErrorSchema}
|
||||
formData={formState}
|
||||
formContext={{ formData: formState }}
|
||||
|
||||
+3
-3
@@ -18,7 +18,7 @@ import {
|
||||
SecretsContextProvider,
|
||||
useTemplateSecrets,
|
||||
} from '@backstage/plugin-scaffolder-react';
|
||||
import { Secret } from './Secret';
|
||||
import { SecretInput } from './SecretInput';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { Form } from '@backstage/plugin-scaffolder-react/alpha';
|
||||
import validator from '@rjsf/validator-ajv8';
|
||||
@@ -45,7 +45,7 @@ describe('<Secret/>', () => {
|
||||
'ui:field': 'Secret',
|
||||
}}
|
||||
fields={{
|
||||
Secret: Secret,
|
||||
Secret: SecretInput,
|
||||
}}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
@@ -86,7 +86,7 @@ describe('<Secret/>', () => {
|
||||
},
|
||||
}}
|
||||
fields={{
|
||||
Secret: Secret,
|
||||
Secret: SecretInput,
|
||||
}}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
+2
-17
@@ -19,10 +19,7 @@ import { ScaffolderRJSFFieldProps } from '@backstage/plugin-scaffolder-react';
|
||||
import { ScaffolderField } from '@backstage/plugin-scaffolder-react/alpha';
|
||||
import { Input, InputLabel } from '@material-ui/core';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const Secret = (props: ScaffolderRJSFFieldProps) => {
|
||||
export const SecretInput = (props: ScaffolderRJSFFieldProps) => {
|
||||
const { setSecrets, secrets } = useTemplateSecrets();
|
||||
const {
|
||||
name,
|
||||
@@ -30,7 +27,6 @@ export const Secret = (props: ScaffolderRJSFFieldProps) => {
|
||||
rawErrors,
|
||||
disabled,
|
||||
errors,
|
||||
onChange,
|
||||
required,
|
||||
} = props;
|
||||
|
||||
@@ -46,18 +42,7 @@ export const Secret = (props: ScaffolderRJSFFieldProps) => {
|
||||
<Input
|
||||
id={title}
|
||||
aria-describedby={title}
|
||||
onChange={e => {
|
||||
// TODO(blam): this is a bit of a hack. We need to to probably figure out
|
||||
// how to provide our own validator that can filter out the secrets from the
|
||||
// jsonschema, or merge the secrets with the formData for validation?
|
||||
// Makes the review step a little cleaner with this though.
|
||||
onChange(
|
||||
Array(e.target?.value.length ?? 0)
|
||||
.fill('*')
|
||||
.join(''),
|
||||
);
|
||||
setSecrets({ [name]: e.target?.value });
|
||||
}}
|
||||
onChange={e => setSecrets({ [name]: e.target?.value })}
|
||||
value={secrets[name] ?? ''}
|
||||
type="password"
|
||||
autoComplete="off"
|
||||
+1
-1
@@ -13,4 +13,4 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export * from './Secret';
|
||||
export * from './SecretInput';
|
||||
@@ -19,6 +19,5 @@ export * from './RepoUrlPicker';
|
||||
export * from './OwnedEntityPicker';
|
||||
export * from './EntityTagsPicker';
|
||||
export * from './MyGroupsPicker';
|
||||
export * from './Secret';
|
||||
|
||||
export { type FieldSchema, makeFieldSchemaFromZod } from './utils';
|
||||
|
||||
@@ -43,7 +43,8 @@ import {
|
||||
MyGroupsPicker,
|
||||
MyGroupsPickerSchema,
|
||||
} from '../components/fields/MyGroupsPicker/MyGroupsPicker';
|
||||
import { Secret } from '../components';
|
||||
|
||||
import { SecretInput } from '../components/fields/SecretInput';
|
||||
|
||||
export const DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS = [
|
||||
{
|
||||
@@ -84,7 +85,7 @@ export const DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS = [
|
||||
schema: MyGroupsPickerSchema,
|
||||
},
|
||||
{
|
||||
component: Secret,
|
||||
component: SecretInput,
|
||||
name: 'Secret',
|
||||
},
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user