fix(catalog-import): migrate to the new react-hook-form version
Signed-off-by: Dominik Henneke <dominik.henneke@sda-se.com>
This commit is contained in:
committed by
Fredrik Adelöw
parent
508520ffbc
commit
3c684fdb9c
@@ -9,7 +9,7 @@ import { ApiRef } from '@backstage/core-plugin-api';
|
||||
import { BackstagePlugin } from '@backstage/core-plugin-api';
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
import { ConfigApi } from '@backstage/core-plugin-api';
|
||||
import { Control } from 'react-hook-form';
|
||||
import { Controller } from 'react-hook-form';
|
||||
import { DiscoveryApi } from '@backstage/core-plugin-api';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { EntityName } from '@backstage/catalog-model';
|
||||
@@ -23,9 +23,8 @@ import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { SubmitHandler } from 'react-hook-form';
|
||||
import { TextFieldProps } from '@material-ui/core/TextField/TextField';
|
||||
import { UnpackNestedValue } from 'react-hook-form';
|
||||
import { UseControllerOptions } from 'react-hook-form';
|
||||
import { UseFormMethods } from 'react-hook-form';
|
||||
import { UseFormOptions } from 'react-hook-form';
|
||||
import { UseFormProps } from 'react-hook-form';
|
||||
import { UseFormReturn } from 'react-hook-form';
|
||||
|
||||
// Warning: (ae-missing-release-tag) "AnalyzeResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
@@ -53,7 +52,6 @@ export const AutocompleteTextField: <TFieldValue extends string>({
|
||||
name,
|
||||
options,
|
||||
required,
|
||||
control,
|
||||
errors,
|
||||
rules,
|
||||
loading,
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ConfigApi } from '@backstage/core-plugin-api';
|
||||
import {
|
||||
Box,
|
||||
Checkbox,
|
||||
@@ -25,6 +26,7 @@ import {
|
||||
} from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { BackButton } from '../Buttons';
|
||||
import { asInputRef } from '../helpers';
|
||||
import { StepFinishImportLocation } from '../StepFinishImportLocation';
|
||||
import { StepInitAnalyzeUrl } from '../StepInitAnalyzeUrl';
|
||||
import {
|
||||
@@ -34,7 +36,6 @@ import {
|
||||
import { StepPrepareSelectLocations } from '../StepPrepareSelectLocations';
|
||||
import { StepReviewLocation } from '../StepReviewLocation';
|
||||
import { ImportFlows, ImportState } from '../useImportState';
|
||||
import { ConfigApi } from '@backstage/core-plugin-api';
|
||||
|
||||
export type StepperProviderOpts = {
|
||||
pullRequest?: {
|
||||
@@ -186,7 +187,7 @@ export function defaultGenerateStepper(
|
||||
defaultBody={body}
|
||||
renderFormFields={({
|
||||
values,
|
||||
control,
|
||||
setValue,
|
||||
errors,
|
||||
groupsLoading,
|
||||
groups,
|
||||
@@ -198,25 +199,31 @@ export function defaultGenerateStepper(
|
||||
</Box>
|
||||
|
||||
<TextField
|
||||
name="title"
|
||||
{...asInputRef(
|
||||
register('title', {
|
||||
required: true,
|
||||
}),
|
||||
)}
|
||||
label="Pull Request Title"
|
||||
placeholder="Add Backstage catalog entity descriptor files"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
inputRef={register({ required: true })}
|
||||
error={Boolean(errors.title)}
|
||||
required
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="body"
|
||||
{...asInputRef(
|
||||
register('body', {
|
||||
required: true,
|
||||
}),
|
||||
)}
|
||||
label="Pull Request Body"
|
||||
placeholder="A describing text with Markdown support"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
inputRef={register({ required: true })}
|
||||
error={Boolean(errors.body)}
|
||||
multiline
|
||||
required
|
||||
@@ -227,13 +234,14 @@ export function defaultGenerateStepper(
|
||||
</Box>
|
||||
|
||||
<TextField
|
||||
name="componentName"
|
||||
{...asInputRef(
|
||||
register('componentName', { required: true }),
|
||||
)}
|
||||
label="Name of the created component"
|
||||
placeholder="my-component"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
inputRef={register({ required: true })}
|
||||
error={Boolean(errors.componentName)}
|
||||
required
|
||||
/>
|
||||
@@ -241,7 +249,6 @@ export function defaultGenerateStepper(
|
||||
{!values.useCodeowners && (
|
||||
<AutocompleteTextField
|
||||
name="owner"
|
||||
control={control}
|
||||
errors={errors}
|
||||
options={groups || []}
|
||||
loading={groupsLoading}
|
||||
@@ -260,11 +267,10 @@ export function defaultGenerateStepper(
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
name="useCodeowners"
|
||||
inputRef={register}
|
||||
{...asInputRef(register('useCodeowners'))}
|
||||
onChange={(_, value) => {
|
||||
if (value) {
|
||||
control.setValue('owner', '');
|
||||
setValue('owner', '');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -14,13 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { errorApiRef, useApi } from '@backstage/core-plugin-api';
|
||||
import { FormHelperText, Grid, TextField } from '@material-ui/core';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { AnalyzeResult, catalogImportApiRef } from '../../api';
|
||||
import { NextButton } from '../Buttons';
|
||||
import { asInputRef } from '../helpers';
|
||||
import { ImportFlows, PrepareResult } from '../useImportState';
|
||||
import { errorApiRef, useApi } from '@backstage/core-plugin-api';
|
||||
|
||||
type FormData = {
|
||||
url: string;
|
||||
@@ -123,15 +124,17 @@ export const StepInitAnalyzeUrl = ({
|
||||
return (
|
||||
<form onSubmit={handleSubmit(handleResult)}>
|
||||
<TextField
|
||||
{...register('url', {
|
||||
required: true,
|
||||
validate: {
|
||||
httpsValidator: (value: any) =>
|
||||
(typeof value === 'string' &&
|
||||
value.match(/^http[s]?:\/\//) !== null) ||
|
||||
'Must start with http:// or https://.',
|
||||
},
|
||||
})}
|
||||
{...asInputRef(
|
||||
register('url', {
|
||||
required: true,
|
||||
validate: {
|
||||
httpsValidator: (value: any) =>
|
||||
(typeof value === 'string' &&
|
||||
value.match(/^http[s]?:\/\//) !== null) ||
|
||||
'Must start with http:// or https://.',
|
||||
},
|
||||
}),
|
||||
)}
|
||||
fullWidth
|
||||
id="url"
|
||||
label="Repository URL"
|
||||
|
||||
+5
-6
@@ -18,14 +18,13 @@ import { CircularProgress, TextField } from '@material-ui/core';
|
||||
import { TextFieldProps } from '@material-ui/core/TextField/TextField';
|
||||
import { Autocomplete } from '@material-ui/lab';
|
||||
import React from 'react';
|
||||
import { Control, Controller, FieldErrors } from 'react-hook-form';
|
||||
import { Controller, FieldErrors } from 'react-hook-form';
|
||||
|
||||
type Props<TFieldValue extends string> = {
|
||||
name: TFieldValue;
|
||||
options: string[];
|
||||
required?: boolean;
|
||||
|
||||
control?: Control<Record<string, any>>;
|
||||
errors?: FieldErrors<Record<TFieldValue, string>>;
|
||||
rules?: React.ComponentProps<typeof Controller>['rules'];
|
||||
|
||||
@@ -42,7 +41,6 @@ export const AutocompleteTextField = <TFieldValue extends string>({
|
||||
name,
|
||||
options,
|
||||
required,
|
||||
control,
|
||||
errors,
|
||||
rules,
|
||||
loading = false,
|
||||
@@ -54,16 +52,17 @@ export const AutocompleteTextField = <TFieldValue extends string>({
|
||||
return (
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
rules={rules}
|
||||
render={({ field }) => (
|
||||
render={({ field: { onChange } }) => (
|
||||
<Autocomplete
|
||||
loading={loading}
|
||||
loadingText={loadingText}
|
||||
options={options || []}
|
||||
autoSelect
|
||||
freeSolo
|
||||
{...field}
|
||||
onChange={(_event: React.ChangeEvent<{}>, value: string | null) =>
|
||||
onChange(value)
|
||||
}
|
||||
renderInput={params => (
|
||||
<TextField
|
||||
{...params}
|
||||
|
||||
+4
-4
@@ -18,6 +18,7 @@ import { FormHelperText, TextField } from '@material-ui/core';
|
||||
import { act, render } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import React from 'react';
|
||||
import { asInputRef } from '../helpers';
|
||||
import { PreparePullRequestForm } from './PreparePullRequestForm';
|
||||
|
||||
describe('<PreparePullRequestForm />', () => {
|
||||
@@ -29,7 +30,7 @@ describe('<PreparePullRequestForm />', () => {
|
||||
defaultValues={{ main: 'default' }}
|
||||
render={({ register }) => (
|
||||
<>
|
||||
<TextField name="main" inputRef={register()} />
|
||||
<TextField {...asInputRef(register('main'))} />
|
||||
<button type="submit">Submit</button>{' '}
|
||||
</>
|
||||
)}
|
||||
@@ -54,10 +55,9 @@ describe('<PreparePullRequestForm />', () => {
|
||||
render={({ register }) => (
|
||||
<>
|
||||
<TextField
|
||||
{...asInputRef(register('main'))}
|
||||
id="main"
|
||||
name="main"
|
||||
label="Main Field"
|
||||
inputRef={register()}
|
||||
/>
|
||||
<button type="submit">Submit</button>
|
||||
</>
|
||||
@@ -85,9 +85,9 @@ describe('<PreparePullRequestForm />', () => {
|
||||
render={({ errors, register }) => (
|
||||
<>
|
||||
<TextField
|
||||
{...asInputRef(register('main', { required: true }))}
|
||||
name="main"
|
||||
required
|
||||
inputRef={register({ required: true })}
|
||||
/>
|
||||
{errors.main && (
|
||||
<FormHelperText error>
|
||||
|
||||
-5
@@ -55,10 +55,6 @@ export const PreparePullRequestForm = <
|
||||
onSubmit,
|
||||
render,
|
||||
}: Props<TFieldValues>) => {
|
||||
<<<<<<< HEAD
|
||||
const { handleSubmit, watch, control, register, errors } =
|
||||
useForm<TFieldValues>({ mode: 'onTouched', defaultValues });
|
||||
=======
|
||||
const {
|
||||
handleSubmit,
|
||||
watch,
|
||||
@@ -66,7 +62,6 @@ export const PreparePullRequestForm = <
|
||||
register,
|
||||
formState: { errors },
|
||||
} = useForm<TFieldValues>({ mode: 'onTouched', defaultValues });
|
||||
>>>>>>> chore: fixing up some migrations
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
|
||||
+13
-14
@@ -20,6 +20,7 @@ import { act, render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import React from 'react';
|
||||
import { AnalyzeResult, catalogImportApiRef } from '../../api';
|
||||
import { asInputRef } from '../helpers';
|
||||
import {
|
||||
generateEntities,
|
||||
StepPrepareCreatePullRequest,
|
||||
@@ -91,10 +92,10 @@ describe('<StepPrepareCreatePullRequest />', () => {
|
||||
renderFormFields={({ register }) => {
|
||||
return (
|
||||
<>
|
||||
<TextField name="title" inputRef={register()} />
|
||||
<TextField name="body" inputRef={register()} />
|
||||
<TextField name="componentName" inputRef={register()} />
|
||||
<TextField name="owner" inputRef={register()} />
|
||||
<TextField {...asInputRef(register('title'))} />
|
||||
<TextField {...asInputRef(register('body'))} />
|
||||
<TextField {...asInputRef(register('componentName'))} />
|
||||
<TextField {...asInputRef(register('owner'))} />
|
||||
</>
|
||||
);
|
||||
}}
|
||||
@@ -132,19 +133,17 @@ describe('<StepPrepareCreatePullRequest />', () => {
|
||||
renderFormFields={({ register }) => {
|
||||
return (
|
||||
<>
|
||||
<TextField name="title" inputRef={register()} />
|
||||
<TextField name="body" inputRef={register()} />
|
||||
<TextField {...asInputRef(register('title'))} />
|
||||
<TextField {...asInputRef(register('body'))} />
|
||||
<TextField
|
||||
{...asInputRef(register('componentName'))}
|
||||
id="name"
|
||||
label="name"
|
||||
name="componentName"
|
||||
inputRef={register()}
|
||||
/>
|
||||
<TextField
|
||||
{...asInputRef(register('owner'))}
|
||||
id="owner"
|
||||
label="owner"
|
||||
name="owner"
|
||||
inputRef={register()}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
@@ -222,10 +221,10 @@ spec:
|
||||
renderFormFields={({ register }) => {
|
||||
return (
|
||||
<>
|
||||
<TextField name="title" inputRef={register()} />
|
||||
<TextField name="body" inputRef={register()} />
|
||||
<TextField name="componentName" inputRef={register()} />
|
||||
<TextField name="owner" inputRef={register()} />
|
||||
<TextField {...asInputRef(register('title'))} />
|
||||
<TextField {...asInputRef(register('body'))} />
|
||||
<TextField {...asInputRef(register('componentName'))} />
|
||||
<TextField {...asInputRef(register('owner'))} />
|
||||
</>
|
||||
);
|
||||
}}
|
||||
|
||||
+6
-5
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import {
|
||||
catalogApiRef,
|
||||
formatEntityRefTitle,
|
||||
@@ -22,7 +23,7 @@ import {
|
||||
import { Box, FormHelperText, Grid, Typography } from '@material-ui/core';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { UnpackNestedValue, UseFormMethods } from 'react-hook-form';
|
||||
import { FieldErrors, UnpackNestedValue, UseFormReturn } from 'react-hook-form';
|
||||
import { useAsync } from 'react-use';
|
||||
import YAML from 'yaml';
|
||||
import { AnalyzeResult, catalogImportApiRef } from '../../api';
|
||||
@@ -32,7 +33,6 @@ import { PrepareResult } from '../useImportState';
|
||||
import { PreparePullRequestForm } from './PreparePullRequestForm';
|
||||
import { PreviewCatalogInfoComponent } from './PreviewCatalogInfoComponent';
|
||||
import { PreviewPullRequestComponent } from './PreviewPullRequestComponent';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
previewCard: {
|
||||
@@ -63,7 +63,8 @@ type Props = {
|
||||
defaultBody: string;
|
||||
|
||||
renderFormFields: (
|
||||
props: Pick<UseFormMethods<FormData>, 'errors' | 'register' | 'control'> & {
|
||||
props: Pick<UseFormReturn<FormData>, 'register' | 'setValue'> & {
|
||||
errors: FieldErrors<FormData>;
|
||||
values: UnpackNestedValue<FormData>;
|
||||
groups: string[];
|
||||
groupsLoading: boolean;
|
||||
@@ -192,13 +193,13 @@ export const StepPrepareCreatePullRequest = ({
|
||||
analyzeResult.generatedEntities[0]?.metadata?.name || '',
|
||||
useCodeowners: false,
|
||||
}}
|
||||
render={({ values, errors, control, register }) => (
|
||||
render={({ values, errors, register, setValue }) => (
|
||||
<>
|
||||
{renderFormFields({
|
||||
values,
|
||||
errors,
|
||||
register,
|
||||
control,
|
||||
setValue,
|
||||
groups: groups ?? [],
|
||||
groupsLoading,
|
||||
})}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2021 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 { UseFormRegisterReturn } from 'react-hook-form';
|
||||
|
||||
/**
|
||||
* A helper that converts the result of a render('name', opts) to make it compatible with material-ui.
|
||||
*
|
||||
* See also https://github.com/react-hook-form/react-hook-form/issues/4629#issuecomment-815840872
|
||||
* TODO: remove when updating to material-ui v5 (https://github.com/mui-org/material-ui/pull/23174)
|
||||
*
|
||||
* @param renderResult - the result of a render('name', opts)
|
||||
*/
|
||||
export function asInputRef(renderResult: UseFormRegisterReturn) {
|
||||
const { ref, ...rest } = renderResult;
|
||||
return {
|
||||
inputRef: ref,
|
||||
...rest,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user