0

merge TextField and TextFieldAdmin components

This commit is contained in:
dorj222 2023-01-23 15:34:59 +01:00
parent 90515f37b5
commit dd9f41fef6
3 changed files with 84 additions and 204 deletions

View File

@ -1,6 +1,6 @@
import React, { FC } from 'react';
import React, { FC, useEffect } from 'react';
import classNames from 'classnames';
import { Input, InputNumber } from 'antd';
import { Input, Form, InputNumber } from 'antd';
import { FieldUpdaterFunc } from '../../types/config-section';
// import InfoTip from '../info-tip';
import { StatusState } from '../../utils/input-statuses';
@ -61,6 +61,13 @@ export const TextField: FC<TextFieldProps> = ({
}
};
const [form] = Form.useForm();
useEffect(() => {
// console.log('value: ', value);
form.setFieldsValue({ adminPassword: value });
}, [value]);
// if you blur a required field with an empty value, restore its original value in state (parent's state), if an onChange from parent is available.
const handleBlur = (e: any) => {
const val = e.target.value;
@ -128,25 +135,76 @@ export const TextField: FC<TextFieldProps> = ({
</div>
) : null}
<div className="input-side">
<div className="input-group">
<Field
id={fieldId}
className={`field ${className} ${fieldId}`}
{...fieldProps}
{...(type !== TEXTFIELD_TYPE_NUMBER && { allowClear: true })}
placeholder={placeholder}
maxLength={maxLength}
onChange={handleChange}
onBlur={handleBlur}
onPressEnter={handlePressEnter}
disabled={disabled}
value={value as number | (readonly string[] & number)}
/>
{fieldName !== 'adminPassword' ? (
<div className="input-side">
<div className="input-group">
<Field
id={fieldId}
className={`field ${className} ${fieldId}`}
{...fieldProps}
{...(type !== TEXTFIELD_TYPE_NUMBER && { allowClear: true })}
placeholder={placeholder}
maxLength={maxLength}
onChange={handleChange}
onBlur={handleBlur}
onPressEnter={handlePressEnter}
disabled={disabled}
value={value as number | (readonly string[] & number)}
/>
</div>
<FormStatusIndicator status={status} />
<p className="field-tip">{tip}</p>
</div>
<FormStatusIndicator status={status} />
<p className="field-tip">{tip}</p>
</div>
) : (
<div className="input-side">
<div className="input-group">
<Form
name="basic"
form={form}
initialValues={{ adminPassword: value }}
style={{ width: '100%' }}
>
<Form.Item
name="adminPassword"
rules={[
{ min: 8, message: '- minimum 8 characters' },
{ max: 192, message: '- maximum 192 characters' },
{
pattern: /^(?=.*[a-z])/,
message: '- at least one lowercase letter',
},
{
pattern: /^(?=.*[A-Z])/,
message: '- at least one uppercase letter',
},
{
pattern: /\d/,
message: '- at least one digit',
},
{
pattern: /^(?=.*?[#?!@$%^&*-])/,
message: '- at least one special character: !@#$%^&*',
},
]}
>
<Input.Password
id={fieldId}
className={`field ${className} ${fieldId}`}
{...(type !== TEXTFIELD_TYPE_NUMBER && { allowClear: true })}
onChange={handleChange}
onBlur={handleBlur}
placeholder={placeholder}
onPressEnter={handlePressEnter}
disabled={disabled}
value={value as number | (readonly string[] & number)}
/>
</Form.Item>
<FormStatusIndicator status={status} />
<p className="field-tip">{tip}</p>
</Form>
</div>
</div>
)}
</div>
);
};

View File

@ -1,168 +0,0 @@
import React, { FC, useEffect } from 'react';
import classNames from 'classnames';
import { Input, Form } from 'antd';
import { FieldUpdaterFunc } from '../../types/config-section';
// import InfoTip from '../info-tip';
import { StatusState } from '../../utils/input-statuses';
// import { FormStatusIndicator } from './FormStatusIndicator';
export const TEXTFIELD_TYPE_TEXT = 'default';
export const TEXTFIELD_TYPE_PASSWORD = 'password'; // Input.Password
export const TEXTFIELD_TYPE_NUMBER = 'numeric'; // InputNumber
export const TEXTFIELD_TYPE_TEXTAREA = 'textarea'; // Input.TextArea
export const TEXTFIELD_TYPE_URL = 'url';
export type TextFieldAdminProps = {
fieldName: string;
onSubmit?: () => void;
onPressEnter?: () => void;
className?: string;
disabled?: boolean;
label?: string;
placeholder?: string;
required?: boolean;
status?: StatusState;
tip?: string;
type?: string;
useTrim?: boolean;
useTrimLead?: boolean;
value?: string | number;
onBlur?: FieldUpdaterFunc;
onChange?: FieldUpdaterFunc;
};
export const TextFieldAdmin: FC<TextFieldAdminProps> = ({
className,
disabled,
fieldName,
label,
onBlur,
onChange,
onPressEnter,
placeholder,
required,
status,
type,
useTrim,
value,
}) => {
const handleChange = (e: any) => {
// if an extra onChange handler was sent in as a prop, let's run that too.
if (onChange) {
const val = type === TEXTFIELD_TYPE_NUMBER ? e : e.target.value;
onChange({ fieldName, value: useTrim ? val.trim() : val });
}
};
const [form] = Form.useForm();
// const formRef = useRef(null);
useEffect(() => {
// console.log('value: ', value);
form.setFieldsValue({ adminPassword: value });
}, [value]);
// if you blur a required field with an empty value, restore its original value in state (parent's state), if an onChange from parent is available.
const handleBlur = (e: any) => {
const val = e.target.value;
if (onBlur) {
onBlur({ value: val });
}
};
const handlePressEnter = () => {
if (onPressEnter) {
onPressEnter();
}
};
const onFinish = (values: Store) => {
console.log('Received values of form: ', values);
};
// display the appropriate Ant text field
// let Field = Input as typeof Input.Password;
// let fieldProps = {};
// Field = Input.Password;
// fieldProps = {
// visibilityToggle: true,
// };
const fieldId = `field-${fieldName}`;
const { type: statusType } = status || {};
const containerClass = classNames({
'formfield-container': true,
'textfield-container': true,
[`type-${type}`]: true,
required,
[`status-${statusType}`]: status,
});
return (
<div className={containerClass}>
<Form name="basic" form={form} initialValues={{ adminPassword: value }} onFinish={onFinish}>
<Form.Item
label={label}
name="adminPassword"
rules={[
{ min: 8, message: '- minimum 8 characters' },
{ max: 192, message: '- maximum 192 characters' },
{
pattern: /^(?=.*[a-z])/,
message: '- at least one lowercase letter',
},
{
pattern: /^(?=.*[A-Z])/,
message: '- at least one uppercase letter',
},
{
pattern: /\d/,
message: '- at least one digit',
},
{
pattern: /^(?=.*?[#?!@$%^&*-])/,
message: '- at least one special character: !@#$%^&*',
},
]}
>
<Input.Password
id={fieldId}
className={`field ${className} ${fieldId}`}
{...(type !== TEXTFIELD_TYPE_NUMBER && { allowClear: true })}
onChange={handleChange}
onBlur={handleBlur}
placeholder={placeholder}
onPressEnter={handlePressEnter}
disabled={disabled}
value={value as number | (readonly string[] & number)}
/>
</Form.Item>
</Form>
</div>
);
};
export default TextFieldAdmin;
TextFieldAdmin.defaultProps = {
className: '',
disabled: false,
placeholder: '',
required: false,
status: null,
tip: '',
type: TEXTFIELD_TYPE_TEXT,
value: '',
useTrim: false,
useTrimLead: false,
onSubmit: () => {},
onBlur: () => {},
onChange: () => {},
onPressEnter: () => {},
};

View File

@ -13,7 +13,6 @@ import {
import { ServerStatusContext } from '../../utils/server-status-context';
import { FormStatusIndicator } from './FormStatusIndicator';
import { TextField, TextFieldProps } from './TextField';
import { TextFieldAdmin } from './TextFieldAdmin';
export const TEXTFIELD_TYPE_TEXT = 'default';
export const TEXTFIELD_TYPE_PASSWORD = 'password'; // Input.Password
@ -122,21 +121,12 @@ export const TextFieldWithSubmit: FC<TextFieldWithSubmitProps> = ({
return (
<div className={textfieldContainerClass}>
<div className="textfield-component">
{textFieldProps.fieldName !== 'adminPassword' ? (
<TextField
{...textFieldProps}
onSubmit={null}
onBlur={handleBlur}
onChange={handleChange}
/>
) : (
<TextFieldAdmin
{...textFieldProps}
onSubmit={null}
onBlur={handleBlur}
onChange={handleChange}
/>
)}
<TextField
{...textFieldProps}
onSubmit={null}
onBlur={handleBlur}
onChange={handleChange}
/>
</div>
<div className="formfield-container lower-container">
<p className="label-spacer" />