mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2024-12-18 13:01:51 +03:00
rewrite form
This commit is contained in:
parent
77420d8c96
commit
8e2dea267c
7 changed files with 76 additions and 63 deletions
|
@ -44,7 +44,7 @@ const Check = ({ onSubmit }: Props) => {
|
|||
type="text"
|
||||
className="form-control"
|
||||
placeholder={t('form_enter_host') ?? ''}
|
||||
{...register('name', { required: true })}
|
||||
{...register('name', { required: t('form_error_required') })}
|
||||
/>
|
||||
<span className="input-group-append">
|
||||
<button
|
||||
|
|
|
@ -1,50 +1,71 @@
|
|||
import React from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
|
||||
import { Field, reduxForm } from 'redux-form';
|
||||
import { Trans, withTranslation } from 'react-i18next';
|
||||
import flow from 'lodash/flow';
|
||||
import { validateAnswer, validateDomain } from '../../../helpers/validators';
|
||||
|
||||
import { renderInputField } from '../../../helpers/form';
|
||||
import { validateAnswer, validateDomain, validateRequiredValue } from '../../../helpers/validators';
|
||||
import { FORM_NAME } from '../../../helpers/constants';
|
||||
|
||||
interface FormProps {
|
||||
pristine: boolean;
|
||||
handleSubmit: (...args: unknown[]) => string;
|
||||
reset: (...args: unknown[]) => string;
|
||||
toggleRewritesModal: (...args: unknown[]) => unknown;
|
||||
submitting: boolean;
|
||||
processingAdd: boolean;
|
||||
t: (...args: unknown[]) => string;
|
||||
initialValues?: object;
|
||||
interface FormValues {
|
||||
domain: string;
|
||||
answer: string;
|
||||
}
|
||||
|
||||
const Form = (props: FormProps) => {
|
||||
const { t, handleSubmit, reset, pristine, submitting, toggleRewritesModal, processingAdd } = props;
|
||||
type Props = {
|
||||
processingAdd: boolean;
|
||||
currentRewrite?: { answer: string, domain: string; };
|
||||
toggleRewritesModal: () => void;
|
||||
onSubmit?: (data: FormValues) => Promise<void> | void;
|
||||
}
|
||||
|
||||
const Form = ({ processingAdd, currentRewrite, toggleRewritesModal, onSubmit }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
reset,
|
||||
formState: { isDirty, isSubmitting, errors },
|
||||
} = useForm<FormValues>({
|
||||
mode: 'onChange',
|
||||
defaultValues: {
|
||||
domain: currentRewrite?.domain || '',
|
||||
answer: currentRewrite?.answer || '',
|
||||
},
|
||||
});
|
||||
|
||||
const handleFormSubmit = async (data: FormValues) => {
|
||||
if (onSubmit) {
|
||||
await onSubmit(data);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<form onSubmit={handleSubmit(handleFormSubmit)}>
|
||||
<div className="modal-body">
|
||||
<div className="form__desc form__desc--top">
|
||||
<Trans>domain_desc</Trans>
|
||||
</div>
|
||||
<div className="form__group">
|
||||
<Field
|
||||
<input
|
||||
id="domain"
|
||||
name="domain"
|
||||
component={renderInputField}
|
||||
type="text"
|
||||
className="form-control"
|
||||
placeholder={t('form_domain')}
|
||||
validate={[validateRequiredValue, validateDomain]}
|
||||
{...register('domain', {
|
||||
validate: validateDomain,
|
||||
required: t('form_error_required'),
|
||||
})}
|
||||
/>
|
||||
{errors.domain && (
|
||||
<div className="form__message form__message--error">
|
||||
{errors.domain.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Trans>examples_title</Trans>:
|
||||
<ol className="leading-loose">
|
||||
<li>
|
||||
<code>example.org</code> – <Trans>example_rewrite_domain</Trans>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<code>*.example.org</code> –
|
||||
<span>
|
||||
|
@ -53,15 +74,21 @@ const Form = (props: FormProps) => {
|
|||
</li>
|
||||
</ol>
|
||||
<div className="form__group">
|
||||
<Field
|
||||
<input
|
||||
id="answer"
|
||||
name="answer"
|
||||
component={renderInputField}
|
||||
type="text"
|
||||
className="form-control"
|
||||
placeholder={t('form_answer')}
|
||||
validate={[validateRequiredValue, validateAnswer]}
|
||||
placeholder={t('form_answer') ?? ''}
|
||||
{...register('answer', {
|
||||
validate: validateAnswer,
|
||||
required: t('form_error_required'),
|
||||
})}
|
||||
/>
|
||||
{errors.answer && (
|
||||
<div className="form__message form__message--error">
|
||||
{errors.answer.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -78,18 +105,20 @@ const Form = (props: FormProps) => {
|
|||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary btn-standard"
|
||||
disabled={submitting || processingAdd}
|
||||
disabled={isSubmitting || processingAdd}
|
||||
onClick={() => {
|
||||
reset();
|
||||
toggleRewritesModal();
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<Trans>cancel_btn</Trans>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-success btn-standard"
|
||||
disabled={submitting || pristine || processingAdd}>
|
||||
disabled={isSubmitting || !isDirty || processingAdd}
|
||||
>
|
||||
<Trans>save_btn</Trans>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -98,10 +127,4 @@ const Form = (props: FormProps) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default flow([
|
||||
withTranslation(),
|
||||
reduxForm({
|
||||
form: FORM_NAME.REWRITES,
|
||||
enableReinitialize: true,
|
||||
}),
|
||||
])(Form);
|
||||
export default Form;
|
||||
|
|
|
@ -14,7 +14,7 @@ interface ModalProps {
|
|||
processingAdd: boolean;
|
||||
processingDelete: boolean;
|
||||
modalType: string;
|
||||
currentRewrite?: object;
|
||||
currentRewrite?: { answer: string, domain: string; };
|
||||
}
|
||||
|
||||
const Modal = (props: ModalProps) => {
|
||||
|
@ -23,7 +23,6 @@ const Modal = (props: ModalProps) => {
|
|||
handleSubmit,
|
||||
toggleRewritesModal,
|
||||
processingAdd,
|
||||
processingDelete,
|
||||
modalType,
|
||||
currentRewrite,
|
||||
} = props;
|
||||
|
@ -50,11 +49,10 @@ const Modal = (props: ModalProps) => {
|
|||
</div>
|
||||
|
||||
<Form
|
||||
initialValues={{ ...currentRewrite }}
|
||||
onSubmit={handleSubmit}
|
||||
toggleRewritesModal={toggleRewritesModal}
|
||||
processingAdd={processingAdd}
|
||||
processingDelete={processingDelete}
|
||||
currentRewrite={currentRewrite}
|
||||
/>
|
||||
</div>
|
||||
</ReactModal>
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
}
|
||||
|
||||
.form__message {
|
||||
margin-top: 4px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
|
|
|
@ -292,7 +292,7 @@ export const validateIsSafePort = (value: any) => {
|
|||
*/
|
||||
export const validateDomain = (value: any) => {
|
||||
if (value && !R_HOST.test(value)) {
|
||||
return 'form_error_domain_format';
|
||||
return i18next.t('form_error_domain_format');
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
@ -303,7 +303,7 @@ export const validateDomain = (value: any) => {
|
|||
*/
|
||||
export const validateAnswer = (value: any) => {
|
||||
if (value && !R_IPV4.test(value) && !R_IPV6.test(value) && !R_HOST.test(value)) {
|
||||
return 'form_error_answer_format';
|
||||
return i18next.t('form_error_answer_format');
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
|
|
@ -55,17 +55,14 @@ const Auth = (props: Props) => {
|
|||
<Trans>install_auth_username</Trans>
|
||||
</label>
|
||||
<input
|
||||
{...register('username', { required: {
|
||||
value: true,
|
||||
message: i18n.t('form_error_required'),
|
||||
}})}
|
||||
{...register('username', { required: t('form_error_required') })}
|
||||
type="text"
|
||||
className={cn('form-control', { 'is-invalid': errors.username })}
|
||||
placeholder={t('install_auth_username_enter')}
|
||||
autoComplete="username"
|
||||
/>
|
||||
{errors.username && (
|
||||
<div className="invalid-feedback">
|
||||
<div className="form__message form__message--error">
|
||||
{errors.username.message}
|
||||
</div>
|
||||
)}
|
||||
|
@ -77,10 +74,7 @@ const Auth = (props: Props) => {
|
|||
</label>
|
||||
<input
|
||||
{...register('password', {
|
||||
required: {
|
||||
value: true,
|
||||
message: i18n.t('form_error_required'),
|
||||
},
|
||||
required: t('form_error_required'),
|
||||
validate: validatePasswordLength,
|
||||
})}
|
||||
type="password"
|
||||
|
@ -89,8 +83,8 @@ const Auth = (props: Props) => {
|
|||
autoComplete="new-password"
|
||||
/>
|
||||
{errors.password && (
|
||||
<div className="invalid-feedback">
|
||||
{errors.password.message || i18n.t('form_error_password_length')}
|
||||
<div className="form__message form__message--error">
|
||||
{errors.password.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@ -101,10 +95,7 @@ const Auth = (props: Props) => {
|
|||
</label>
|
||||
<input
|
||||
{...register('confirm_password', {
|
||||
required: {
|
||||
value: true,
|
||||
message: i18n.t('form_error_required'),
|
||||
},
|
||||
required: t('form_error_required'),
|
||||
validate: validateConfirmPassword,
|
||||
})}
|
||||
type="password"
|
||||
|
|
|
@ -276,7 +276,7 @@ const Settings: React.FC<Props> = ({
|
|||
)}
|
||||
/>
|
||||
{errors.web?.port && (
|
||||
<div className="text-danger">
|
||||
<div className="form__message form__message--error">
|
||||
{errors.web.port.message}
|
||||
</div>
|
||||
)}
|
||||
|
@ -376,7 +376,7 @@ const Settings: React.FC<Props> = ({
|
|||
)}
|
||||
/>
|
||||
{errors.dns?.port.message && (
|
||||
<div className="text-danger">
|
||||
<div className="form__message form__message--error">
|
||||
{t(errors.dns.port.message)}
|
||||
</div>
|
||||
)}
|
||||
|
|
Loading…
Reference in a new issue