use common checkbox component
This commit is contained in:
14
client/package-lock.json
generated
vendored
14
client/package-lock.json
generated
vendored
@@ -11,6 +11,7 @@
|
|||||||
"@nivo/line": "^0.64.0",
|
"@nivo/line": "^0.64.0",
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
"countries-and-timezones": "^3.6.0",
|
"countries-and-timezones": "^3.6.0",
|
||||||
"date-fns": "^1.29.0",
|
"date-fns": "^1.29.0",
|
||||||
"i18next": "^19.6.2",
|
"i18next": "^19.6.2",
|
||||||
@@ -6389,6 +6390,14 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/clsx": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/co": {
|
"node_modules/co": {
|
||||||
"version": "4.6.0",
|
"version": "4.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||||
@@ -24834,6 +24843,11 @@
|
|||||||
"shallow-clone": "^3.0.0"
|
"shallow-clone": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"clsx": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="
|
||||||
|
},
|
||||||
"co": {
|
"co": {
|
||||||
"version": "4.6.0",
|
"version": "4.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||||
|
|||||||
1
client/package.json
vendored
1
client/package.json
vendored
@@ -24,6 +24,7 @@
|
|||||||
"@nivo/line": "^0.64.0",
|
"@nivo/line": "^0.64.0",
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
"countries-and-timezones": "^3.6.0",
|
"countries-and-timezones": "^3.6.0",
|
||||||
"date-fns": "^1.29.0",
|
"date-fns": "^1.29.0",
|
||||||
"i18next": "^19.6.2",
|
"i18next": "^19.6.2",
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useFormContext } from 'react-hook-form';
|
import { Controller, useFormContext } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Checkbox } from '../ui/Controls/Checkbox';
|
||||||
|
|
||||||
const getIconsData = (homepage: string, source: string) => [
|
const getIconsData = (homepage: string, source: string) => [
|
||||||
{
|
{
|
||||||
@@ -49,7 +50,7 @@ type Props = {
|
|||||||
|
|
||||||
export const FiltersList = ({ categories, filters, selectedSources }: Props) => {
|
export const FiltersList = ({ categories, filters, selectedSources }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { register } = useFormContext();
|
const { control } = useFormContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -69,21 +70,19 @@ export const FiltersList = ({ categories, filters, selectedSources }: Props) =>
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={name} className="d-flex align-items-center pb-1">
|
<div key={name} className="d-flex align-items-center pb-1">
|
||||||
<label className="checkbox checkbox--settings">
|
<Controller
|
||||||
<span className="checkbox__marker" />
|
name={id}
|
||||||
<input
|
control={control}
|
||||||
id={id}
|
render={({ field: { value, onChange } }) => (
|
||||||
type="checkbox"
|
<Checkbox
|
||||||
className="checkbox__input"
|
name={id}
|
||||||
disabled={isSelected}
|
title={name}
|
||||||
{...register(id)}
|
value={value}
|
||||||
/>
|
onChange={(value) => onChange(value)}
|
||||||
<span className="checkbox__label">
|
disabled={isSelected}
|
||||||
<span className="checkbox__label-text">
|
/>
|
||||||
<span className="checkbox__label-title">{t(name)}</span>
|
)}
|
||||||
</span>
|
/>
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
{renderIcons(iconsData)}
|
{renderIcons(iconsData)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -107,8 +107,6 @@ class Modal extends Component<ModalProps> {
|
|||||||
|
|
||||||
const title = t(getTitle(modalType, whitelist));
|
const title = t(getTitle(modalType, whitelist));
|
||||||
|
|
||||||
console.log(modalType, initialValues);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactModal
|
<ReactModal
|
||||||
className="Modal__Bootstrap modal-dialog modal-dialog-centered"
|
className="Modal__Bootstrap modal-dialog modal-dialog-centered"
|
||||||
|
|||||||
@@ -1,27 +1,28 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import {
|
import i18next from 'i18next';
|
||||||
validateIp,
|
import { validateIp, validateIpv4, validateIpv6, validateRequiredValue } from '../../../../helpers/validators';
|
||||||
validateIpv4,
|
|
||||||
validateIpv6,
|
|
||||||
validateRequiredValue
|
|
||||||
} from '../../../../helpers/validators';
|
|
||||||
|
|
||||||
import { BLOCKING_MODES, UINT32_RANGE } from '../../../../helpers/constants';
|
import { BLOCKING_MODES, UINT32_RANGE } from '../../../../helpers/constants';
|
||||||
import { removeEmptyLines } from '../../../../helpers/helpers';
|
import { removeEmptyLines } from '../../../../helpers/helpers';
|
||||||
|
import { Checkbox } from '../../../ui/Controls/Checkbox';
|
||||||
|
|
||||||
const checkboxes = [
|
const checkboxes: {
|
||||||
|
name: 'dnssec_enabled' | 'disable_ipv6';
|
||||||
|
placeholder: string;
|
||||||
|
subtitle: string;
|
||||||
|
}[] = [
|
||||||
{
|
{
|
||||||
name: 'dnssec_enabled',
|
name: 'dnssec_enabled',
|
||||||
placeholder: 'dnssec_enable',
|
placeholder: i18next.t('dnssec_enable'),
|
||||||
subtitle: 'dnssec_enable_desc',
|
subtitle: i18next.t('dnssec_enable_desc'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'disable_ipv6',
|
name: 'disable_ipv6',
|
||||||
placeholder: 'disable_ipv6',
|
placeholder: i18next.t('disable_ipv6'),
|
||||||
subtitle: 'disable_ipv6_desc',
|
subtitle: i18next.t('disable_ipv6_desc'),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -52,13 +53,13 @@ type FormData = {
|
|||||||
blocking_ipv4?: string;
|
blocking_ipv4?: string;
|
||||||
blocking_ipv6?: string;
|
blocking_ipv6?: string;
|
||||||
blocked_response_ttl: number;
|
blocked_response_ttl: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
processing?: boolean;
|
processing?: boolean;
|
||||||
initialValues?: Partial<FormData>;
|
initialValues?: Partial<FormData>;
|
||||||
onSubmit: (data: FormData) => void;
|
onSubmit: (data: FormData) => void;
|
||||||
}
|
};
|
||||||
|
|
||||||
const Form = ({ processing, initialValues, onSubmit }: Props) => {
|
const Form = ({ processing, initialValues, onSubmit }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -67,6 +68,7 @@ const Form = ({ processing, initialValues, onSubmit }: Props) => {
|
|||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
watch,
|
watch,
|
||||||
|
control,
|
||||||
formState: { errors, isSubmitting, isDirty },
|
formState: { errors, isSubmitting, isDirty },
|
||||||
} = useForm<FormData>({
|
} = useForm<FormData>({
|
||||||
mode: 'onChange',
|
mode: 'onChange',
|
||||||
@@ -86,9 +88,7 @@ const Form = ({ processing, initialValues, onSubmit }: Props) => {
|
|||||||
{t('rate_limit')}
|
{t('rate_limit')}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="form__desc form__desc--top">
|
<div className="form__desc form__desc--top">{t('rate_limit_desc')}</div>
|
||||||
{t('rate_limit_desc')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<input
|
<input
|
||||||
id="ratelimit"
|
id="ratelimit"
|
||||||
@@ -103,9 +103,7 @@ const Form = ({ processing, initialValues, onSubmit }: Props) => {
|
|||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
{errors.ratelimit && (
|
{errors.ratelimit && (
|
||||||
<div className="form__message form__message--error">
|
<div className="form__message form__message--error">{errors.ratelimit.message}</div>
|
||||||
{errors.ratelimit.message}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -116,9 +114,7 @@ const Form = ({ processing, initialValues, onSubmit }: Props) => {
|
|||||||
{t('rate_limit_subnet_len_ipv4')}
|
{t('rate_limit_subnet_len_ipv4')}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="form__desc form__desc--top">
|
<div className="form__desc form__desc--top">{t('rate_limit_subnet_len_ipv4_desc')}</div>
|
||||||
{t('rate_limit_subnet_len_ipv4_desc')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<input
|
<input
|
||||||
id="ratelimit_subnet_len_ipv4"
|
id="ratelimit_subnet_len_ipv4"
|
||||||
@@ -146,9 +142,7 @@ const Form = ({ processing, initialValues, onSubmit }: Props) => {
|
|||||||
{t('rate_limit_subnet_len_ipv6')}
|
{t('rate_limit_subnet_len_ipv6')}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="form__desc form__desc--top">
|
<div className="form__desc form__desc--top">{t('rate_limit_subnet_len_ipv6_desc')}</div>
|
||||||
{t('rate_limit_subnet_len_ipv6_desc')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<input
|
<input
|
||||||
id="ratelimit_subnet_len_ipv6"
|
id="ratelimit_subnet_len_ipv6"
|
||||||
@@ -176,9 +170,7 @@ const Form = ({ processing, initialValues, onSubmit }: Props) => {
|
|||||||
{t('rate_limit_whitelist')}
|
{t('rate_limit_whitelist')}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="form__desc form__desc--top">
|
<div className="form__desc form__desc--top">{t('rate_limit_whitelist_desc')}</div>
|
||||||
{t('rate_limit_whitelist_desc')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<textarea
|
<textarea
|
||||||
id="ratelimit_whitelist"
|
id="ratelimit_whitelist"
|
||||||
@@ -198,41 +190,37 @@ const Form = ({ processing, initialValues, onSubmit }: Props) => {
|
|||||||
|
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<div className="form__group form__group--settings">
|
<div className="form__group form__group--settings">
|
||||||
<label className="checkbox checkbox--settings">
|
<Controller
|
||||||
<span className="checkbox__marker" />
|
name="edns_cs_enabled"
|
||||||
<input
|
control={control}
|
||||||
id="edns_cs_enabled"
|
render={({ field: { name, value, onChange } }) => (
|
||||||
type="checkbox"
|
<Checkbox
|
||||||
className="checkbox__input"
|
name={name}
|
||||||
disabled={processing}
|
title={t('edns_enable')}
|
||||||
{...register('edns_cs_enabled')}
|
value={value}
|
||||||
/>
|
onChange={(value) => onChange(value)}
|
||||||
<span className="checkbox__label">
|
disabled={processing}
|
||||||
<span className="checkbox__label-text">
|
/>
|
||||||
<span className="checkbox__label-title">{t('edns_enable')}</span>
|
)}
|
||||||
</span>
|
/>
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-12 form__group form__group--inner">
|
<div className="col-12 form__group form__group--inner">
|
||||||
<div className="form__group">
|
<div className="form__group">
|
||||||
<label className="checkbox checkbox--settings">
|
<Controller
|
||||||
<span className="checkbox__marker" />
|
name="edns_cs_use_custom"
|
||||||
<input
|
control={control}
|
||||||
id="edns_cs_use_custom"
|
render={({ field: { name, value, onChange } }) => (
|
||||||
type="checkbox"
|
<Checkbox
|
||||||
className="checkbox__input"
|
name={name}
|
||||||
disabled={processing || !edns_cs_enabled}
|
title={t('edns_use_custom_ip')}
|
||||||
{...register('edns_cs_use_custom')}
|
value={value}
|
||||||
/>
|
onChange={(value) => onChange(value)}
|
||||||
<span className="checkbox__label">
|
disabled={processing || !edns_cs_enabled}
|
||||||
<span className="checkbox__label-text">
|
/>
|
||||||
<span className="checkbox__label-subtitle">{t('edns_use_custom_ip')}</span>
|
)}
|
||||||
</span>
|
/>
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{edns_cs_use_custom && (
|
{edns_cs_use_custom && (
|
||||||
@@ -252,42 +240,32 @@ const Form = ({ processing, initialValues, onSubmit }: Props) => {
|
|||||||
{checkboxes.map(({ name, placeholder, subtitle }) => (
|
{checkboxes.map(({ name, placeholder, subtitle }) => (
|
||||||
<div className="col-12" key={name}>
|
<div className="col-12" key={name}>
|
||||||
<div className="form__group form__group--settings">
|
<div className="form__group form__group--settings">
|
||||||
<label className="checkbox checkbox--settings">
|
<Controller
|
||||||
<span className="checkbox__marker" />
|
name={name}
|
||||||
<input
|
control={control}
|
||||||
id={name}
|
render={({ field: { name, value, onChange } }) => (
|
||||||
type="checkbox"
|
<Checkbox
|
||||||
className="checkbox__input"
|
name={name}
|
||||||
disabled={processing}
|
title={placeholder}
|
||||||
{...register(name as keyof FormData)}
|
subtitle={subtitle}
|
||||||
/>
|
value={value}
|
||||||
<span className="checkbox__label">
|
onChange={(value) => onChange(value)}
|
||||||
<span className="checkbox__label-text">
|
disabled={processing}
|
||||||
<span className="checkbox__label-title">{t(placeholder)}</span>
|
/>
|
||||||
{subtitle && (
|
)}
|
||||||
<span className="checkbox__label-subtitle">{t(subtitle)}</span>
|
/>
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<div className="form__group form__group--settings mb-4">
|
<div className="form__group form__group--settings mb-4">
|
||||||
<label className="form__label form__label--with-desc">
|
<label className="form__label form__label--with-desc">{t('blocking_mode')}</label>
|
||||||
{t('blocking_mode')}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div className="form__desc form__desc--top">
|
<div className="form__desc form__desc--top">
|
||||||
{Object.values(BLOCKING_MODES)
|
{Object.values(BLOCKING_MODES).map((mode: any) => (
|
||||||
|
<li key={mode}>{t(`blocking_mode_${mode}`)}</li>
|
||||||
.map((mode: any) => (
|
))}
|
||||||
<li key={mode}>
|
|
||||||
{t(`blocking_mode_${mode}`)}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="custom-controls-stacked">
|
<div className="custom-controls-stacked">
|
||||||
@@ -315,9 +293,7 @@ const Form = ({ processing, initialValues, onSubmit }: Props) => {
|
|||||||
{t(name)}
|
{t(name)}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="form__desc form__desc--top">
|
<div className="form__desc form__desc--top">{t(description)}</div>
|
||||||
{t(description)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<input
|
<input
|
||||||
id={name}
|
id={name}
|
||||||
@@ -346,9 +322,7 @@ const Form = ({ processing, initialValues, onSubmit }: Props) => {
|
|||||||
{t('blocked_response_ttl')}
|
{t('blocked_response_ttl')}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="form__desc form__desc--top">
|
<div className="form__desc form__desc--top">{t('blocked_response_ttl_desc')}</div>
|
||||||
{t('blocked_response_ttl_desc')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<input
|
<input
|
||||||
id="blocked_response_ttl"
|
id="blocked_response_ttl"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { getTextareaCommentsHighlight, syncScroll } from '../../../../helpers/hi
|
|||||||
import { RootState } from '../../../../initialState';
|
import { RootState } from '../../../../initialState';
|
||||||
import '../../../ui/texareaCommentsHighlight.css';
|
import '../../../ui/texareaCommentsHighlight.css';
|
||||||
import Examples from './Examples';
|
import Examples from './Examples';
|
||||||
|
import { Checkbox } from '../../../ui/Controls/Checkbox';
|
||||||
|
|
||||||
const UPSTREAM_DNS_NAME = 'upstream_dns';
|
const UPSTREAM_DNS_NAME = 'upstream_dns';
|
||||||
const UPSTREAM_MODE_NAME = 'upstream_mode';
|
const UPSTREAM_MODE_NAME = 'upstream_mode';
|
||||||
@@ -23,12 +24,12 @@ type FormData = {
|
|||||||
local_ptr_upstreams: string;
|
local_ptr_upstreams: string;
|
||||||
use_private_ptr_resolvers: boolean;
|
use_private_ptr_resolvers: boolean;
|
||||||
resolve_clients: boolean;
|
resolve_clients: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
type FormProps = {
|
type FormProps = {
|
||||||
initialValues?: Partial<FormData>;
|
initialValues?: Partial<FormData>;
|
||||||
onSubmit: (data: FormData) => void;
|
onSubmit: (data: FormData) => void;
|
||||||
}
|
};
|
||||||
|
|
||||||
const INPUT_FIELDS = [
|
const INPUT_FIELDS = [
|
||||||
{
|
{
|
||||||
@@ -96,37 +97,29 @@ const Form = ({ initialValues, onSubmit }: FormProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(onSubmit)} className="form--upstream">
|
<form onSubmit={handleSubmit(onSubmit)} className="form--upstream">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<label className="col form__label" htmlFor={UPSTREAM_DNS_NAME}>
|
<label className="col form__label" htmlFor={UPSTREAM_DNS_NAME}>
|
||||||
<Trans
|
<Trans
|
||||||
components={{
|
components={{
|
||||||
a: <a
|
a: <a href={UPSTREAM_CONFIGURATION_WIKI_LINK} target="_blank" rel="noopener noreferrer" />,
|
||||||
href={UPSTREAM_CONFIGURATION_WIKI_LINK}
|
}}>
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
/>,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
upstream_dns_help
|
upstream_dns_help
|
||||||
</Trans>
|
</Trans>{' '}
|
||||||
{' '}
|
|
||||||
<Trans
|
<Trans
|
||||||
components={[
|
components={[
|
||||||
<a
|
<a
|
||||||
href="https://link.adtidy.org/forward.html?action=dns_kb_providers&from=ui&app=home"
|
href="https://link.adtidy.org/forward.html?action=dns_kb_providers&from=ui&app=home"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
key="0"
|
key="0">
|
||||||
>
|
|
||||||
DNS providers
|
DNS providers
|
||||||
</a>
|
</a>,
|
||||||
]}
|
]}>
|
||||||
>
|
|
||||||
dns_providers
|
dns_providers
|
||||||
</Trans>
|
</Trans>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="col-12 mb-4">
|
<div className="col-12 mb-4">
|
||||||
<div className="text-edit-container">
|
<div className="text-edit-container">
|
||||||
<Controller
|
<Controller
|
||||||
name="upstream_dns"
|
name="upstream_dns"
|
||||||
@@ -188,9 +181,7 @@ const Form = ({ initialValues, onSubmit }: FormProps) => {
|
|||||||
{t('fallback_dns_title')}
|
{t('fallback_dns_title')}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="form__desc form__desc--top">
|
<div className="form__desc form__desc--top">{t('fallback_dns_desc')}</div>
|
||||||
{t('fallback_dns_desc')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Controller
|
<Controller
|
||||||
name="fallback_dns"
|
name="fallback_dns"
|
||||||
@@ -220,9 +211,7 @@ const Form = ({ initialValues, onSubmit }: FormProps) => {
|
|||||||
{t('bootstrap_dns')}
|
{t('bootstrap_dns')}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="form__desc form__desc--top">
|
<div className="form__desc form__desc--top">{t('bootstrap_dns_desc')}</div>
|
||||||
{t('bootstrap_dns_desc')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Controller
|
<Controller
|
||||||
name="bootstrap_dns"
|
name="bootstrap_dns"
|
||||||
@@ -252,13 +241,13 @@ const Form = ({ initialValues, onSubmit }: FormProps) => {
|
|||||||
{t('local_ptr_title')}
|
{t('local_ptr_title')}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="form__desc form__desc--top">
|
<div className="form__desc form__desc--top">{t('local_ptr_desc')}</div>
|
||||||
{t('local_ptr_desc')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="form__desc form__desc--top">
|
<div className="form__desc form__desc--top">
|
||||||
{defaultLocalPtrUpstreams?.length > 0
|
{defaultLocalPtrUpstreams?.length > 0
|
||||||
? t('local_ptr_default_resolver', { ip: defaultLocalPtrUpstreams.map((s: any) => `"${s}"`).join(', ') })
|
? t('local_ptr_default_resolver', {
|
||||||
|
ip: defaultLocalPtrUpstreams.map((s: any) => `"${s}"`).join(', '),
|
||||||
|
})
|
||||||
: t('local_ptr_no_default_resolver')}
|
: t('local_ptr_no_default_resolver')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -284,28 +273,15 @@ const Form = ({ initialValues, onSubmit }: FormProps) => {
|
|||||||
<Controller
|
<Controller
|
||||||
name="use_private_ptr_resolvers"
|
name="use_private_ptr_resolvers"
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field: { value, onChange, ...field } }) => (
|
render={({ field: { name, value, onChange } }) => (
|
||||||
<label className="checkbox">
|
<Checkbox
|
||||||
<span className="checkbox__marker" />
|
name={name}
|
||||||
<input
|
title={t('use_private_ptr_resolvers_title')}
|
||||||
{...field}
|
subtitle={t('use_private_ptr_resolvers_desc')}
|
||||||
type="checkbox"
|
value={value}
|
||||||
checked={value}
|
onChange={(value) => onChange(value)}
|
||||||
onChange={(e) => onChange(e.target.checked)}
|
disabled={processingSetConfig}
|
||||||
className="checkbox__input"
|
/>
|
||||||
disabled={processingSetConfig}
|
|
||||||
/>
|
|
||||||
<span className="checkbox__label">
|
|
||||||
<span className="checkbox__label-text checkbox__label-text--long">
|
|
||||||
<span className="checkbox__label-title">
|
|
||||||
{t('use_private_ptr_resolvers_title')}
|
|
||||||
</span>
|
|
||||||
<span className="checkbox__label-subtitle">
|
|
||||||
{t('use_private_ptr_resolvers_desc')}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -319,24 +295,15 @@ const Form = ({ initialValues, onSubmit }: FormProps) => {
|
|||||||
<Controller
|
<Controller
|
||||||
name="resolve_clients"
|
name="resolve_clients"
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field: { value, onChange, ...field } }) => (
|
render={({ field: { name, value, onChange } }) => (
|
||||||
<label className="checkbox">
|
<Checkbox
|
||||||
<span className="checkbox__marker" />
|
name={name}
|
||||||
<input
|
title={t('resolve_clients_title')}
|
||||||
{...field}
|
subtitle={t('resolve_clients_desc')}
|
||||||
type="checkbox"
|
value={value}
|
||||||
checked={value}
|
onChange={(value) => onChange(value)}
|
||||||
onChange={(e) => onChange(e.target.checked)}
|
disabled={processingSetConfig}
|
||||||
className="checkbox__input"
|
/>
|
||||||
disabled={processingSetConfig}
|
|
||||||
/>
|
|
||||||
<span className="checkbox__label">
|
|
||||||
<span className="checkbox__label-text checkbox__label-text--long">
|
|
||||||
<span className="checkbox__label-title">{t('resolve_clients_title')}</span>
|
|
||||||
<span className="checkbox__label-subtitle">{t('resolve_clients_desc')}</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import React, { useEffect, useRef } from 'react';
|
import React, { useEffect, useRef } from 'react';
|
||||||
import { useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
import { Trans, useTranslation } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { toNumber } from '../../../helpers/form';
|
import { toNumber } from '../../../helpers/form';
|
||||||
import { FILTERS_INTERVALS_HOURS, FILTERS_RELATIVE_LINK } from '../../../helpers/constants';
|
import { FILTERS_INTERVALS_HOURS, FILTERS_RELATIVE_LINK } from '../../../helpers/constants';
|
||||||
|
import { Checkbox } from '../../ui/Controls/Checkbox';
|
||||||
|
|
||||||
const getTitleForInterval = (interval: any, t: any) => {
|
const getTitleForInterval = (interval: any, t: any) => {
|
||||||
if (interval === 0) {
|
if (interval === 0) {
|
||||||
@@ -31,7 +32,7 @@ export const FiltersConfig = ({ initialValues, setFiltersConfig, processing }: P
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const prevFormValuesRef = useRef<FormValues>(initialValues);
|
const prevFormValuesRef = useRef<FormValues>(initialValues);
|
||||||
|
|
||||||
const { register, watch } = useForm({
|
const { register, watch, control } = useForm({
|
||||||
mode: 'onChange',
|
mode: 'onChange',
|
||||||
defaultValues: initialValues,
|
defaultValues: initialValues,
|
||||||
});
|
});
|
||||||
@@ -56,24 +57,20 @@ export const FiltersConfig = ({ initialValues, setFiltersConfig, processing }: P
|
|||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<div className="form__group form__group--settings">
|
<div className="form__group form__group--settings">
|
||||||
<label className="checkbox">
|
<Controller
|
||||||
<span className="checkbox__marker" />
|
name="enabled"
|
||||||
|
control={control}
|
||||||
|
render={({ field: { name, value, onChange } }) => (
|
||||||
|
<Checkbox
|
||||||
|
name={name}
|
||||||
|
title={t('block_domain_use_filters_and_hosts')}
|
||||||
|
value={value}
|
||||||
|
onChange={(value) => onChange(value)}
|
||||||
|
disabled={processing}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
className="checkbox__input"
|
|
||||||
{...register('enabled')}
|
|
||||||
disabled={processing}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<span className="checkbox__label">
|
|
||||||
<span className="checkbox__label-text checkbox__label-text--long">
|
|
||||||
<span className="checkbox__label-title">
|
|
||||||
{t('block_domain_use_filters_and_hosts')}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
<p>
|
<p>
|
||||||
<Trans components={components}>filters_block_toggle_hint</Trans>
|
<Trans components={components}>filters_block_toggle_hint</Trans>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { Trans } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
import i18next from 'i18next';
|
import i18next from 'i18next';
|
||||||
import { useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
|
|
||||||
import { trimLinesAndRemoveEmpty } from '../../../helpers/helpers';
|
import { trimLinesAndRemoveEmpty } from '../../../helpers/helpers';
|
||||||
import {
|
import {
|
||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
CUSTOM_INTERVAL,
|
CUSTOM_INTERVAL,
|
||||||
} from '../../../helpers/constants';
|
} from '../../../helpers/constants';
|
||||||
import '../FormButton.css';
|
import '../FormButton.css';
|
||||||
|
import { Checkbox } from '../../ui/Controls/Checkbox';
|
||||||
|
|
||||||
const getIntervalTitle = (interval: number) => {
|
const getIntervalTitle = (interval: number) => {
|
||||||
switch (interval) {
|
switch (interval) {
|
||||||
@@ -33,7 +34,7 @@ export type FormValues = {
|
|||||||
interval: number;
|
interval: number;
|
||||||
customInterval?: number | null;
|
customInterval?: number | null;
|
||||||
ignored: string;
|
ignored: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
initialValues: Partial<FormValues>;
|
initialValues: Partial<FormValues>;
|
||||||
@@ -41,29 +42,26 @@ type Props = {
|
|||||||
processingReset: boolean;
|
processingReset: boolean;
|
||||||
onSubmit: (values: FormValues) => void;
|
onSubmit: (values: FormValues) => void;
|
||||||
onReset: () => void;
|
onReset: () => void;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export const Form = ({ initialValues, processing, processingReset, onSubmit, onReset }: Props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
export const Form = ({
|
|
||||||
initialValues,
|
|
||||||
processing,
|
|
||||||
processingReset,
|
|
||||||
onSubmit,
|
|
||||||
onReset,
|
|
||||||
}: Props) => {
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
watch,
|
watch,
|
||||||
setValue,
|
setValue,
|
||||||
|
control,
|
||||||
formState: { isSubmitting },
|
formState: { isSubmitting },
|
||||||
} = useForm<FormValues>({
|
} = useForm<FormValues>({
|
||||||
mode: 'onChange',
|
mode: 'onChange',
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
enabled: initialValues.enabled || false,
|
enabled: initialValues.enabled || false,
|
||||||
anonymize_client_ip: initialValues.anonymize_client_ip || false,
|
anonymize_client_ip: initialValues.anonymize_client_ip || false,
|
||||||
interval: initialValues.interval || DAY,
|
interval: initialValues.interval || DAY,
|
||||||
customInterval: initialValues.customInterval || null,
|
customInterval: initialValues.customInterval || null,
|
||||||
ignored: initialValues.ignored || '',
|
ignored: initialValues.ignored || '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -85,50 +83,41 @@ export const Form = ({
|
|||||||
setValue('ignored', trimmed);
|
setValue('ignored', trimmed);
|
||||||
};
|
};
|
||||||
|
|
||||||
const disableSubmit =
|
const disableSubmit = isSubmitting || processing || (intervalValue === RETENTION_CUSTOM && !customIntervalValue);
|
||||||
isSubmitting ||
|
|
||||||
processing ||
|
|
||||||
(intervalValue === RETENTION_CUSTOM && !customIntervalValue);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(onSubmitForm)}>
|
<form onSubmit={handleSubmit(onSubmitForm)}>
|
||||||
<div className="form__group form__group--settings">
|
<div className="form__group form__group--settings">
|
||||||
<label className="checkbox">
|
<Controller
|
||||||
<span className="checkbox__marker" />
|
name="enabled"
|
||||||
|
control={control}
|
||||||
<input
|
render={({ field: { name, value, onChange } }) => (
|
||||||
type="checkbox"
|
<Checkbox
|
||||||
className="checkbox__input"
|
name={name}
|
||||||
{...register('enabled')}
|
title={t('query_log_enable')}
|
||||||
disabled={processing}
|
value={value}
|
||||||
/>
|
onChange={(value) => onChange(value)}
|
||||||
|
disabled={processing}
|
||||||
<span className="checkbox__label">
|
/>
|
||||||
<span className="checkbox__label-text checkbox__label-text--long">
|
)}
|
||||||
<span className="checkbox__label-title">{i18next.t('query_log_enable')}</span>
|
/>
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="form__group form__group--settings">
|
<div className="form__group form__group--settings">
|
||||||
<label className="checkbox">
|
<Controller
|
||||||
<span className="checkbox__marker" />
|
name="anonymize_client_ip"
|
||||||
|
control={control}
|
||||||
<input
|
render={({ field: { name, value, onChange } }) => (
|
||||||
type="checkbox"
|
<Checkbox
|
||||||
className="checkbox__input"
|
name={name}
|
||||||
{...register('anonymize_client_ip')}
|
title={t('anonymize_client_ip')}
|
||||||
disabled={processing}
|
subtitle={t('anonymize_client_ip_desc')}
|
||||||
/>
|
value={value}
|
||||||
|
onChange={(value) => onChange(value)}
|
||||||
<span className="checkbox__label">
|
disabled={processing}
|
||||||
<span className="checkbox__label-text checkbox__label-text--long">
|
/>
|
||||||
<span className="checkbox__label-title">{i18next.t('anonymize_client_ip')}</span>
|
)}
|
||||||
<span className="checkbox__label-subtitle">{i18next.t('anonymize_client_ip_desc')}</span>
|
/>
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="form__label">
|
<div className="form__label">
|
||||||
@@ -180,7 +169,7 @@ export const Form = ({
|
|||||||
value={interval}
|
value={interval}
|
||||||
checked={intervalValue === interval}
|
checked={intervalValue === interval}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setValue("interval", parseInt(e.target.value, 10));
|
setValue('interval', parseInt(e.target.value, 10));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -209,11 +198,7 @@ export const Form = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-5">
|
<div className="mt-5">
|
||||||
<button
|
<button type="submit" className="btn btn-success btn-standard btn-large" disabled={disableSubmit}>
|
||||||
type="submit"
|
|
||||||
className="btn btn-success btn-standard btn-large"
|
|
||||||
disabled={disableSubmit}
|
|
||||||
>
|
|
||||||
<Trans>save_btn</Trans>
|
<Trans>save_btn</Trans>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -221,8 +206,7 @@ export const Form = ({
|
|||||||
type="button"
|
type="button"
|
||||||
className="btn btn-outline-secondary btn-standard form__button"
|
className="btn btn-outline-secondary btn-standard form__button"
|
||||||
onClick={onReset}
|
onClick={onReset}
|
||||||
disabled={processingReset}
|
disabled={processingReset}>
|
||||||
>
|
|
||||||
<Trans>query_log_clear</Trans>
|
<Trans>query_log_clear</Trans>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { Trans } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
import i18next from 'i18next';
|
import i18next from 'i18next';
|
||||||
|
|
||||||
import { useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
import {
|
import {
|
||||||
STATS_INTERVALS_DAYS,
|
STATS_INTERVALS_DAYS,
|
||||||
DAY,
|
DAY,
|
||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
|
|
||||||
import { trimLinesAndRemoveEmpty } from '../../../helpers/helpers';
|
import { trimLinesAndRemoveEmpty } from '../../../helpers/helpers';
|
||||||
import '../FormButton.css';
|
import '../FormButton.css';
|
||||||
|
import { Checkbox } from '../../ui/Controls/Checkbox';
|
||||||
|
|
||||||
const getIntervalTitle = (interval: any) => {
|
const getIntervalTitle = (interval: any) => {
|
||||||
switch (interval) {
|
switch (interval) {
|
||||||
@@ -30,7 +31,7 @@ export type FormValues = {
|
|||||||
interval: number;
|
interval: number;
|
||||||
customInterval?: number | null;
|
customInterval?: number | null;
|
||||||
ignored: string;
|
ignored: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
initialValues: Partial<FormValues>;
|
initialValues: Partial<FormValues>;
|
||||||
@@ -38,28 +39,25 @@ type Props = {
|
|||||||
processingReset: boolean;
|
processingReset: boolean;
|
||||||
onSubmit: (values: FormValues) => void;
|
onSubmit: (values: FormValues) => void;
|
||||||
onReset: () => void;
|
onReset: () => void;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export const Form = ({ initialValues, processing, processingReset, onSubmit, onReset }: Props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
export const Form = ({
|
|
||||||
initialValues,
|
|
||||||
processing,
|
|
||||||
processingReset,
|
|
||||||
onSubmit,
|
|
||||||
onReset,
|
|
||||||
}: Props) => {
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
watch,
|
watch,
|
||||||
setValue,
|
setValue,
|
||||||
|
control,
|
||||||
formState: { isSubmitting },
|
formState: { isSubmitting },
|
||||||
} = useForm<FormValues>({
|
} = useForm<FormValues>({
|
||||||
mode: 'onChange',
|
mode: 'onChange',
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
enabled: initialValues.enabled || false,
|
enabled: initialValues.enabled || false,
|
||||||
interval: initialValues.interval || DAY,
|
interval: initialValues.interval || DAY,
|
||||||
customInterval: initialValues.customInterval || null,
|
customInterval: initialValues.customInterval || null,
|
||||||
ignored: initialValues.ignored || '',
|
ignored: initialValues.ignored || '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -81,30 +79,24 @@ export const Form = ({
|
|||||||
setValue('ignored', trimmed);
|
setValue('ignored', trimmed);
|
||||||
};
|
};
|
||||||
|
|
||||||
const disableSubmit =
|
const disableSubmit = isSubmitting || processing || (intervalValue === RETENTION_CUSTOM && !customIntervalValue);
|
||||||
isSubmitting ||
|
|
||||||
processing ||
|
|
||||||
(intervalValue === RETENTION_CUSTOM && !customIntervalValue);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(onSubmitForm)}>
|
<form onSubmit={handleSubmit(onSubmitForm)}>
|
||||||
<div className="form__group form__group--settings">
|
<div className="form__group form__group--settings">
|
||||||
<label className="checkbox">
|
<Controller
|
||||||
<span className="checkbox__marker" />
|
name="enabled"
|
||||||
|
control={control}
|
||||||
<input
|
render={({ field: { name, value, onChange } }) => (
|
||||||
type="checkbox"
|
<Checkbox
|
||||||
className="checkbox__input"
|
name={name}
|
||||||
{...register('enabled')}
|
title={t('statistics_enable')}
|
||||||
disabled={processing}
|
value={value}
|
||||||
/>
|
onChange={(value) => onChange(value)}
|
||||||
|
disabled={processing}
|
||||||
<span className="checkbox__label">
|
/>
|
||||||
<span className="checkbox__label-text checkbox__label-text--long">
|
)}
|
||||||
<span className="checkbox__label-title">{i18next.t('statistics_enable')}</span>
|
/>
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="form__label form__label--with-desc">
|
<div className="form__label form__label--with-desc">
|
||||||
@@ -134,9 +126,7 @@ export const Form = ({
|
|||||||
|
|
||||||
{!STATS_INTERVALS_DAYS.includes(intervalValue) && (
|
{!STATS_INTERVALS_DAYS.includes(intervalValue) && (
|
||||||
<div className="form__group--input">
|
<div className="form__group--input">
|
||||||
<div className="form__desc form__desc--top">
|
<div className="form__desc form__desc--top">{i18next.t('custom_retention_input')}</div>
|
||||||
{i18next.t('custom_retention_input')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* <Field
|
{/* <Field
|
||||||
key={RETENTION_CUSTOM_INPUT}
|
key={RETENTION_CUSTOM_INPUT}
|
||||||
@@ -183,7 +173,7 @@ export const Form = ({
|
|||||||
value={interval}
|
value={interval}
|
||||||
checked={intervalValue === interval}
|
checked={intervalValue === interval}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setValue("interval", parseInt(e.target.value, 10));
|
setValue('interval', parseInt(e.target.value, 10));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -221,11 +211,7 @@ export const Form = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-5">
|
<div className="mt-5">
|
||||||
<button
|
<button type="submit" className="btn btn-success btn-standard btn-large" disabled={disableSubmit}>
|
||||||
type="submit"
|
|
||||||
className="btn btn-success btn-standard btn-large"
|
|
||||||
disabled={disableSubmit}
|
|
||||||
>
|
|
||||||
<Trans>save_btn</Trans>
|
<Trans>save_btn</Trans>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import React, { Component, Fragment } from 'react';
|
import React, { Component, Fragment } from 'react';
|
||||||
import { withTranslation } from 'react-i18next';
|
import { withTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import i18next from 'i18next';
|
||||||
import StatsConfig from './StatsConfig';
|
import StatsConfig from './StatsConfig';
|
||||||
|
|
||||||
import LogsConfig from './LogsConfig';
|
import LogsConfig from './LogsConfig';
|
||||||
|
|
||||||
import { FiltersConfig } from './FiltersConfig';
|
import { FiltersConfig } from './FiltersConfig';
|
||||||
|
|
||||||
import Checkbox from '../ui/Checkbox';
|
import { Checkbox } from '../ui/Controls/Checkbox';
|
||||||
|
|
||||||
import Loading from '../ui/Loading';
|
import Loading from '../ui/Loading';
|
||||||
|
|
||||||
@@ -24,14 +25,14 @@ const ORDER_KEY = 'order';
|
|||||||
const SETTINGS = {
|
const SETTINGS = {
|
||||||
safebrowsing: {
|
safebrowsing: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
title: 'use_adguard_browsing_sec',
|
title: i18next.t('use_adguard_browsing_sec'),
|
||||||
subtitle: 'use_adguard_browsing_sec_hint',
|
subtitle: i18next.t('use_adguard_browsing_sec_hint'),
|
||||||
[ORDER_KEY]: 0,
|
[ORDER_KEY]: 0,
|
||||||
},
|
},
|
||||||
parental: {
|
parental: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
title: 'use_adguard_parental',
|
title: i18next.t('use_adguard_parental'),
|
||||||
subtitle: 'use_adguard_parental_hint',
|
subtitle: i18next.t('use_adguard_parental_hint'),
|
||||||
[ORDER_KEY]: 1,
|
[ORDER_KEY]: 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -89,9 +90,18 @@ class Settings extends Component<SettingsProps> {
|
|||||||
renderSettings = (settings: any) =>
|
renderSettings = (settings: any) =>
|
||||||
getObjectKeysSorted(SETTINGS, ORDER_KEY).map((key: any) => {
|
getObjectKeysSorted(SETTINGS, ORDER_KEY).map((key: any) => {
|
||||||
const setting = settings[key];
|
const setting = settings[key];
|
||||||
const { enabled } = setting;
|
const { enabled, title, subtitle } = setting;
|
||||||
|
|
||||||
return <Checkbox {...setting} key={key} handleChange={() => this.props.toggleSetting(key, enabled)} />;
|
return (
|
||||||
|
<div key={key} className="form__group form__group--checkbox">
|
||||||
|
<Checkbox
|
||||||
|
value={enabled}
|
||||||
|
title={title}
|
||||||
|
subtitle={subtitle}
|
||||||
|
onChange={(checked) => this.props.toggleSetting(key, !checked)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
renderSafeSearch = () => {
|
renderSafeSearch = () => {
|
||||||
@@ -106,27 +116,29 @@ class Settings extends Component<SettingsProps> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Checkbox
|
<div className="form__group form__group--checkbox">
|
||||||
enabled={enabled}
|
<Checkbox
|
||||||
title="enforce_safe_search"
|
value={enabled}
|
||||||
subtitle="enforce_save_search_hint"
|
title={i18next.t('enforce_safe_search')}
|
||||||
handleChange={({ target: { checked: enabled } }) =>
|
subtitle={i18next.t('enforce_save_search_hint')}
|
||||||
this.props.toggleSetting('safesearch', { ...safesearch, enabled })
|
onChange={(checked) =>
|
||||||
}
|
this.props.toggleSetting('safesearch', { ...safesearch, enabled: checked })
|
||||||
/>
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="form__group--inner">
|
<div className="form__group--inner">
|
||||||
{Object.keys(searches).map((searchKey) => (
|
{Object.keys(searches).map((searchKey) => (
|
||||||
<Checkbox
|
<div key={searchKey} className="form__group form__group--checkbox">
|
||||||
key={searchKey}
|
<Checkbox
|
||||||
enabled={searches[searchKey]}
|
value={searches[searchKey]}
|
||||||
title={captitalizeWords(searchKey)}
|
title={captitalizeWords(searchKey)}
|
||||||
subtitle=""
|
disabled={!safesearch.enabled}
|
||||||
disabled={!safesearch.enabled}
|
onChange={(checked) =>
|
||||||
handleChange={({ target: { checked } }: any) =>
|
this.props.toggleSetting('safesearch', { ...safesearch, [searchKey]: checked })
|
||||||
this.props.toggleSetting('safesearch', { ...safesearch, [searchKey]: checked })
|
}
|
||||||
}
|
/>
|
||||||
/>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import { withTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
import './Checkbox.css';
|
|
||||||
|
|
||||||
interface CheckboxProps {
|
|
||||||
title: string;
|
|
||||||
subtitle: string;
|
|
||||||
enabled: boolean;
|
|
||||||
handleChange: (...args: unknown[]) => unknown;
|
|
||||||
disabled?: boolean;
|
|
||||||
t?: (...args: unknown[]) => string;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Checkbox extends Component<CheckboxProps> {
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
title,
|
|
||||||
|
|
||||||
subtitle,
|
|
||||||
|
|
||||||
enabled,
|
|
||||||
|
|
||||||
handleChange,
|
|
||||||
|
|
||||||
disabled,
|
|
||||||
|
|
||||||
t,
|
|
||||||
} = this.props;
|
|
||||||
return (
|
|
||||||
<div className="form__group form__group--checkbox">
|
|
||||||
<label className="checkbox checkbox--settings">
|
|
||||||
<span className="checkbox__marker" />
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
className="checkbox__input"
|
|
||||||
onChange={handleChange}
|
|
||||||
checked={enabled}
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<span className="checkbox__label">
|
|
||||||
<span className="checkbox__label-text">
|
|
||||||
<span className="checkbox__label-title">{t(title)}</span>
|
|
||||||
|
|
||||||
<span
|
|
||||||
className="checkbox__label-subtitle"
|
|
||||||
dangerouslySetInnerHTML={{ __html: t(subtitle) }}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withTranslation()(Checkbox);
|
|
||||||
35
client/src/components/ui/Controls/Checkbox/index.tsx
Normal file
35
client/src/components/ui/Controls/Checkbox/index.tsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import React, { ReactNode } from 'react';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
|
||||||
|
import './checkbox.css';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
title: string;
|
||||||
|
subtitle?: ReactNode;
|
||||||
|
value: boolean;
|
||||||
|
name?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
className?: string;
|
||||||
|
onChange: (value: boolean) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Checkbox = ({ title, subtitle, value, name, disabled, className = 'checkbox--form', onChange }: Props) => (
|
||||||
|
<label className={clsx('checkbox', className)}>
|
||||||
|
<span className="checkbox__marker" />
|
||||||
|
<input
|
||||||
|
name={name}
|
||||||
|
type="checkbox"
|
||||||
|
className="checkbox__input"
|
||||||
|
disabled={disabled}
|
||||||
|
checked={value}
|
||||||
|
onChange={(e) => onChange(e.target.checked)}
|
||||||
|
/>
|
||||||
|
<span className="checkbox__label">
|
||||||
|
<span className="checkbox__label-text checkbox__label-text--long">
|
||||||
|
<span className="checkbox__label-title">{title}</span>
|
||||||
|
|
||||||
|
{subtitle && <span className="checkbox__label-subtitle">{subtitle}</span>}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
);
|
||||||
63
client/src/components/ui/Controls/InputGroup.tsx
Normal file
63
client/src/components/ui/Controls/InputGroup.tsx
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
id?: string;
|
||||||
|
className?: string;
|
||||||
|
placeholder?: string;
|
||||||
|
type?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
autoComplete?: string;
|
||||||
|
isActionAvailable?: boolean;
|
||||||
|
removeField?: () => void;
|
||||||
|
normalizeOnBlur?: (value: string) => string;
|
||||||
|
value: string;
|
||||||
|
onChange: (value: string) => void;
|
||||||
|
onBlur: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const InputGroup = ({
|
||||||
|
id,
|
||||||
|
className,
|
||||||
|
placeholder,
|
||||||
|
type,
|
||||||
|
disabled,
|
||||||
|
autoComplete,
|
||||||
|
isActionAvailable,
|
||||||
|
removeField,
|
||||||
|
normalizeOnBlur,
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
onBlur,
|
||||||
|
}: Props) => {
|
||||||
|
const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {
|
||||||
|
if (normalizeOnBlur) {
|
||||||
|
onChange(normalizeOnBlur(event.target.value));
|
||||||
|
}
|
||||||
|
onBlur();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="input-group">
|
||||||
|
<input
|
||||||
|
id={id}
|
||||||
|
placeholder={placeholder}
|
||||||
|
type={type}
|
||||||
|
className={className}
|
||||||
|
disabled={disabled}
|
||||||
|
autoComplete={autoComplete}
|
||||||
|
value={value}
|
||||||
|
onChange={(e) => onChange(e.target.value)}
|
||||||
|
onBlur={handleBlur}
|
||||||
|
/>
|
||||||
|
{isActionAvailable && (
|
||||||
|
<span className="input-group-append">
|
||||||
|
<button type="button" className="btn btn-secondary btn-icon btn-icon--green" onClick={removeField}>
|
||||||
|
<svg className="icon icon--24">
|
||||||
|
<use xlinkHref="#cross" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user