diff --git a/client/src/__locales/de.json b/client/src/__locales/de.json
index 2a9784ad..72f7989f 100644
--- a/client/src/__locales/de.json
+++ b/client/src/__locales/de.json
@@ -45,7 +45,7 @@
"dhcp_warning": "Wenn Sie den DHCP-Server trotzdem aktivieren möchten, stellen Sie sicher, dass sich in Ihrem Netzwerk kein anderer aktiver DHCP-Server befindet. Andernfalls kann es bei angeschlossenen Geräten zu einem Ausfall des Internets kommen!",
"dhcp_error": "Es konnte nicht ermittelt werden, ob es einen anderen DHCP-Server im Netzwerk gibt.",
"dhcp_static_ip_error": "Um den DHCP-Server nutzen zu können, muss eine statische IP-Adresse festgelegt werden. Es konnte nicht ermittelt werden, ob diese Netzwerkschnittstelle mit statischer IP-Adresse konfiguriert ist. Bitte legen Sie eine statische IP-Adresse manuell fest.",
- "dhcp_dynamic_ip_found": "Ihr System verwendet die dynamische Konfiguration der IP-Adresse für die Schnittstelle <0>{{interfaceName}}0>. Um den DHCP-Server nutzen zu können, muss eine statische IP-Adresse festgelegt werden. Ihre aktuelle IP-Adresse ist <0>{{ipAddress}}}0>. Diese IP-Adresse wird automatisch als statisch festgelegt, sobald Sie auf die Schaltfläche „DHCP aktivieren” klicken.",
+ "dhcp_dynamic_ip_found": "Ihr System verwendet die dynamische Konfiguration der IP-Adresse für die Schnittstelle <0>{{interfaceName}}0>. Um den DHCP-Server nutzen zu können, muss eine statische IP-Adresse festgelegt werden. Ihre aktuelle IP-Adresse ist <0>{{ipAddress}}0>. Diese IP-Adresse wird automatisch als statisch festgelegt, sobald Sie auf die Schaltfläche „DHCP aktivieren” klicken.",
"dhcp_lease_added": "Statischer Lease „{{key}}” erfolgreich hinzugefügt",
"dhcp_lease_deleted": "Statischer Lease „{{key}}” erfolgreich entfernt",
"dhcp_new_static_lease": "Neuer statischer Lease",
@@ -99,7 +99,7 @@
"no_clients_found": "Keine Clients gefunden",
"general_statistics": "Allgemeine Statistiken",
"number_of_dns_query_days": "Anzahl der in den letzten {{count}} Tagen verarbeiteten DNS-Anfragen",
- "number_of_dns_query_days_plural": "Anzahl der DNS-Abfragen, die in den letzten {{count}}} Tagen verarbeitet wurden",
+ "number_of_dns_query_days_plural": "Anzahl der DNS-Abfragen, die in den letzten {{count}} Tagen verarbeitet wurden",
"number_of_dns_query_24_hours": "Anzahl der in den letzten 24 Stunden durchgeführten DNS-Anfragen",
"number_of_dns_query_blocked_24_hours": "Anzahl der durch Werbefilter und Host-Blocklisten geblockten DNS-Anfragen",
"number_of_dns_query_blocked_24_hours_by_sec": "Anzahl der durch das AdGuard-Modul für Internet-Sicherheit blockierten DNS-Anfragen",
diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json
index e8e984e2..6cce0d91 100644
--- a/client/src/__locales/en.json
+++ b/client/src/__locales/en.json
@@ -194,6 +194,10 @@
"dns_test_not_ok_toast": "Server \"{{key}}\": could not be used, please check that you've written it correctly",
"unblock": "Unblock",
"block": "Block",
+ "disallow_this_client": "Disallow this client",
+ "allow_this_client": "Allow this client",
+ "block_for_this_client_only": "Block for this client only",
+ "unblock_for_this_client_only": "Unblock for this client only",
"time_table_header": "Time",
"date": "Date",
"domain_name_table_header": "Domain name",
@@ -569,5 +573,6 @@
"setup_config_to_enable_dhcp_server": "Setup config to enable DHCP server",
"original_response": "Original response",
"click_to_view_queries": "Click to view queries",
- "port_53_faq_link": "Port 53 is often occupied by \"DNSStubListener\" or \"systemd-resolved\" services. Please read <0>this instruction0> on how to resolve this."
+ "port_53_faq_link": "Port 53 is often occupied by \"DNSStubListener\" or \"systemd-resolved\" services. Please read <0>this instruction0> on how to resolve this.",
+ "adg_will_drop_dns_queries": "AdGuard Home will be dropping all DNS queries from this client."
}
diff --git a/client/src/actions/index.js b/client/src/actions/index.js
index ff512883..d4018bb0 100644
--- a/client/src/actions/index.js
+++ b/client/src/actions/index.js
@@ -545,15 +545,17 @@ export const removeStaticLease = (config) => async (dispatch) => {
export const removeToast = createAction('REMOVE_TOAST');
-export const toggleBlocking = (type, domain) => async (dispatch, getState) => {
+export const toggleBlocking = (
+ type, domain, baseRule, baseUnblocking,
+) => async (dispatch, getState) => {
+ const baseBlockingRule = baseRule || `||${domain}^$important`;
+ const baseUnblockingRule = baseUnblocking || `@@${baseBlockingRule}`;
const { userRules } = getState().filtering;
const lineEnding = !endsWith(userRules, '\n') ? '\n' : '';
- const baseRule = `||${domain}^$important`;
- const baseUnblocking = `@@${baseRule}`;
- const blockingRule = type === BLOCK_ACTIONS.BLOCK ? baseUnblocking : baseRule;
- const unblockingRule = type === BLOCK_ACTIONS.BLOCK ? baseRule : baseUnblocking;
+ const blockingRule = type === BLOCK_ACTIONS.BLOCK ? baseUnblockingRule : baseBlockingRule;
+ const unblockingRule = type === BLOCK_ACTIONS.BLOCK ? baseBlockingRule : baseUnblockingRule;
const preparedBlockingRule = new RegExp(`(^|\n)${escapeRegExp(blockingRule)}($|\n)`);
const preparedUnblockingRule = new RegExp(`(^|\n)${escapeRegExp(unblockingRule)}($|\n)`);
@@ -576,3 +578,10 @@ export const toggleBlocking = (type, domain) => async (dispatch, getState) => {
dispatch(getFilteringStatus());
};
+
+export const toggleBlockingForClient = (type, domain, client) => {
+ const baseRule = `||${domain}^$client='${client.replace(/'/g, '/\'')}'`;
+ const baseUnblocking = `@@${baseRule}`;
+
+ return toggleBlocking(type, domain, baseRule, baseUnblocking);
+};
diff --git a/client/src/components/App/index.css b/client/src/components/App/index.css
index 091a6612..e2b0304d 100644
--- a/client/src/components/App/index.css
+++ b/client/src/components/App/index.css
@@ -66,3 +66,12 @@ body {
.select--no-warning {
margin-bottom: 1.375rem;
}
+
+.button-action {
+ visibility: hidden;
+}
+
+.logs__row:hover .button-action,
+.button-action--active {
+ visibility: visible;
+}
diff --git a/client/src/components/Dashboard/Clients.js b/client/src/components/Dashboard/Clients.js
index 24b278f4..3c163035 100644
--- a/client/src/components/Dashboard/Clients.js
+++ b/client/src/components/Dashboard/Clients.js
@@ -51,15 +51,16 @@ const renderBlockingButton = (ip) => {
const type = isNotFound ? BLOCK_ACTIONS.BLOCK : BLOCK_ACTIONS.UNBLOCK;
const text = type;
- const className = classNames('btn btn-sm', {
- 'btn-outline-danger': isNotFound,
- 'btn-outline-secondary': !isNotFound,
+ const buttonClass = classNames('button-action button-action--main', {
+ 'button-action--unblock': !isNotFound,
});
const toggleClientStatus = (type, ip) => {
- const confirmMessage = type === BLOCK_ACTIONS.BLOCK ? 'client_confirm_block' : 'client_confirm_unblock';
+ const confirmMessage = type === BLOCK_ACTIONS.BLOCK
+ ? `${t('adg_will_drop_dns_queries')} ${t('client_confirm_block', { ip })}`
+ : t('client_confirm_unblock', { ip });
- if (window.confirm(t(confirmMessage, { ip }))) {
+ if (window.confirm(confirmMessage)) {
dispatch(toggleClientBlock(type, ip));
}
};
@@ -69,7 +70,7 @@ const renderBlockingButton = (ip) => {
return