mirror of
https://github.com/owncast/owncast.git
synced 2025-11-02 11:56:57 +08:00
merge TextField and TextFieldAdmin components
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC, useEffect } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Input, InputNumber } from 'antd';
|
import { Input, Form, InputNumber } from 'antd';
|
||||||
import { FieldUpdaterFunc } from '../../types/config-section';
|
import { FieldUpdaterFunc } from '../../types/config-section';
|
||||||
// import InfoTip from '../info-tip';
|
// import InfoTip from '../info-tip';
|
||||||
import { StatusState } from '../../utils/input-statuses';
|
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.
|
// 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 handleBlur = (e: any) => {
|
||||||
const val = e.target.value;
|
const val = e.target.value;
|
||||||
@ -128,25 +135,76 @@ export const TextField: FC<TextFieldProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<div className="input-side">
|
{fieldName !== 'adminPassword' ? (
|
||||||
<div className="input-group">
|
<div className="input-side">
|
||||||
<Field
|
<div className="input-group">
|
||||||
id={fieldId}
|
<Field
|
||||||
className={`field ${className} ${fieldId}`}
|
id={fieldId}
|
||||||
{...fieldProps}
|
className={`field ${className} ${fieldId}`}
|
||||||
{...(type !== TEXTFIELD_TYPE_NUMBER && { allowClear: true })}
|
{...fieldProps}
|
||||||
placeholder={placeholder}
|
{...(type !== TEXTFIELD_TYPE_NUMBER && { allowClear: true })}
|
||||||
maxLength={maxLength}
|
placeholder={placeholder}
|
||||||
onChange={handleChange}
|
maxLength={maxLength}
|
||||||
onBlur={handleBlur}
|
onChange={handleChange}
|
||||||
onPressEnter={handlePressEnter}
|
onBlur={handleBlur}
|
||||||
disabled={disabled}
|
onPressEnter={handlePressEnter}
|
||||||
value={value as number | (readonly string[] & number)}
|
disabled={disabled}
|
||||||
/>
|
value={value as number | (readonly string[] & number)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<FormStatusIndicator status={status} />
|
||||||
|
<p className="field-tip">{tip}</p>
|
||||||
</div>
|
</div>
|
||||||
<FormStatusIndicator status={status} />
|
) : (
|
||||||
<p className="field-tip">{tip}</p>
|
<div className="input-side">
|
||||||
</div>
|
<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>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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: () => {},
|
|
||||||
};
|
|
||||||
@ -13,7 +13,6 @@ import {
|
|||||||
import { ServerStatusContext } from '../../utils/server-status-context';
|
import { ServerStatusContext } from '../../utils/server-status-context';
|
||||||
import { FormStatusIndicator } from './FormStatusIndicator';
|
import { FormStatusIndicator } from './FormStatusIndicator';
|
||||||
import { TextField, TextFieldProps } from './TextField';
|
import { TextField, TextFieldProps } from './TextField';
|
||||||
import { TextFieldAdmin } from './TextFieldAdmin';
|
|
||||||
|
|
||||||
export const TEXTFIELD_TYPE_TEXT = 'default';
|
export const TEXTFIELD_TYPE_TEXT = 'default';
|
||||||
export const TEXTFIELD_TYPE_PASSWORD = 'password'; // Input.Password
|
export const TEXTFIELD_TYPE_PASSWORD = 'password'; // Input.Password
|
||||||
@ -122,21 +121,12 @@ export const TextFieldWithSubmit: FC<TextFieldWithSubmitProps> = ({
|
|||||||
return (
|
return (
|
||||||
<div className={textfieldContainerClass}>
|
<div className={textfieldContainerClass}>
|
||||||
<div className="textfield-component">
|
<div className="textfield-component">
|
||||||
{textFieldProps.fieldName !== 'adminPassword' ? (
|
<TextField
|
||||||
<TextField
|
{...textFieldProps}
|
||||||
{...textFieldProps}
|
onSubmit={null}
|
||||||
onSubmit={null}
|
onBlur={handleBlur}
|
||||||
onBlur={handleBlur}
|
onChange={handleChange}
|
||||||
onChange={handleChange}
|
/>
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<TextFieldAdmin
|
|
||||||
{...textFieldProps}
|
|
||||||
onSubmit={null}
|
|
||||||
onBlur={handleBlur}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="formfield-container lower-container">
|
<div className="formfield-container lower-container">
|
||||||
<p className="label-spacer" />
|
<p className="label-spacer" />
|
||||||
|
|||||||
Reference in New Issue
Block a user