cleanup forms
This commit is contained in:
@@ -1,12 +1,14 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
|
|
||||||
import Card from '../../ui/Card';
|
import Card from '../../ui/Card';
|
||||||
import Info from './Info';
|
import Info from './Info';
|
||||||
|
|
||||||
import { RootState } from '../../../initialState';
|
import { RootState } from '../../../initialState';
|
||||||
|
import { validateRequiredValue } from '../../../helpers/validators';
|
||||||
|
import { Input } from '../../ui/Controls/Input';
|
||||||
|
|
||||||
interface FormValues {
|
interface FormValues {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -14,7 +16,7 @@ interface FormValues {
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onSubmit?: (data: FormValues) => void;
|
onSubmit?: (data: FormValues) => void;
|
||||||
}
|
};
|
||||||
|
|
||||||
const Check = ({ onSubmit }: Props) => {
|
const Check = ({ onSubmit }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -23,7 +25,7 @@ const Check = ({ onSubmit }: Props) => {
|
|||||||
const hostname = useSelector((state: RootState) => state.filtering.check.hostname);
|
const hostname = useSelector((state: RootState) => state.filtering.check.hostname);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
register,
|
control,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
formState: { isDirty, isValid },
|
formState: { isDirty, isValid },
|
||||||
} = useForm<FormValues>({
|
} = useForm<FormValues>({
|
||||||
@@ -38,24 +40,29 @@ const Check = ({ onSubmit }: Props) => {
|
|||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12 col-md-6">
|
<div className="col-12 col-md-6">
|
||||||
<div className="input-group">
|
<Controller
|
||||||
<input
|
name="name"
|
||||||
id="name"
|
control={control}
|
||||||
type="text"
|
rules={{ validate: validateRequiredValue }}
|
||||||
className="form-control"
|
render={({ field, fieldState }) => (
|
||||||
placeholder={t('form_enter_host') ?? ''}
|
<Input
|
||||||
{...register('name', { required: t('form_error_required') })}
|
{...field}
|
||||||
/>
|
type="text"
|
||||||
<span className="input-group-append">
|
placeholder={t('form_enter_host')}
|
||||||
<button
|
error={fieldState.error?.message}
|
||||||
className="btn btn-success btn-standard btn-large"
|
rightAddon={
|
||||||
type="submit"
|
<span className="input-group-append">
|
||||||
disabled={!isDirty || !isValid || processingCheck}
|
<button
|
||||||
>
|
className="btn btn-success btn-standard btn-large"
|
||||||
{t('check')}
|
type="submit"
|
||||||
</button>
|
disabled={!isDirty || !isValid || processingCheck}>
|
||||||
</span>
|
{t('check')}
|
||||||
</div>
|
</button>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
{hostname && (
|
{hostname && (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { validatePath, validateRequiredValue } from '../../helpers/validators';
|
|||||||
import { MODAL_OPEN_TIMEOUT, MODAL_TYPE } from '../../helpers/constants';
|
import { MODAL_OPEN_TIMEOUT, MODAL_TYPE } from '../../helpers/constants';
|
||||||
import filtersCatalog from '../../helpers/filters/filters';
|
import filtersCatalog from '../../helpers/filters/filters';
|
||||||
import { FiltersList } from './FiltersList';
|
import { FiltersList } from './FiltersList';
|
||||||
|
import { Input } from '../ui/Controls/Input';
|
||||||
|
|
||||||
type FormValues = {
|
type FormValues = {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
@@ -15,7 +16,7 @@ type FormValues = {
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
closeModal: (...args: unknown[]) => void;
|
closeModal: (...args: unknown[]) => void;
|
||||||
onSubmit: (...args: unknown[]) => void;
|
onSubmit: (values: FormValues) => void;
|
||||||
processingAddFilter: boolean;
|
processingAddFilter: boolean;
|
||||||
processingConfigFilter: boolean;
|
processingConfigFilter: boolean;
|
||||||
whitelist?: boolean;
|
whitelist?: boolean;
|
||||||
@@ -81,13 +82,7 @@ export const Form = ({
|
|||||||
name="name"
|
name="name"
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<input
|
<Input {...field} type="text" placeholder={t('enter_name_hint')} trimOnBlur />
|
||||||
{...field}
|
|
||||||
type="text"
|
|
||||||
className="form-control"
|
|
||||||
placeholder={t('enter_name_hint')}
|
|
||||||
onBlur={(e) => field.onChange(e.target.value.trim())}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -98,12 +93,11 @@ export const Form = ({
|
|||||||
control={control}
|
control={control}
|
||||||
rules={{ validate: { validateRequiredValue, validatePath } }}
|
rules={{ validate: { validateRequiredValue, validatePath } }}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<input
|
<Input
|
||||||
{...field}
|
{...field}
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control"
|
|
||||||
placeholder={t('enter_url_or_path_hint')}
|
placeholder={t('enter_url_or_path_hint')}
|
||||||
onBlur={(e) => field.onChange(e.target.value.trim())}
|
trimOnBlur
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import React from 'react';
|
import React 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 { validateAnswer, validateDomain } from '../../../helpers/validators';
|
import { validateAnswer, validateDomain, validateRequiredValue } from '../../../helpers/validators';
|
||||||
|
import { Input } from '../../ui/Controls/Input';
|
||||||
|
|
||||||
interface FormValues {
|
interface FormValues {
|
||||||
domain: string;
|
domain: string;
|
||||||
@@ -11,21 +12,21 @@ interface FormValues {
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
processingAdd: boolean;
|
processingAdd: boolean;
|
||||||
currentRewrite?: { answer: string, domain: string; };
|
currentRewrite?: { answer: string; domain: string };
|
||||||
toggleRewritesModal: () => void;
|
toggleRewritesModal: () => void;
|
||||||
onSubmit?: (data: FormValues) => Promise<void> | void;
|
onSubmit?: (data: FormValues) => Promise<void> | void;
|
||||||
}
|
};
|
||||||
|
|
||||||
const Form = ({ processingAdd, currentRewrite, toggleRewritesModal, onSubmit }: Props) => {
|
const Form = ({ processingAdd, currentRewrite, toggleRewritesModal, onSubmit }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
register,
|
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
reset,
|
reset,
|
||||||
formState: { isDirty, isSubmitting, errors },
|
control,
|
||||||
|
formState: { isDirty, isSubmitting },
|
||||||
} = useForm<FormValues>({
|
} = useForm<FormValues>({
|
||||||
mode: 'onChange',
|
mode: 'onChange',
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
domain: currentRewrite?.domain || '',
|
domain: currentRewrite?.domain || '',
|
||||||
answer: currentRewrite?.answer || '',
|
answer: currentRewrite?.answer || '',
|
||||||
@@ -45,21 +46,24 @@ const Form = ({ processingAdd, currentRewrite, toggleRewritesModal, onSubmit }:
|
|||||||
<Trans>domain_desc</Trans>
|
<Trans>domain_desc</Trans>
|
||||||
</div>
|
</div>
|
||||||
<div className="form__group">
|
<div className="form__group">
|
||||||
<input
|
<Controller
|
||||||
id="domain"
|
name="domain"
|
||||||
type="text"
|
control={control}
|
||||||
className="form-control"
|
rules={{
|
||||||
placeholder={t('form_domain')}
|
validate: {
|
||||||
{...register('domain', {
|
validate: validateDomain,
|
||||||
validate: validateDomain,
|
required: validateRequiredValue,
|
||||||
required: t('form_error_required'),
|
},
|
||||||
})}
|
}}
|
||||||
|
render={({ field, fieldState }) => (
|
||||||
|
<Input
|
||||||
|
{...field}
|
||||||
|
type="text"
|
||||||
|
placeholder={t('form_domain')}
|
||||||
|
error={fieldState.error?.message}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
{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">
|
||||||
@@ -74,21 +78,24 @@ const Form = ({ processingAdd, currentRewrite, toggleRewritesModal, onSubmit }:
|
|||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
<div className="form__group">
|
<div className="form__group">
|
||||||
<input
|
<Controller
|
||||||
id="answer"
|
name="answer"
|
||||||
type="text"
|
control={control}
|
||||||
className="form-control"
|
rules={{
|
||||||
placeholder={t('form_answer') ?? ''}
|
validate: {
|
||||||
{...register('answer', {
|
validate: validateAnswer,
|
||||||
validate: validateAnswer,
|
required: validateRequiredValue,
|
||||||
required: t('form_error_required'),
|
},
|
||||||
})}
|
}}
|
||||||
|
render={({ field, fieldState }) => (
|
||||||
|
<Input
|
||||||
|
{...field}
|
||||||
|
type="text"
|
||||||
|
placeholder={t('form_answer')}
|
||||||
|
error={fieldState.error?.message}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
{errors.answer && (
|
|
||||||
<div className="form__message form__message--error">
|
|
||||||
{errors.answer.message}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -109,16 +116,14 @@ const Form = ({ processingAdd, currentRewrite, toggleRewritesModal, onSubmit }:
|
|||||||
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={isSubmitting || !isDirty || processingAdd}
|
disabled={isSubmitting || !isDirty || processingAdd}>
|
||||||
>
|
|
||||||
<Trans>save_btn</Trans>
|
<Trans>save_btn</Trans>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ type FormValues = {
|
|||||||
interface FormProps {
|
interface FormProps {
|
||||||
initialValues: Record<string, boolean>;
|
initialValues: Record<string, boolean>;
|
||||||
blockedServices: BlockedService[];
|
blockedServices: BlockedService[];
|
||||||
onSubmit: (...args: unknown[]) => void;
|
onSubmit: (values: FormValues) => void;
|
||||||
processing: boolean;
|
processing: boolean;
|
||||||
processingSet: boolean;
|
processingSet: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,52 +2,40 @@ import React from 'react';
|
|||||||
import cn from 'classnames';
|
import cn from 'classnames';
|
||||||
import { FieldValues, ControllerRenderProps } from 'react-hook-form';
|
import { FieldValues, ControllerRenderProps } from 'react-hook-form';
|
||||||
|
|
||||||
interface ServiceFieldProps extends ControllerRenderProps<FieldValues> {
|
type Props = ControllerRenderProps<FieldValues> & {
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
error?: string;
|
error?: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const ServiceField = React.forwardRef<HTMLInputElement, ServiceFieldProps>(({
|
export const ServiceField = React.forwardRef<HTMLInputElement, Props>(
|
||||||
name,
|
({ name, value, onChange, onBlur, placeholder, disabled, className, icon, error }, ref) => (
|
||||||
value,
|
<>
|
||||||
onChange,
|
<label className={cn('service custom-switch', className)}>
|
||||||
onBlur,
|
<input
|
||||||
placeholder,
|
name={name}
|
||||||
disabled,
|
type="checkbox"
|
||||||
className,
|
className="custom-switch-input"
|
||||||
icon,
|
checked={!!value}
|
||||||
error,
|
onChange={onChange}
|
||||||
}, ref) => (
|
onBlur={onBlur}
|
||||||
<>
|
ref={ref}
|
||||||
<label className={cn('service custom-switch', className)}>
|
disabled={disabled}
|
||||||
<input
|
/>
|
||||||
name={name}
|
|
||||||
type="checkbox"
|
|
||||||
className="custom-switch-input"
|
|
||||||
checked={!!value}
|
|
||||||
onChange={onChange}
|
|
||||||
onBlur={onBlur}
|
|
||||||
ref={ref}
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<span className="service__switch custom-switch-indicator"></span>
|
<span className="service__switch custom-switch-indicator"></span>
|
||||||
|
|
||||||
<span className="service__text" title={placeholder}>
|
<span className="service__text" title={placeholder}>
|
||||||
{placeholder}
|
{placeholder}
|
||||||
</span>
|
</span>
|
||||||
{icon && <div dangerouslySetInnerHTML={{ __html: window.atob(icon) }} className="service__icon" />}
|
{icon && <div dangerouslySetInnerHTML={{ __html: window.atob(icon) }} className="service__icon" />}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
{!disabled && error && (
|
{!disabled && error && <span className="form__message form__message--error">{error}</span>}
|
||||||
<span className="form__message form__message--error">
|
</>
|
||||||
{error}
|
),
|
||||||
</span>
|
);
|
||||||
)}
|
|
||||||
</>
|
|
||||||
));
|
|
||||||
|
|
||||||
ServiceField.displayName = 'ServiceField';
|
ServiceField.displayName = 'ServiceField';
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ import { SearchField } from './SearchField';
|
|||||||
export type FormValues = {
|
export type FormValues = {
|
||||||
search: string;
|
search: string;
|
||||||
response_status: string;
|
response_status: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
initialValues: FormValues;
|
initialValues: FormValues;
|
||||||
className?: string;
|
className?: string;
|
||||||
setIsLoading: (...args: unknown[]) => unknown;
|
setIsLoading: (value: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Form = ({ initialValues, className, setIsLoading }: Props) => {
|
export const Form = ({ initialValues, className, setIsLoading }: Props) => {
|
||||||
@@ -35,11 +35,7 @@ export const Form = ({ initialValues, className, setIsLoading }: Props) => {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
const {
|
const { register, watch, setValue } = useForm<FormValues>({
|
||||||
register,
|
|
||||||
watch,
|
|
||||||
setValue,
|
|
||||||
} = useForm<FormValues>({
|
|
||||||
mode: 'onChange',
|
mode: 'onChange',
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
search: initialValues.search || DEFAULT_LOGS_FILTER.search,
|
search: initialValues.search || DEFAULT_LOGS_FILTER.search,
|
||||||
@@ -50,10 +46,7 @@ export const Form = ({ initialValues, className, setIsLoading }: Props) => {
|
|||||||
const searchValue = watch('search');
|
const searchValue = watch('search');
|
||||||
const responseStatusValue = watch('response_status');
|
const responseStatusValue = watch('response_status');
|
||||||
|
|
||||||
const [debouncedSearch, setDebouncedSearch] = useDebounce(
|
const [debouncedSearch, setDebouncedSearch] = useDebounce(searchValue.trim(), DEBOUNCE_FILTER_TIMEOUT);
|
||||||
searchValue.trim(),
|
|
||||||
DEBOUNCE_FILTER_TIMEOUT
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(
|
dispatch(
|
||||||
@@ -91,7 +84,7 @@ export const Form = ({ initialValues, className, setIsLoading }: Props) => {
|
|||||||
value: e.target.value,
|
value: e.target.value,
|
||||||
onChange: (v: string) => setValue('search', v),
|
onChange: (v: string) => setValue('search', v),
|
||||||
},
|
},
|
||||||
(data: string) => data.trim()
|
(data: string) => data.trim(),
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -99,8 +92,7 @@ export const Form = ({ initialValues, className, setIsLoading }: Props) => {
|
|||||||
className="d-flex flex-wrap form-control--container"
|
className="d-flex flex-wrap form-control--container"
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}}
|
}}>
|
||||||
>
|
|
||||||
<div className="field__search">
|
<div className="field__search">
|
||||||
<SearchField
|
<SearchField
|
||||||
value={searchValue}
|
value={searchValue}
|
||||||
@@ -117,8 +109,7 @@ export const Form = ({ initialValues, className, setIsLoading }: Props) => {
|
|||||||
<div className="field__select">
|
<div className="field__select">
|
||||||
<select
|
<select
|
||||||
{...register('response_status')}
|
{...register('response_status')}
|
||||||
className="form-control custom-select custom-select--logs custom-select__arrow--left form-control--transparent d-sm-block"
|
className="form-control custom-select custom-select--logs custom-select__arrow--left form-control--transparent d-sm-block">
|
||||||
>
|
|
||||||
{Object.values(RESPONSE_FILTER).map(({ QUERY, LABEL, disabled }: any) => (
|
{Object.values(RESPONSE_FILTER).map(({ QUERY, LABEL, disabled }: any) => (
|
||||||
<option key={LABEL} value={QUERY} disabled={disabled}>
|
<option key={LABEL} value={QUERY} disabled={disabled}>
|
||||||
{t(LABEL)}
|
{t(LABEL)}
|
||||||
|
|||||||
@@ -111,6 +111,12 @@ const ClientsTable = ({
|
|||||||
config.tags = [];
|
config.tags = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (values.ids) {
|
||||||
|
config.ids = values.ids.map((id) => id.name);
|
||||||
|
} else {
|
||||||
|
config.ids = [];
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof values.upstreams_cache_size === 'string') {
|
if (typeof values.upstreams_cache_size === 'string') {
|
||||||
config.upstreams_cache_size = 0;
|
config.upstreams_cache_size = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const defaultFormValues: ClientForm = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onSubmit: (...args: unknown[]) => void;
|
onSubmit: (values: ClientForm) => void;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
useGlobalSettings?: boolean;
|
useGlobalSettings?: boolean;
|
||||||
useGlobalServices?: boolean;
|
useGlobalServices?: boolean;
|
||||||
@@ -45,7 +45,7 @@ type Props = {
|
|||||||
};
|
};
|
||||||
processingAdding: boolean;
|
processingAdding: boolean;
|
||||||
processingUpdating: boolean;
|
processingUpdating: boolean;
|
||||||
tagsOptions: unknown[];
|
tagsOptions: { label: string; value: string }[];
|
||||||
initialValues?: ClientForm;
|
initialValues?: ClientForm;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -79,15 +79,6 @@ export const Form = ({
|
|||||||
const safeSearchServices = { ...safe_search };
|
const safeSearchServices = { ...safe_search };
|
||||||
delete safeSearchServices.enabled;
|
delete safeSearchServices.enabled;
|
||||||
|
|
||||||
const onFormSubmit = (values: ClientForm) => {
|
|
||||||
const data = {
|
|
||||||
...values,
|
|
||||||
ids: values.ids.map((idObj) => idObj.name),
|
|
||||||
};
|
|
||||||
|
|
||||||
onSubmit(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
const [activeTabLabel, setActiveTabLabel] = useState('settings');
|
const [activeTabLabel, setActiveTabLabel] = useState('settings');
|
||||||
|
|
||||||
const tabs = {
|
const tabs = {
|
||||||
@@ -113,7 +104,7 @@ export const Form = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<FormProvider {...methods}>
|
<FormProvider {...methods}>
|
||||||
<form onSubmit={handleSubmit(onFormSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
<div className="form__group mb-0">
|
<div className="form__group mb-0">
|
||||||
<div className="form__group">
|
<div className="form__group">
|
||||||
|
|||||||
@@ -21,3 +21,8 @@ export type ClientForm = {
|
|||||||
ignore_querylog: boolean;
|
ignore_querylog: boolean;
|
||||||
ignore_statistics: boolean;
|
ignore_statistics: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type SubmitClientForm = Omit<ClientForm, 'ids' | 'tags'> & {
|
||||||
|
ids: string[];
|
||||||
|
tags: string[];
|
||||||
|
};
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ interface ModalProps {
|
|||||||
handleClose: (...args: unknown[]) => unknown;
|
handleClose: (...args: unknown[]) => unknown;
|
||||||
processingAdding: boolean;
|
processingAdding: boolean;
|
||||||
processingUpdating: boolean;
|
processingUpdating: boolean;
|
||||||
tagsOptions: unknown[];
|
tagsOptions: { label: string; value: string }[];
|
||||||
t: (...args: unknown[]) => string;
|
t: (...args: unknown[]) => string;
|
||||||
clientId?: string;
|
clientId?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import React, { useMemo } from 'react';
|
|||||||
import { useFormContext } from 'react-hook-form';
|
import { useFormContext } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { isValid } from 'date-fns';
|
|
||||||
import { UINT32_RANGE } from '../../../helpers/constants';
|
import { UINT32_RANGE } from '../../../helpers/constants';
|
||||||
import {
|
import {
|
||||||
validateGatewaySubnetMask,
|
validateGatewaySubnetMask,
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ export const FiltersConfig = ({ initialValues, setFiltersConfig, processing }: P
|
|||||||
disabled={processing}>
|
disabled={processing}>
|
||||||
{FILTERS_INTERVALS_HOURS.map((interval) => (
|
{FILTERS_INTERVALS_HOURS.map((interval) => (
|
||||||
<option value={interval} key={interval}>
|
<option value={interval} key={interval}>
|
||||||
{getTitleForInterval(interval, t)}
|
{getTitleForInterval(interval)}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ type Props = ComponentProps<'input'> & {
|
|||||||
leftAddon?: ReactNode;
|
leftAddon?: ReactNode;
|
||||||
rightAddon?: ReactNode;
|
rightAddon?: ReactNode;
|
||||||
error?: string;
|
error?: string;
|
||||||
|
trimOnBlur?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Input = forwardRef<HTMLInputElement, Props>(
|
export const Input = forwardRef<HTMLInputElement, Props>(
|
||||||
({ name, label, className, leftAddon, rightAddon, error, ...rest }, ref) => (
|
({ name, label, className, leftAddon, rightAddon, error, trimOnBlur, onBlur, ...rest }, ref) => (
|
||||||
<div className={clsx('form-group', { 'has-error': !!error })}>
|
<div className={clsx('form-group', { 'has-error': !!error })}>
|
||||||
{label && (
|
{label && (
|
||||||
<label className="form__label" htmlFor={name}>
|
<label className="form__label" htmlFor={name}>
|
||||||
@@ -18,7 +19,20 @@ export const Input = forwardRef<HTMLInputElement, Props>(
|
|||||||
)}
|
)}
|
||||||
<div className="input-group">
|
<div className="input-group">
|
||||||
{leftAddon && <div>{leftAddon}</div>}
|
{leftAddon && <div>{leftAddon}</div>}
|
||||||
<input className={clsx('form-control', { 'is-invalid': !!error }, className)} ref={ref} {...rest} />
|
<input
|
||||||
|
className={clsx('form-control', { 'is-invalid': !!error }, className)}
|
||||||
|
ref={ref}
|
||||||
|
onBlur={(e) => {
|
||||||
|
if (trimOnBlur) {
|
||||||
|
e.target.value = e.target.value.trim();
|
||||||
|
rest.onChange(e);
|
||||||
|
}
|
||||||
|
if (onBlur) {
|
||||||
|
onBlur(e);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
{rightAddon && <div>{rightAddon}</div>}
|
{rightAddon && <div>{rightAddon}</div>}
|
||||||
</div>
|
</div>
|
||||||
{error && <div className="form__message form__message--error mt-1">{error}</div>}
|
{error && <div className="form__message form__message--error mt-1">{error}</div>}
|
||||||
|
|||||||
Reference in New Issue
Block a user