mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-27 21:54:27 +01:00
(ui) refactor form components to use props inheritance
This commit is contained in:
parent
8fee9c6bb8
commit
f7dd75dca1
@ -47,7 +47,7 @@ export const ProviderForm: React.FC<ProviderFormProps> = ({ action, provider, on
|
|||||||
return (
|
return (
|
||||||
<form className="provider-form" onSubmit={handleSubmit(onSubmit)}>
|
<form className="provider-form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
<RHFInput id="name" register={register} readOnly={action === 'update'} rules={{ required: true }} label={t('app.shared.authentication.name')} />
|
<RHFInput id="name" register={register} readOnly={action === 'update'} rules={{ required: true }} label={t('app.shared.authentication.name')} />
|
||||||
<FabSelect id="providable_type" control={control} options={buildProvidableTypeOptions()} valueDefault={'DatabaseProvider'} />
|
<FabSelect id="providable_type" control={control} options={buildProvidableTypeOptions()} label={t('app.shared.authentication.authentication_type')} rules={{ required: true }} />
|
||||||
<input type={'submit'} />
|
<input type={'submit'} />
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
import React, { SelectHTMLAttributes } from 'react';
|
import React, { SelectHTMLAttributes } from 'react';
|
||||||
import Select from 'react-select';
|
import Select from 'react-select';
|
||||||
import { Controller, Path } from 'react-hook-form';
|
import { Controller, Path } from 'react-hook-form';
|
||||||
import { Control } from 'react-hook-form/dist/types/form';
|
|
||||||
import { FieldValues } from 'react-hook-form/dist/types/fields';
|
import { FieldValues } from 'react-hook-form/dist/types/fields';
|
||||||
import { FieldPath } from 'react-hook-form/dist/types/path';
|
import { FieldPath } from 'react-hook-form/dist/types/path';
|
||||||
import { FieldPathValue, UnpackNestedValue } from 'react-hook-form/dist/types';
|
import { FieldPathValue, UnpackNestedValue } from 'react-hook-form/dist/types';
|
||||||
|
import { FormControlledComponent } from '../../models/form-component';
|
||||||
|
|
||||||
interface FabSelectProps<TFieldValues, TContext extends object, TOptionValue> extends SelectHTMLAttributes<HTMLSelectElement> {
|
interface FabSelectProps<TFieldValues, TContext extends object, TOptionValue> extends SelectHTMLAttributes<HTMLSelectElement>, FormControlledComponent<TFieldValues, TContext> {
|
||||||
id: string,
|
id: string,
|
||||||
label?: string,
|
label?: string,
|
||||||
className?: string,
|
|
||||||
control: Control<TFieldValues, TContext>,
|
|
||||||
placeholder?: string,
|
|
||||||
options: Array<selectOption<TOptionValue>>,
|
options: Array<selectOption<TOptionValue>>,
|
||||||
valuesDefault?: Array<TOptionValue>,
|
valuesDefault?: Array<TOptionValue>,
|
||||||
}
|
}
|
||||||
@ -26,9 +23,15 @@ type selectOption<TOptionValue> = { value: TOptionValue, label: string };
|
|||||||
* This component is a wrapper around react-select to use with react-hook-form.
|
* This component is a wrapper around react-select to use with react-hook-form.
|
||||||
* It is a multi-select component.
|
* It is a multi-select component.
|
||||||
*/
|
*/
|
||||||
export const FabMultiSelect = <TFieldValues extends FieldValues, TContext extends object, TOptionValue>({ id, label, className, control, placeholder, options, valuesDefault }: FabSelectProps<TFieldValues, TContext, TOptionValue>) => {
|
export const FabMultiSelect = <TFieldValues extends FieldValues, TContext extends object, TOptionValue>({ id, label, className, control, placeholder, options, valuesDefault, error, rules, disabled }: FabSelectProps<TFieldValues, TContext, TOptionValue>) => {
|
||||||
|
const classNames = `
|
||||||
|
fab-multi-select ${className || ''}
|
||||||
|
${error && error[id] ? 'is-incorrect' : ''}
|
||||||
|
${rules && rules.required ? 'is-required' : ''}
|
||||||
|
${disabled ? 'is-disabled' : ''}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<label className={`fab-multi-select ${className || ''}`}>
|
<label className={classNames}>
|
||||||
{label && <div className="fab-multi-select-header">
|
{label && <div className="fab-multi-select-header">
|
||||||
<p>{label}</p>
|
<p>{label}</p>
|
||||||
</div>}
|
</div>}
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
import React, { SelectHTMLAttributes } from 'react';
|
import React, { SelectHTMLAttributes } from 'react';
|
||||||
import Select from 'react-select';
|
import Select from 'react-select';
|
||||||
import { Controller, Path } from 'react-hook-form';
|
import { Controller, Path } from 'react-hook-form';
|
||||||
import { Control } from 'react-hook-form/dist/types/form';
|
|
||||||
import { FieldValues } from 'react-hook-form/dist/types/fields';
|
import { FieldValues } from 'react-hook-form/dist/types/fields';
|
||||||
import { FieldPath } from 'react-hook-form/dist/types/path';
|
import { FieldPath } from 'react-hook-form/dist/types/path';
|
||||||
import { FieldPathValue, UnpackNestedValue } from 'react-hook-form/dist/types';
|
import { FieldPathValue, UnpackNestedValue } from 'react-hook-form/dist/types';
|
||||||
|
import { FormControlledComponent } from '../../models/form-component';
|
||||||
|
|
||||||
interface FabSelectProps<TFieldValues, TContext extends object, TOptionValue> extends SelectHTMLAttributes<HTMLSelectElement> {
|
interface FabSelectProps<TFieldValues, TContext extends object, TOptionValue> extends SelectHTMLAttributes<HTMLSelectElement>, FormControlledComponent<TFieldValues, TContext> {
|
||||||
id: string,
|
id: string,
|
||||||
label?: string,
|
label?: string,
|
||||||
className?: string,
|
|
||||||
control: Control<TFieldValues, TContext>,
|
|
||||||
placeholder?: string,
|
|
||||||
options: Array<selectOption<TOptionValue>>,
|
options: Array<selectOption<TOptionValue>>,
|
||||||
valueDefault?: TOptionValue,
|
valueDefault?: TOptionValue,
|
||||||
}
|
}
|
||||||
@ -25,9 +22,15 @@ type selectOption<TOptionValue> = { value: TOptionValue, label: string };
|
|||||||
/**
|
/**
|
||||||
* This component is a wrapper for react-select to use with react-hook-form
|
* This component is a wrapper for react-select to use with react-hook-form
|
||||||
*/
|
*/
|
||||||
export const FabSelect = <TFieldValues extends FieldValues, TContext extends object, TOptionValue>({ id, label, className, control, placeholder, options, valueDefault }: FabSelectProps<TFieldValues, TContext, TOptionValue>) => {
|
export const FabSelect = <TFieldValues extends FieldValues, TContext extends object, TOptionValue>({ id, label, className, control, placeholder, options, valueDefault, error, rules, disabled }: FabSelectProps<TFieldValues, TContext, TOptionValue>) => {
|
||||||
|
const classNames = `
|
||||||
|
fab-select ${className || ''}
|
||||||
|
${error && error[id] ? 'is-incorrect' : ''}
|
||||||
|
${rules && rules.required ? 'is-required' : ''}
|
||||||
|
${disabled ? 'is-disabled' : ''}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<label className={`fab-select ${className || ''}`}>
|
<label className={classNames}>
|
||||||
{label && <div className="fab-select-header">
|
{label && <div className="fab-select-header">
|
||||||
<p>{label}</p>
|
<p>{label}</p>
|
||||||
</div>}
|
</div>}
|
||||||
|
@ -1,45 +1,25 @@
|
|||||||
import React, { ReactNode } from 'react';
|
import React, { InputHTMLAttributes, ReactNode } from 'react';
|
||||||
import { FieldErrors, FieldPathValue, UseFormRegister, Validate } from 'react-hook-form';
|
import { FieldPathValue } from 'react-hook-form';
|
||||||
import { FieldValues } from 'react-hook-form/dist/types/fields';
|
import { FieldValues } from 'react-hook-form/dist/types/fields';
|
||||||
import { FieldPath } from 'react-hook-form/dist/types/path';
|
import { FieldPath } from 'react-hook-form/dist/types/path';
|
||||||
|
import { FormComponent } from '../../models/form-component';
|
||||||
|
|
||||||
type inputType = string|number|readonly string [];
|
interface RHFInputProps<TFieldValues> extends InputHTMLAttributes<HTMLInputElement>, FormComponent<TFieldValues>{
|
||||||
type ruleTypes<TFieldValues> = {
|
|
||||||
required?: boolean | string,
|
|
||||||
pattern?: RegExp | {value: RegExp, message: string},
|
|
||||||
minLength?: number,
|
|
||||||
maxLength?: number,
|
|
||||||
min?: number,
|
|
||||||
max?: number,
|
|
||||||
validate?: Validate<TFieldValues>;
|
|
||||||
};
|
|
||||||
|
|
||||||
interface RHFInputProps<TFieldValues> {
|
|
||||||
id: string,
|
id: string,
|
||||||
register: UseFormRegister<TFieldValues>,
|
|
||||||
label?: string,
|
label?: string,
|
||||||
tooltip?: string,
|
tooltip?: string,
|
||||||
defaultValue?: inputType,
|
|
||||||
icon?: ReactNode,
|
icon?: ReactNode,
|
||||||
addOn?: ReactNode,
|
addOn?: ReactNode,
|
||||||
addOnClassName?: string,
|
addOnClassName?: string,
|
||||||
classes?: string,
|
|
||||||
rules?: ruleTypes<TFieldValues>,
|
|
||||||
readOnly?: boolean,
|
|
||||||
disabled?: boolean,
|
|
||||||
placeholder?: string,
|
|
||||||
error?: FieldErrors,
|
|
||||||
type?: 'text' | 'date' | 'password' | 'url' | 'time' | 'tel' | 'search' | 'number' | 'month' | 'email' | 'datetime-local' | 'week',
|
|
||||||
step?: number | 'any'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component is a template for an input component to use within React Hook Form
|
* This component is a template for an input component to use within React Hook Form
|
||||||
*/
|
*/
|
||||||
export const RHFInput = <TFieldValues extends FieldValues>({ id, register, label, tooltip, defaultValue, icon, classes, rules, readOnly, disabled, type, addOn, addOnClassName, placeholder, error, step }: RHFInputProps<TFieldValues>) => {
|
export const RHFInput = <TFieldValues extends FieldValues>({ id, register, label, tooltip, defaultValue, icon, className, rules, readOnly, disabled, type, addOn, addOnClassName, placeholder, error, step }: RHFInputProps<TFieldValues>) => {
|
||||||
// Compose classnames from props
|
// Compose classnames from props
|
||||||
const classNames = `
|
const classNames = `
|
||||||
rhf-input ${classes || ''}
|
rhf-input ${className || ''}
|
||||||
${error && error[id] ? 'is-incorrect' : ''}
|
${error && error[id] ? 'is-incorrect' : ''}
|
||||||
${rules && rules.required ? 'is-required' : ''}
|
${rules && rules.required ? 'is-required' : ''}
|
||||||
${readOnly ? 'is-readOnly' : ''}
|
${readOnly ? 'is-readOnly' : ''}
|
||||||
|
24
app/frontend/src/javascript/models/form-component.ts
Normal file
24
app/frontend/src/javascript/models/form-component.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { FieldErrors, UseFormRegister, Validate } from 'react-hook-form';
|
||||||
|
import { Control } from 'react-hook-form/dist/types/form';
|
||||||
|
|
||||||
|
export type ruleTypes<TFieldValues> = {
|
||||||
|
required?: boolean | string,
|
||||||
|
pattern?: RegExp | {value: RegExp, message: string},
|
||||||
|
minLength?: number,
|
||||||
|
maxLength?: number,
|
||||||
|
min?: number,
|
||||||
|
max?: number,
|
||||||
|
validate?: Validate<TFieldValues>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface FormComponent<TFieldValues> {
|
||||||
|
register: UseFormRegister<TFieldValues>,
|
||||||
|
error?: FieldErrors,
|
||||||
|
rules?: ruleTypes<TFieldValues>,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FormControlledComponent<TFieldValues, TContext extends object> {
|
||||||
|
control: Control<TFieldValues, TContext>,
|
||||||
|
error?: FieldErrors,
|
||||||
|
rules?: ruleTypes<TFieldValues>,
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user