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