mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2026-08-04 15:28:58 +00:00
fix validation issues
This commit is contained in:
parent
0e677a7349
commit
20158785f0
12 changed files with 50 additions and 35 deletions
|
|
@ -75,6 +75,7 @@
|
|||
"client_id_placeholder": "Enter a ClientID",
|
||||
"client_added": "Client added",
|
||||
"client_removed": "Client removed",
|
||||
"client_name_already_exists": "Client with this name already exists",
|
||||
"download_mobileconfig": "Download configuration file",
|
||||
"plain_dns": "Plain DNS",
|
||||
"rate_limit_subnet_len_ipv4_error": "The IPv4 subnet prefix length should be between 0 and 32",
|
||||
|
|
@ -634,6 +635,7 @@
|
|||
"dhcp_table_mac_address": "MAC address",
|
||||
"dhcp_table_ip_address": "IP address",
|
||||
"dhcp_table_hostname": "Hostname",
|
||||
"dhcp_mac_address_already_added": "This MAC address is already added",
|
||||
"reset_settings": "Reset settings",
|
||||
"reset_settings_confirm": "Yes, reset",
|
||||
"actions_table_header": "Actions",
|
||||
|
|
@ -790,6 +792,7 @@
|
|||
"notify_undo": "Undo",
|
||||
"user_rules_domain_is_allowed": "Domain is allowed",
|
||||
"user_rules_rule_added_to_custom_filtering_rules": "Rule added to custom filtering rules",
|
||||
"user_rules_rule_added": "User rule added: <strong>%rule%</strong>",
|
||||
"user_rules_disable_parental_control": "Disable Parental control",
|
||||
"user_rules_parental_control_disabled": "Parental control disabled",
|
||||
"user_rules_disable_browsing_security": "Disable Browsing security",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { createMemo, createEffect, Show, onMount } from 'solid-js';
|
||||
import { createMemo, createEffect, createSignal, Show, onMount } from 'solid-js';
|
||||
import { useNavigate, useParams, useLocation } from '@solidjs/router';
|
||||
import cn from 'clsx';
|
||||
|
||||
|
|
@ -37,11 +37,24 @@ export const AddClient = () => {
|
|||
const params = useParams<{ clientName?: string }>();
|
||||
const location = useLocation();
|
||||
|
||||
const [nameError, setNameError] = createSignal<string | undefined>();
|
||||
|
||||
createEffect(() => {
|
||||
const formErrors = clientFormState.formErrors;
|
||||
setNameError(
|
||||
typeof formErrors.name === 'string' ? formErrors.name : undefined,
|
||||
);
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
getClients();
|
||||
});
|
||||
|
||||
// Set initial ID from query params
|
||||
const handleNameChange = (e: Event) => {
|
||||
const value = (e.target as HTMLInputElement).value;
|
||||
updateClientFormField({ field: 'name', value });
|
||||
setNameError(undefined);
|
||||
};
|
||||
createEffect(() => {
|
||||
const searchParams = new URLSearchParams(location.search);
|
||||
const id = searchParams.get('id');
|
||||
|
|
@ -180,27 +193,13 @@ export const AddClient = () => {
|
|||
data-testid="client-form-name"
|
||||
type="text"
|
||||
value={clientFormState.name}
|
||||
onChange={(e: Event) =>
|
||||
updateClientFormField({
|
||||
field: 'name',
|
||||
value: (e.target as HTMLInputElement).value,
|
||||
})
|
||||
}
|
||||
onInput={(e: Event) =>
|
||||
updateClientFormField({
|
||||
field: 'name',
|
||||
value: (e.target as HTMLInputElement).value,
|
||||
})
|
||||
}
|
||||
onChange={handleNameChange}
|
||||
onInput={handleNameChange}
|
||||
placeholder={intl.getMessage('clients_add_default_name')}
|
||||
label={intl.getMessage('clients_add_name')}
|
||||
size="large"
|
||||
error={!!clientFormState.formErrors.name}
|
||||
errorMessage={
|
||||
typeof clientFormState.formErrors.name === 'string'
|
||||
? clientFormState.formErrors.name
|
||||
: undefined
|
||||
}
|
||||
error={!!nameError()}
|
||||
errorMessage={nameError()}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ export const Dhcp = () => {
|
|||
|
||||
const handleLeaseModalSubmit = (data: LeaseData) => {
|
||||
if (dhcpState.modalType === MODAL_TYPE.EDIT_LEASE) {
|
||||
updateStaticLease({ target: dhcpState.leaseModalConfig!, update: data });
|
||||
updateStaticLease(data);
|
||||
} else {
|
||||
addStaticLease(data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ export const Form = (props: Props) => {
|
|||
setWhitelistError(
|
||||
ratelimitWhitelist() ? validateIpPerLine(ratelimitWhitelist()) || '' : '',
|
||||
);
|
||||
setTtlError(validateRequiredValue(String(blockedResponseTtl())) || '');
|
||||
setTtlError(validateRequiredValue(String(blockedResponseTtl())) || validateBetween(blockedResponseTtl(), UINT32_RANGE.MIN, UINT32_RANGE.MAX) || '');
|
||||
|
||||
if (ednsCsUseCustom()) {
|
||||
const err =
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { Button } from 'panel/common/ui/Button';
|
|||
import { FaqTooltip } from 'panel/common/ui/FaqTooltip';
|
||||
import intl from 'panel/common/intl';
|
||||
import { DNS_REQUEST_OPTIONS, UINT32_RANGE, UPSTREAM_TIMEOUT } from 'panel/helpers/constants';
|
||||
import { validateMinValue, validateUpstreams } from 'panel/helpers/validators';
|
||||
import { validateMinValue, validateMaxValue, validateUpstreams } from 'panel/helpers/validators';
|
||||
import theme from 'panel/lib/theme';
|
||||
|
||||
import { Examples } from '../Examples';
|
||||
|
|
@ -124,7 +124,9 @@ export const Form = (props: FormProps) => {
|
|||
};
|
||||
|
||||
const validateUpstreamTimeout = () => {
|
||||
const err = validateMinValue(upstreamTimeout(), UPSTREAM_TIMEOUT.MIN);
|
||||
const err =
|
||||
validateMinValue(upstreamTimeout(), UPSTREAM_TIMEOUT.MIN) ||
|
||||
validateMaxValue(upstreamTimeout(), UPSTREAM_TIMEOUT.MAX);
|
||||
setUpstreamTimeoutError(err || '');
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -153,7 +153,6 @@
|
|||
.cellNameLabel {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding-top: 8px;
|
||||
text-align: left;
|
||||
word-break: break-word;
|
||||
overflow: hidden;
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ export const RewritesTable = (props: Props) => {
|
|||
},
|
||||
accessor: 'enabled',
|
||||
sortable: false,
|
||||
fitContent: true,
|
||||
width: 64,
|
||||
className: s.cellNameToggleOuter,
|
||||
render: (value: boolean, row: Rewrite) => {
|
||||
const { domain, enabled } = row;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { createSignal, createMemo, createEffect, on, onCleanup, Show } from 'solid-js';
|
||||
import { createSignal, createMemo, createEffect, on, onCleanup, Show, untrack } from 'solid-js';
|
||||
import cn from 'clsx';
|
||||
|
||||
import intl from 'panel/common/intl';
|
||||
|
|
@ -105,7 +105,7 @@ const REASON_OPTIONS = [
|
|||
];
|
||||
|
||||
export const Header = (props: Props) => {
|
||||
const [searchValue, setSearchValue] = createSignal(props.currentSearch);
|
||||
const [searchValue, setSearchValue] = createSignal(untrack(() => props.currentSearch));
|
||||
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
|
|
|
|||
|
|
@ -594,7 +594,7 @@ export const validateMacNotDuplicate =
|
|||
(existingLeases: LeaseEntry[], editMac?: string): ((value?: string) => ValidationResult) =>
|
||||
(value) => {
|
||||
if (value && value !== editMac && existingLeases.some((lease) => lease.mac === value)) {
|
||||
return intl.getMessage('form_error_mac_already_added');
|
||||
return intl.getMessage('dhcp_mac_address_already_added');
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -147,6 +147,11 @@ export const computeExistingClientIds = (): string[] =>
|
|||
.filter((c: Client) => state.mode !== 'edit' || c.name !== state.originalName)
|
||||
.flatMap((c: Client) => c.ids);
|
||||
|
||||
export const computeExistingClientNames = (): string[] =>
|
||||
(dashboardState.clients || [])
|
||||
.filter((c: Client) => state.mode !== 'edit' || c.name !== state.originalName)
|
||||
.map((c: Client) => c.name);
|
||||
|
||||
export const saveClient = async (): Promise<boolean> => {
|
||||
const errors: Record<string, string | string[]> = {};
|
||||
|
||||
|
|
@ -154,6 +159,13 @@ export const saveClient = async (): Promise<boolean> => {
|
|||
errors.name = intl.getMessage('form_error_required');
|
||||
}
|
||||
|
||||
if (!errors.name) {
|
||||
const existingClientNames = computeExistingClientNames();
|
||||
if (existingClientNames.includes(state.name.trim())) {
|
||||
errors.name = intl.getMessage('client_name_already_exists');
|
||||
}
|
||||
}
|
||||
|
||||
const existingClientIds = computeExistingClientIds();
|
||||
|
||||
const idErrors = state.ids.map((id: string, index: number) => {
|
||||
|
|
|
|||
|
|
@ -290,15 +290,15 @@ export const removeStaticLease = async (lease: Lease) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const updateStaticLease = async (config: { target: Lease; update: Lease }) => {
|
||||
export const updateStaticLease = async (lease: Lease) => {
|
||||
setState('processingUpdating', true);
|
||||
try {
|
||||
await apiClient.updateStaticLease(config);
|
||||
await apiClient.updateStaticLease(lease);
|
||||
setState('processingUpdating', false);
|
||||
toggleLeaseModal();
|
||||
addSuccessToast(
|
||||
intl.getMessage('dhcp_lease_updated', {
|
||||
key: config.update.hostname || config.update.ip,
|
||||
key: lease.hostname || lease.ip,
|
||||
}),
|
||||
);
|
||||
await getDhcpStatus();
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ export const blockDomain = async (domain: string): Promise<boolean> => {
|
|||
|
||||
addSuccessToast(
|
||||
createUndoToast(
|
||||
intl.getMessage('user_rules_rule_added_to_custom_filtering_rules'),
|
||||
intl.getMessage('user_rules_rule_added', { rule }),
|
||||
intl.getMessage('notify_undo'),
|
||||
async () => {
|
||||
const didUndo = await setRules(previousRules);
|
||||
|
|
@ -137,7 +137,7 @@ export const unblockDomain = async (domain: string): Promise<boolean> => {
|
|||
|
||||
addSuccessToast(
|
||||
createUndoToast(
|
||||
intl.getMessage('user_rules_rule_added_to_custom_filtering_rules'),
|
||||
intl.getMessage('user_rules_rule_added', { rule: desiredRule }),
|
||||
intl.getMessage('notify_undo'),
|
||||
async () => {
|
||||
const didUndo = await setRules(previousRules);
|
||||
|
|
@ -225,7 +225,7 @@ export const toggleBlocking = async (
|
|||
|
||||
addSuccessToast(
|
||||
createUndoToast(
|
||||
intl.getMessage('user_rules_rule_added_to_custom_filtering_rules'),
|
||||
intl.getMessage('user_rules_rule_added', { rule: desiredRule }),
|
||||
intl.getMessage('notify_undo'),
|
||||
async () => {
|
||||
const didUndo = await setRules(previousRules);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue