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