From 49646cf706dac1c2998d91f4a6f109b5026dabdd Mon Sep 17 00:00:00 2001 From: Andrey Meshkov Date: Mon, 6 Jul 2020 19:58:44 +0300 Subject: [PATCH] + client: Add choosing filter lists Fix #1325 Squashed commit of the following: commit d8f7de72226855a961051e09b4b78f4dd71baadd Merge: f9bbe861 36f3218b Author: Andrey Meshkov Date: Mon Jul 6 19:34:53 2020 +0300 Merge branch 'master' into feature/1325 commit f9bbe861c9dbd631b5708f8eb073270b83a3f70f Merge: 99710fef 4f8138bd Author: Andrey Meshkov Date: Mon Jul 6 19:33:53 2020 +0300 Merge branch 'master' into feature/1325 commit 99710fef0825966b224e4a30a979e4d45f929af1 Merge: 8329326d a5380ead Author: ArtemBaskal Date: Mon Jul 6 18:04:32 2020 +0300 Merge branch 'feature/1325' of ssh://bit.adguard.com:7999/dns/adguard-home into feature/1325 commit 8329326d6470dfcf2cdc4479e0290f7cc56ddca4 Author: ArtemBaskal Date: Mon Jul 6 18:03:56 2020 +0300 Update locales, add title for select modal commit a5380ead56d15eba3f36c38f8fc0eedc89c2c57a Author: Andrey Meshkov Date: Mon Jul 6 17:26:37 2020 +0300 Update readme commit dfe6e254d909ee6994cacef53d417bb073dfd802 Author: ArtemBaskal Date: Mon Jul 6 13:44:19 2020 +0300 Change info icon width commit 06120cf3da9065fc9cc3a2864b976563d4cfe06a Author: ArtemBaskal Date: Mon Jul 6 13:38:58 2020 +0300 Review changes commit ae3c6cacc5610a0f95bec2f6ef8a63e90041e4dd Merge: dd56a3bb 73c5d9ea Author: ArtemBaskal Date: Mon Jul 6 12:01:57 2020 +0300 Merge branch 'master' into feature/1325 commit dd56a3bbb851687823242fa653cc3bb63dedf5e4 Author: Andrey Meshkov Date: Fri Jul 3 15:52:01 2020 +0300 Added blocklists commit f08f0eb0cdd8cd488d3a8f1182854b72775cf06e Merge: 854d4f88 21dfb5ff Author: Andrey Meshkov Date: Fri Jul 3 14:06:19 2020 +0300 Merge branch 'master' into feature/1325 commit 854d4f88017a33dc7f788835dc98591cec9b213f Merge: 23946266 2c47053c Author: ArtemBaskal Date: Mon Jun 22 14:09:31 2020 +0300 Merge branch 'master' into feature/1325 commit 23946266d4913479bcecfcb7702a096983d20685 Author: ArtemBaskal Date: Tue May 26 19:00:26 2020 +0300 Math filters by url commit 661e0482f01ffea0d0f5aa81b3b253143d0ca112 Author: ArtemBaskal Date: Mon May 25 21:07:21 2020 +0300 Change data format commit ac4ff483b6b06ec0be49a41b5ddd3329f4ae2bbb Author: ArtemBaskal Date: Thu May 14 19:52:45 2020 +0300 + client: Add choosing filter lists --- README.md | 12 +- client/src/__locales/cs.json | 2 +- client/src/__locales/de.json | 2 +- client/src/__locales/en.json | 15 +- client/src/__locales/ja.json | 2 +- client/src/__locales/ko.json | 2 +- client/src/__locales/nl.json | 42 +++++ client/src/__locales/no.json | 2 +- client/src/__locales/pl.json | 2 +- client/src/__locales/ro.json | 58 +++---- client/src/__locales/ru.json | 2 +- client/src/__locales/sr-cs.json | 49 +++++- client/src/__locales/zh-cn.json | 2 +- client/src/actions/filtering.js | 18 +- client/src/components/App/index.css | 9 + client/src/components/Filters/DnsAllowlist.js | 11 +- client/src/components/Filters/DnsBlocklist.js | 57 +++++-- client/src/components/Filters/Form.js | 148 ++++++++++++++--- client/src/components/Filters/Modal.js | 87 +++++++--- client/src/components/Filters/Table.js | 2 +- client/src/components/Header/Header.css | 4 + .../Settings/Clients/ClientsTable.js | 6 +- .../src/components/Settings/Clients/Modal.js | 2 +- client/src/components/ui/Icons.js | 9 + client/src/helpers/constants.js | 7 +- client/src/helpers/filters/filters.json | 154 ++++++++++++++++++ client/src/helpers/form.js | 24 +-- client/src/helpers/helpers.js | 15 +- home/filter.go | 4 +- 29 files changed, 617 insertions(+), 132 deletions(-) create mode 100644 client/src/helpers/filters/filters.json diff --git a/README.md b/README.md index 73db929b6ed..83aa32fb888 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ It operates as a DNS server that re-routes tracking domains to a "black hole," t * [Test unstable versions](#test-unstable-versions) * [Reporting issues](#reporting-issues) * [Help with translations](#translate) + * [Other](#help-other) * [Projects that use AdGuardHome](#uses) * [Acknowledgments](#acknowledgments) @@ -224,6 +225,15 @@ If you want to help with AdGuard Home translations, please learn more about tran Here is a link to AdGuard Home project: https://crowdin.com/project/adguard-applications/en#/adguard-home + +### Other + +Here's what you can also do to contribute: + +1. [Look for issues](https://github.com/AdguardTeam/AdGuardHome/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22+) marked as "help wanted". +2. Actualize the list of *Blocked services*. It it can be found in [dnsfilter/blocked_services.go](https://github.com/AdguardTeam/AdGuardHome/blob/master/dnsfilter/blocked_services.go). +3. Actualize the list of known *trackers*. It it can be found in [client/src/helpers/trackers/adguard.json](https://github.com/AdguardTeam/AdGuardHome/blob/master/client/src/helpers/trackers/adguard.json). +4. Actualize the list of vetted *blocklists*. It it can be found in [client/src/helpers/filters/filters.json](https://github.com/AdguardTeam/AdGuardHome/blob/master/client/src/helpers/filters/filters.json). ## Projects that use AdGuardHome @@ -255,5 +265,3 @@ This software wouldn't have been possible without: You might have seen that [CoreDNS](https://coredns.io) was mentioned here before — we've stopped using it in AdGuardHome. While we still use it on our servers for [AdGuard DNS](https://adguard.com/adguard-dns/overview.html) service, it seemed like an overkill for Home as it impeded with Home features that we plan to implement. For a full list of all node.js packages in use, please take a look at [client/package.json](https://github.com/AdguardTeam/AdGuardHome/blob/master/client/package.json) file. - -For info on which exact domains that are blocked by the *Blocked services* function, it can be found at [dnsfilter/blocked_services.go](https://github.com/AdguardTeam/AdGuardHome/blob/master/dnsfilter/blocked_services.go) diff --git a/client/src/__locales/cs.json b/client/src/__locales/cs.json index 2f02414b46f..02101213384 100644 --- a/client/src/__locales/cs.json +++ b/client/src/__locales/cs.json @@ -68,7 +68,7 @@ "filter": "Filtr", "query_log": "Protokol dotazů", "compact": "Kompaktní", - "nothing_found": "Nic nebylo nalezeno", + "nothing_found": "Nic nenalezeno", "faq": "FAQ", "version": "Verze", "address": "Adresa", diff --git a/client/src/__locales/de.json b/client/src/__locales/de.json index 233ca87a04c..702be516fdf 100644 --- a/client/src/__locales/de.json +++ b/client/src/__locales/de.json @@ -530,4 +530,4 @@ "safe_search": "Sichere Suche", "blocklist": "Sperrliste", "milliseconds_abbreviation": "ms" -} \ No newline at end of file +} diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index 34ff7ae6efd..29d250b5df9 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -162,6 +162,8 @@ "new_allowlist": "New allowlist", "edit_blocklist": "Edit blocklist", "edit_allowlist": "Edit allowlist", + "choose_blocklist": "Choose blocklists", + "choose_allowlist": "Choose allowlists", "enter_valid_blocklist": "Enter a valid URL to the blocklist.", "enter_valid_allowlist": "Enter a valid URL to the allowlist.", "form_error_url_format": "Invalid URL format", @@ -447,6 +449,7 @@ "domain": "Domain", "answer": "Answer", "filter_added_successfully": "The list has been successfully added", + "filter_removed_successfully": "The list has been successfully removed", "filter_updated": "The list has been successfully updated", "statistics_configuration": "Statistics configuration", "statistics_retention": "Statistics retention", @@ -500,6 +503,8 @@ "check": "Check", "form_enter_host": "Enter a host name", "filtered_custom_rules": "Filtered by Custom filtering rules", + "choose_from_list": "Choose from the list", + "add_custom_list": "Add a custom list", "host_whitelisted": "The host is whitelisted", "check_ip": "IP addresses: {{ip}}", "check_cname": "CNAME: {{cname}}", @@ -547,5 +552,13 @@ "cache_ttl_min_override_desc": "Override TTL value (minimum) received from upstream server. This value can't larger than 3600 (1 hour)", "cache_ttl_max_override_desc": "Override TTL value (maximum) received from upstream server", "min_exceeds_max_value": "Minimum value exceeds maximum value", - "value_not_larger_than": "Value can't be larger than {{maximum}}" + "value_not_larger_than": "Value can't be larger than {{maximum}}", + "filter_category_general": "General", + "filter_category_security": "Security", + "filter_category_regional": "Regional", + "filter_category_other": "Other", + "filter_category_general_desc": "Lists that block tracking and advertising on most of the devices", + "filter_category_security_desc": "Lists that specialize on blocking malware, phishing or scam domains", + "filter_category_regional_desc": "Lists that focus on regional ads and tracking servers", + "filter_category_other_desc": "Other blocklists" } diff --git a/client/src/__locales/ja.json b/client/src/__locales/ja.json index 8a3cc3b6195..1f287855762 100644 --- a/client/src/__locales/ja.json +++ b/client/src/__locales/ja.json @@ -530,4 +530,4 @@ "safe_search": "セーフサーチ", "blocklist": "ブロックリスト", "milliseconds_abbreviation": "ms" -} \ No newline at end of file +} diff --git a/client/src/__locales/ko.json b/client/src/__locales/ko.json index 9e363e131db..82dde576d57 100644 --- a/client/src/__locales/ko.json +++ b/client/src/__locales/ko.json @@ -530,4 +530,4 @@ "safe_search": "세이프 서치", "blocklist": "차단 목록", "milliseconds_abbreviation": "ms" -} \ No newline at end of file +} diff --git a/client/src/__locales/nl.json b/client/src/__locales/nl.json index 05b3f7d443f..5d396c29216 100644 --- a/client/src/__locales/nl.json +++ b/client/src/__locales/nl.json @@ -28,6 +28,7 @@ "form_error_mac_format": "Ongeldig MAC formaat.", "form_error_client_id_format": "Opmaak cliënt-ID is ongeldig", "form_error_positive": "Moet groter zijn dan 0", + "form_error_negative": "Moet 0 of hoger dan 0 zijn", "dhcp_form_gateway_input": "Gateway IP", "dhcp_form_subnet_input": "Subnet mask", "dhcp_form_range_title": "Bereik van IP adressen", @@ -221,11 +222,29 @@ "query_log_retention_confirm": "Weet u zeker dat u de bewaartermijn van het query logboek wilt wijzigen? Als u de intervalwaarde verlaagt, gaan sommige gegevens verloren", "anonymize_client_ip": "Cliënt IP anonimiseren", "anonymize_client_ip_desc": "Het volledige IP-adres van de cliënt niet opnemen in log- en statistiekbestanden", + "dns_config": "DNS server configuratie", + "blocking_mode": "Blocking modus", "default": "Standaard", + "nxdomain": "NXDOMAIN", + "null_ip": "Nul IP", "custom_ip": "Aangepast IP", + "blocking_ipv4": "Blokkeren IP4", + "blocking_ipv6": "Blokkeren IP6", "dns_over_https": "DNS-via-HTTPS", "dns_over_tls": "DNS-via-TLS", "plain_dns": "Gewone DNS", + "form_enter_rate_limit": "Voer ratio limiet in", + "rate_limit": "Ratio limiet", + "edns_enable": "Zet EDNS client subnet aan", + "edns_cs_desc": "Indien ingeschakeld stuurt AdGuard Home het subnet van de client naar de DNS-servers.", + "rate_limit_desc": "Het aantal verzoeken per seconde die een enkele client mag doen (0: onbeperkt)", + "blocking_ipv4_desc": "IP-adres dat moet worden teruggegeven voor een geblokkeerd A-verzoek", + "blocking_ipv6_desc": "IP-adres dat moet worden teruggegeven voor een geblokkeerd A-verzoek", + "blocking_mode_default": "Standaard: Reageer met NXDOMAIN wanneer geblokkeerd door een Adblock-type regel; reageer met het IP-adres dat is opgegeven in de regel wanneer het wordt geblokkeerd door een /etc/hosts type regel", + "blocking_mode_nxdomain": "NXDOMAIN: Reageer met NXDOMAIN code", + "blocking_mode_null_ip": "Nul IP: Reageer met een nul IP address (0.0.0.0 voor A; :: voor AAAA)", + "blocking_mode_custom_ip": "Aangepast IP: Reageer met een handmatige ingesteld IP adres", + "upstream_dns_client_desc": "Indien je dit veld leeglaat zal AdGuard Home de servers welke zijn ingesteld in de <0>DNS instellingen gebruiken.", "tracker_source": "Bron volger", "source_label": "Bron", "found_in_known_domain_db": "Gevonden in de bekende domeingegevensbank.", @@ -460,20 +479,43 @@ "domain_desc": "Voer de domeinnaam of wildcard in die herschreven moet worden.", "example_rewrite_domain": "herschrijf reacties uitsluitend voor deze domeinnaam.", "example_rewrite_wildcard": "herschrijf reacties voor alle subdomeinen van <0>example.org.", + "disable_ipv6": "Zet IPv6 uit", + "disable_ipv6_desc": "Als deze functie is ingeschakeld, worden alle DNS-query's voor IPv6-adressen (type AAAA) verwijderd.", "fastest_addr": "Snelste IP adres", "fastest_addr_desc": "Alle DNS servers bevragen en het snelste IP adres terugkoppelen. Dit zal de DNS verzoeken vertragen omdat we moeten wachten op de antwoorden van alles DNS servers, maar verbetert wel de connectiviteit.", + "autofix_warning_text": "Als je op \"Repareren\" klikt, configureert AdGuard Home uw systeem om de AdGuard Home DNS-server te gebruiken.", + "autofix_warning_list": "De volgende taken worden uitgevoerd: <0> Deactiveren van Systeem DNSStubListener <0> DNS-serveradres instellen op 127.0.0.1 <0> Symbolisch koppelingsdoel van /etc/resolv.conf vervangen door /run/systemd/resolve/resolv.conf <0> Stop DNSStubListener (herlaad systemd-resolved service) ", + "autofix_warning_result": "Als gevolg hiervan worden alle DNS-verzoeken van je systeem standaard door AdGuard Home verwerkt.", "tags_title": "Labels", + "tags_desc": "Je kunt tags selecteren die overeenkomen met de client. Tags kunnen worden opgenomen in de filterregels en je kunt ze dan nauwkeuriger toepassen. <0> Meer informatie ", + "form_select_tags": "Kies client tags", + "check_title": "Controleer de filtering", + "check_desc": "Controleer of de hostnaam wordt gefilterd", "check": "Controleren", "form_enter_host": "Voer een hostnaam in", + "filtered_custom_rules": "Gefilterd door aangepaste filterregels", "host_whitelisted": "De host staat op de toestemmingslijst", "check_ip": "IP-adressen: {{ip}}", "check_cname": "CNAME: {{cname}}", "check_reason": "Reden: {{reason}}", "check_rule": "Regel: {{rule}}", "check_service": "Servicenaam: {{service}}", + "check_not_found": "Niet in je lijst met filters gevonden", + "client_confirm_block": "Weet je zeker dat je client \"{{ip}}\" wil blokkeren?", + "client_confirm_unblock": "Weet je zeker dat je client \"{{ip}}\" niet meer wil blokkeren?", + "client_blocked": "Client \"{{ip}}\" wordt nu geblokkeerd", + "client_unblocked": "Client \"{{ip}}\" wordt niet meer geblokkeerd", + "static_ip": "Statisch IP-adres", + "static_ip_desc": "AdGuard Home is een server en heeft daarom een statisch IP-adres nodig om goed te kunnen functioneren, anders kan uw router op een bepaald moment een ander IP-adres aan dit apparaat toewijzen.", + "set_static_ip": "Stel een statisch IP-adres in", + "install_static_ok": "Goed nieuws! Het statische IP-adres was al geconfigureerd", + "install_static_error": "AdGuard Home kan dit niet automatisch configureren op deze netwerkinterface. Zoek een instructie om dit handmatig te doen.", + "install_static_configure": "We hebben vastgesteld dat er een dynamisch IP-adres wordt gebruikt - <0> {{ip}} . Wil je dit als je statische adres gebruiken?", + "confirm_static_ip": "AdGuard Home configureert {{ip}} als jouw statische IP-adres. Wil je doorgaan?", "list_updated": "{{count}} lijst geüpdatet", "list_updated_plural": "{{count}} lijsten geüpdatet", "dnssec_enable": "DNSSEC inschakelen", + "dnssec_enable_desc": "Zet de DNSSEC-vlag aan bij uitgaande DNS-query's en controleer het resultaat (DNSSEC-compatibele resolver is vereist)", "validated_with_dnssec": "Gevalideerd met DNSSEC", "show_all_responses": "Alle reacties", "show_blocked_responses": "Geblokkeerd", diff --git a/client/src/__locales/no.json b/client/src/__locales/no.json index 319cb917256..6186fc9b3fd 100644 --- a/client/src/__locales/no.json +++ b/client/src/__locales/no.json @@ -492,4 +492,4 @@ "blocked_threats": "Blokkerte trusler", "allowed": "Unntak", "blocklist": "Blokkeringsliste" -} \ No newline at end of file +} diff --git a/client/src/__locales/pl.json b/client/src/__locales/pl.json index 1744d8dc3b2..b4876baa280 100644 --- a/client/src/__locales/pl.json +++ b/client/src/__locales/pl.json @@ -527,4 +527,4 @@ "safe_search": "Bezpieczne wyszukiwanie", "blocklist": "Lista zablokowanych", "milliseconds_abbreviation": "ms" -} \ No newline at end of file +} diff --git a/client/src/__locales/ro.json b/client/src/__locales/ro.json index 39d62d6c986..0442f731bcb 100644 --- a/client/src/__locales/ro.json +++ b/client/src/__locales/ro.json @@ -55,7 +55,7 @@ "country": "Țara", "city": "Oraș", "delete_confirm": "Sunteți sigur că doriți să ștergeți \"{{key}}\"?", - "form_enter_hostname": "Intrați hostname", + "form_enter_hostname": "Introduceți hostname", "error_details": "Detalii eroare", "response_details": "Detalii răspuns", "request_details": "Detalii solicitare", @@ -68,7 +68,7 @@ "filter": "Filtru", "query_log": "Jurnal interogări", "compact": "Compact", - "nothing_found": "Nu s-a găsit nimic", + "nothing_found": "Nimic găsit", "faq": "FAQ", "version": "Versiune", "address": "Adresă", @@ -155,19 +155,19 @@ "add_blocklist": "Adăugați blocaj", "add_allowlist": "Adăugați autorizare", "cancel_btn": "Anulare", - "enter_name_hint": "Intrați numele", - "enter_url_or_path_hint": "Intrați un URL sau o cale absolută a listei", + "enter_name_hint": "Introduceți numele", + "enter_url_or_path_hint": "Introduceți un URL sau o cale absolută a listei", "check_updates_btn": "Caută actualizări", "new_blocklist": "Nouă blocare", "new_allowlist": "Nouă autorizare", "edit_blocklist": "Editare blocare", "edit_allowlist": "Editare autorizare", - "enter_valid_blocklist": "Intrați un URL valid pentru blocare.", - "enter_valid_allowlist": "Intrați un URL valid pentru autorizare.", + "enter_valid_blocklist": "Introduceți un URL valid pentru blocare.", + "enter_valid_allowlist": "Introduceți un URL valid pentru autorizare.", "form_error_url_format": "Format URL invalid", "form_error_url_or_path_format": "Invalid URL sau o cale absolută a listei", "custom_filter_rules": "Reguli de filtrare personalizate", - "custom_filter_rules_hint": "Intrați o regulă pe linie. Puteți utiliza reguli de blocare sau sintaxa de fișiere hosts.", + "custom_filter_rules_hint": "Introduceți o regulă pe linie. Puteți utiliza reguli de blocare sau sintaxa de fișiere hosts.", "examples_title": "Exemple", "example_meaning_filter_block": "blochează accesul la domeniul exemplu.org și la toate subdomeniile sale", "example_meaning_filter_whitelist": "deblochează accesul la domeniul exemplu.org și la toate subdomeniile sale", @@ -233,7 +233,7 @@ "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", "plain_dns": "DNS simplu", - "form_enter_rate_limit": "Intrați limita ratei", + "form_enter_rate_limit": "Introduceți limita ratei", "rate_limit": "Limita ratei", "edns_enable": "Activați clientul subnet EDNS", "edns_cs_desc": "Dacă este activat, AdGuard Home va trimite subnet-ul clienților către serverele DNS.", @@ -259,7 +259,7 @@ "install_settings_listen": "Interfață de ascultare", "install_settings_port": "Port", "install_settings_interface_link": "Interfața dvs. de administrare AdGuard Home va fi disponibilă pe următoarele adrese:", - "form_error_port": "Intrați un port valid", + "form_error_port": "Introduceți un port valid", "install_settings_dns": "Server DNS", "install_settings_dns_desc": "Va trebui să configurați aparatele sau routerul pentru a utiliza serverul DNS pe următoarele adrese:", "install_settings_all_interfaces": "Toate interfețele", @@ -268,8 +268,8 @@ "install_auth_username": "Nume utilizator", "install_auth_password": "Parola", "install_auth_confirm": "Confirmați parola", - "install_auth_username_enter": "Intrați numele de utilizator", - "install_auth_password_enter": "Intrați parola", + "install_auth_username_enter": "Introduceți nume utilizator", + "install_auth_password_enter": "Introduceți parola", "install_step": "Etapa", "install_devices_title": "Configurați aparatele dvs", "install_devices_desc": "Pentru a începe să utilizați AdGuard Home, trebuie să configurați aparatele.", @@ -278,20 +278,20 @@ "install_devices_router": "Router", "install_devices_router_desc": "Această configurație va acoperi automat toate aparatele conectate la routerul de acasă și nu va trebui să le configurați manual pe fiecare.", "install_devices_address": "Serverul DNS AdGuard Home ascultă pe următoarele adrese", - "install_devices_router_list_1": "Deschideți preferințele pentru routerul dvs. De obicei, îl puteți accesa din browserul dvs. printr-o adresă URL (cum ar fi http://192.168.0.1/ sau http://192.168.1.1/). Vi se poate cere să intrați parola. Dacă nu v-o amintiți, puteți reseta adesea parola apăsând un buton de pe routerul propriu-zis. Unele routere necesită o aplicație specifică, care în acest caz ar trebui să fie deja instalată pe computerul/telefonul dvs.", + "install_devices_router_list_1": "Deschideți preferințele pentru routerul dvs. De obicei, îl puteți accesa din browserul dvs. printr-o adresă URL (cum ar fi http://192.168.0.1/ sau http://192.168.1.1/). Vi se poate cere să introduceți parola. Dacă nu v-o amintiți, puteți reseta adesea parola apăsând un buton de pe routerul propriu-zis. Unele routere necesită o aplicație specifică, care în acest caz ar trebui să fie deja instalată pe computerul/telefonul dvs.", "install_devices_router_list_2": "Găsiți setările DHCP/DNS. Căutați literele DNS lângă un câmp care să permită două sau trei seturi de numere, fiecare împărțit în patru grupuri de una până la trei cifre.", - "install_devices_router_list_3": "Intrați adresele serverului dvs. AdGuard Home aici.", + "install_devices_router_list_3": "Introduceți adresele serverului dvs. AdGuard Home aici.", "install_devices_router_list_4": "Unele routere nu permit setarea unui server DNS personalizat. În acest caz, vă poate ajuta dacă ați configura AdGuard Home ca <0>server DHCP. Dacă nu, trebuie căutat manualul modelului dvs. de router ca să aflați cum se pot personaliza serverele DNS.", "install_devices_windows_list_1": "Deschideți panoul de control prin meniul Start sau căutare Windows.", "install_devices_windows_list_2": "Accesați categoria \"Rețea și Internet\", apoi la \"Centrul de Rețea și Partajare\".", "install_devices_windows_list_3": "În partea stângă a ecranului găsiți \"Schimbare setări adaptor\" și clicați pe el.", "install_devices_windows_list_4": "Selectați conexiunea activă, faceți clic dreapta pe ea și alegeți \"Proprietăți\".", "install_devices_windows_list_5": "Găsiți Internet Protocol Versiunea 4 (TCP/IP) din listă, selectați-l și apoi clicați din nou pe Proprietăți.", - "install_devices_windows_list_6": "Alegeți Utilizați următoarele adrese de server DNS și intrați adresele de server AdGuard Home.", + "install_devices_windows_list_6": "Alegeți Utilizați următoarele adrese de server DNS și introduceți adresele de server AdGuard Home.", "install_devices_macos_list_1": "Clicați pe icoana Apple și accesați Preferințele Sistemului.", "install_devices_macos_list_2": "Clicați pe Network.", "install_devices_macos_list_3": "Selectați prima conexiune din listă și clicați pe Avansat.", - "install_devices_macos_list_4": "Selectați fila DNS și intrați adresele serverului dvs. AdGuard Home.", + "install_devices_macos_list_4": "Selectați fila DNS și introduceți adresele serverului dvs. AdGuard Home.", "install_devices_android_list_1": "Din ecranul principal al Meniului Android, tapați Setări.", "install_devices_android_list_2": "Tapați Wi-Fi din meniu. Ecranul cu toate rețelele disponibile va fi afișat (este imposibil să setați DNS personalizat pentru conexiunea mobilă).", "install_devices_android_list_3": "Apăsați lung pe rețeaua la care sunteți conectat și tapați Modificare Rețea.", @@ -300,7 +300,7 @@ "install_devices_ios_list_1": "Din ecranul de start, tapați Setări.", "install_devices_ios_list_2": "Alegeți Wi-Fi în meniul din stânga (este imposibil să configurați DNS pentru rețelele mobile).", "install_devices_ios_list_3": "Tapați numele rețelei active curente.", - "install_devices_ios_list_4": "În câmpul DNS, intrați adresele serverului dvs. AdGuard Home.", + "install_devices_ios_list_4": "În câmpul DNS, introduceți adresele serverului dvs. AdGuard Home.", "get_started": "Să începem", "next": "Următor", "open_dashboard": "Deschideți Tabloul de bord", @@ -309,8 +309,8 @@ "encryption_desc": "Suport de Criptare (HTTPS/TLS) pentru DNS și interfața web administrator", "encryption_config_saved": "Configurația de criptare salvată", "encryption_server": "Nume de server", - "encryption_server_enter": "Intrați numele domeniului", - "encryption_server_desc": "Pentru a utiliza HTTPS, trebuie intrat numele serverului care corespunde certificatului SSL.", + "encryption_server_enter": "Introduceți numele domeniului", + "encryption_server_desc": "Pentru a utiliza HTTPS, trebuie introdus numele serverului care corespunde certificatului SSL.", "encryption_redirect": "Redirecționați automat la HTTPS", "encryption_redirect_desc": "Dacă este bifat, AdGuard Home vă va redirecționa automat de la adrese HTTP la HTTPS.", "encryption_https": "Port HTTPS", @@ -365,11 +365,11 @@ "client_identifier": "Identificator", "ip_address": "Adresa IP", "client_identifier_desc": "Clienții pot fi identificați prin adresa IP, CIDR, adresa MAC. Vă rugăm să rețineți că utilizarea MAC ca identificator este posibilă numai dacă AdGuard Home este și un <0>server DHCP", - "form_enter_ip": "Intrați IP", - "form_enter_mac": "Intrați MAC", - "form_enter_id": "Intrați identificator", + "form_enter_ip": "Introduceți IP", + "form_enter_mac": "Introduceți MAC", + "form_enter_id": "Introduceți identificator", "form_add_id": "Adăugați identificator", - "form_client_name": "Intrați nume client", + "form_client_name": "Introduceți nume client", "name": "Nume", "client_global_settings": "Folosiți setări globale", "client_deleted": "Clientul \"{{key}}\" a fost șters cu succes", @@ -396,7 +396,7 @@ "setup_dns_privacy_1": "<0>DNS-over-TLS: Folosiți stringul <1>{{address}}.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS: Folosiți stringul <1>{{address}}.", "setup_dns_privacy_3": "<0>Rețineți că protocoalele DNS criptate sunt acceptate numai pe Android 9. Așadar, trebuie să instalați programe suplimentare pentru alte sisteme de operare.<0>Iată o listă de software pe care o puteți utiliza.", - "setup_dns_privacy_android_1": "Android 9 acceptă nativ DNS-over-TLS. Pentru a-l configura, accesați Setări → Rețea și internet → Advanced → Private DNS și intrați numele de domeniu acolo.", + "setup_dns_privacy_android_1": "Android 9 acceptă DNS-over-TLS nativ. Pentru a-l configura, accesați Setări → Rețea și internet → Advanced → Private DNS și introduceți numele de domeniu acolo.", "setup_dns_privacy_android_2": "<0>AdGuard pentru Android acceptă <1>DNS-over-HTTPS și <1>DNS-over-TLS.", "setup_dns_privacy_android_3": "<0>Intra adaugă <1>DNS-over-HTTPS suport pentru Android.", "setup_dns_privacy_ios_1": "<0>DNSCloak acceptă <1>DNS-over-HTTPS, dar pentru a-l configura pentru a utiliza propriul server, va trebui să generați un <2>DNS Stamp pentru aceasta.", @@ -417,8 +417,8 @@ "rewrite_applied": "Regula de rescriere s-a aplicat", "rewrite_hosts_applied": "Rescrisă de regula fișierului hosts", "dns_rewrites": "Rescrieri DNS", - "form_domain": "Intrați un nume de domeniu sau wildcard", - "form_answer": "Intrați adresa IP sau numele de domeniu", + "form_domain": "Introduceți un nume de domeniu sau wildcard", + "form_answer": "Introduceți adresa IP sau numele de domeniu", "form_error_domain_format": "Format de răspuns invalid", "form_error_answer_format": "Format de răspuns invalid", "configure": "Configurați", @@ -460,9 +460,9 @@ "filters_interval": "Interval de actualizare filtre", "disabled": "Dezactivat", "username_label": "Nume utilizator", - "username_placeholder": "Intrați numele de utilizator", + "username_placeholder": "Introduceți nume utilizator", "password_label": "Parola", - "password_placeholder": "Intrați parola", + "password_placeholder": "Introduceți parola", "sign_in": "Conectare", "sign_out": "Deconectare", "forgot_password": "Ați uitat parola?", @@ -476,7 +476,7 @@ "filtering_rules_learn_more": "<0>Aflați mai multe despre crearea propriilor liste hosts.", "blocked_by_response": "Blocat de CNAME sau IP ca răspuns", "try_again": "Încercați din nou", - "domain_desc": "Intrați un nume de domeniu sau wildcard care doriți să fie rescris.", + "domain_desc": "Introduceți un nume de domeniu sau wildcard care doriți să fie rescris.", "example_rewrite_domain": "rescrie răspunsuri numai pentru acest nume de domeniu.", "example_rewrite_wildcard": "rescrie răspunsuri pentru toate subdomeniile <0>exemplu.org.", "disable_ipv6": "Dezactivați IPv6", @@ -492,7 +492,7 @@ "check_title": "Verificați filtrarea", "check_desc": "Verificați dacă numele de host este filtrat", "check": "Verificați", - "form_enter_host": "Intrați un nume de host", + "form_enter_host": "Introduceți un nume de host", "filtered_custom_rules": "Filtrat prin reguli de filtrare personalizate", "host_whitelisted": "Numele de host este în lista albă", "check_ip": "Adrese IP: {{ip}}", diff --git a/client/src/__locales/ru.json b/client/src/__locales/ru.json index 2d24726152e..266bdfe00ce 100644 --- a/client/src/__locales/ru.json +++ b/client/src/__locales/ru.json @@ -530,4 +530,4 @@ "safe_search": "Безопасный поиск", "blocklist": "Черный список", "milliseconds_abbreviation": "мс" -} \ No newline at end of file +} diff --git a/client/src/__locales/sr-cs.json b/client/src/__locales/sr-cs.json index d472a4aedce..6f1fa07f040 100644 --- a/client/src/__locales/sr-cs.json +++ b/client/src/__locales/sr-cs.json @@ -2,6 +2,9 @@ "client_settings": "Postavke klijenta", "example_upstream_reserved": "možete odrediti DNS upstream <0>za određene domene", "upstream_parallel": "Koristite paralelne zahteve da ubrzate rešavanje istovremenim zahtevanjem svih servera", + "parallel_requests": "Paralelni zahtevi", + "load_balancing": "Load-balancing", + "load_balancing_desc": "Koristi jedan server. AdGuard Home će koristiti najnoviji nasumični algoritam da izabere server tako da će najbrži server biti češće korišćen.", "bootstrap_dns": "Bootstrap DNS serveri", "bootstrap_dns_desc": "Bootstrap DNS serveri se koriste da reše IP adrese od DoH/DoT razrešivača koje ste odredili kao upstream.", "check_dhcp_servers": "Proveri DHCP servere", @@ -36,6 +39,7 @@ "dhcp_interface_select": "Izaberite DHCP okruženje", "dhcp_hardware_address": "Adresa hardvera", "dhcp_ip_addresses": "IP adrese", + "ip": "IP", "dhcp_table_hostname": "Ime hosta", "dhcp_table_expires": "Ističe", "dhcp_warning": "Ako svakako želite da uključite DHCP server, uverite se da nema drugih aktivnih DHCP servera u vašoj mreži. U suprotnom, to može pokvariti Internet za povezane uređaje!", @@ -48,17 +52,27 @@ "dhcp_static_leases_not_found": "Nisu pronađena statička DHCP iznajmljivanja", "dhcp_add_static_lease": "Dodaj statičko iznajmljivanje", "dhcp_reset": "Jeste li sigurni da želite da resetujete DHCP konfiguraciju?", + "country": "Zemlja", + "city": "Grad", "delete_confirm": "Jeste li sigurni da želite da izbrišete \"{{key}}\"?", "form_enter_hostname": "Unesite ime hosta", "error_details": "Detalji greške", + "response_details": "Pojedinosti odgovora", + "request_details": "Pojedinosti zahteva", + "client_details": "Pojedinosti klijenta", + "details": "Detalji", "back": "Nazad", "dashboard": "Kontrolna tabla", "settings": "Postavke", "filters": "Filteri", + "filter": "Filter", "query_log": "Dnevnik zahteva", + "compact": "Kompaktno", + "nothing_found": "Ništa nije pronađeno", "faq": "ČPP", "version": "Verzija", "address": "Adresa", + "protocol": "Protokol", "on": "Uključeno", "off": "Isključeno", "copyright": "Autorska prava", @@ -131,8 +145,10 @@ "rules_count_table_header": "Broj pravila", "last_time_updated_table_header": "Poslednji put ažurirano", "actions_table_header": "Radnje", + "request_table_header": "Zahtev", "edit_table_action": "Izmeni", "delete_table_action": "Izbriši", + "elapsed": "Proteklo", "filters_and_hosts_hint": "AdGuard Home razume osnovna pravila blokiranja reklama i sintaksu hosts datoteke.", "no_blocklist_added": "Blok liste nisu dodate", "no_whitelist_added": "Liste dozvoljenih nisu dodate", @@ -140,6 +156,7 @@ "add_allowlist": "Dodaj listu dozvoljenih", "cancel_btn": "Otkaži", "enter_name_hint": "Unesite ime", + "enter_url_or_path_hint": "Unesite URL ili apsolutnu putanju liste", "check_updates_btn": "Proveri ažuriranja", "new_blocklist": "Nova blok lista", "new_allowlist": "Nova lista dozvoljenih", @@ -148,6 +165,7 @@ "enter_valid_blocklist": "Unesite važeći URL do blok liste.", "enter_valid_allowlist": "Unesite važeći URL do liste dozvoljenih.", "form_error_url_format": "Nevažeći format Url-a", + "form_error_url_or_path_format": "URL ili apsolutna putanja do liste nije valjana", "custom_filter_rules": "Prilagođena pravila filtriranja", "custom_filter_rules_hint": "Unesite jedno pravilo po redu. Možete koristiti pravila blokatora reklama ili sintaksu hosts datoteke.", "examples_title": "Primeri", @@ -172,8 +190,10 @@ "time_table_header": "Vreme", "date": "Datum", "domain_name_table_header": "Ime domena", + "domain_or_client": "Domen ili klijent", "type_table_header": "Vrsta", "response_table_header": "Odgovor", + "response_code": "Kod odgovora", "client_table_header": "Klijent", "empty_response_status": "Prazno", "show_all_filter_type": "Pokaži sve", @@ -192,6 +212,7 @@ "query_log_filtered": "Filtrirano od {{filter}}", "query_log_confirm_clear": "Jeste li sigurni da želite da očistite ceo dnevnik unosa?", "query_log_cleared": "Dnevnik unosa je uspešno očišćen", + "query_log_updated": "Dnevnik zapisa je uspešno ažuriran", "query_log_clear": "Očisti dnevnike unosa", "query_log_retention": "Zadržavanje dnevnika unosa", "query_log_enable": "Uključi dnevnik", @@ -199,6 +220,8 @@ "query_log_disabled": "Dnevnik unosa je isključen ali se može konfigurisati u <0>postavkama", "query_log_strict_search": "Koristi duple navodnike za striktnu pretragu", "query_log_retention_confirm": "Jeste li sigurni da želite da promenite zadržavanje dnevnika unosa? Ako smanjite vrednost intervala, neki podaci će biti izgubljeni", + "anonymize_client_ip": "Anonimizuj IP klijenta", + "anonymize_client_ip_desc": "Ne čuvaj punu IP adresu klijenta u dnevnicima i statistikama", "dns_config": "Konfiguracija DNS servera", "blocking_mode": "Način blokiranja", "default": "Podrazumevano", @@ -207,6 +230,9 @@ "custom_ip": "Prilagođeni IP", "blocking_ipv4": "Blokiranje IPv4", "blocking_ipv6": "Blokiranje IPv6", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", + "plain_dns": "Plain DNS", "form_enter_rate_limit": "Unesite ograničenje brzine", "rate_limit": "Ograničenje brzine", "edns_enable": "Uključi EDNS Client Subnet", @@ -219,12 +245,14 @@ "blocking_mode_null_ip": "Null IP: Odgovara sa zero IP adresom (0.0.0.0 za A; :: za AAAA)", "blocking_mode_custom_ip": "Prilagođeni IP: Odgovara sa ručno podešenom IP adresom", "upstream_dns_client_desc": "AKo ovo polje ostavite prazno, AdGuard Home će koristiti servere konfigurisane u <0>DNS postavkama.", + "tracker_source": "Izvor praćenja", "source_label": "Izvor", "found_in_known_domain_db": "Pronađeno u poznatim bazama podataka domena.", "category_label": "Kategorija", "rule_label": "Pravilo", "list_label": "Lista", "unknown_filter": "Nepoznat filter {{filterId}}", + "known_tracker": "Poznato praćenje", "install_welcome_title": "Dobrodošli u AdGuard home!", "install_welcome_desc": "AdGuard Home je mrežni DNS server, blokator reklama i praćenja. Dopušta vam da kontrolišete svoju čitavu mrežu i sve vaše uređaje i ne zahteva korišćenje nikakvog klijentskog programa.", "install_settings_title": "Administratorsko web okruženje", @@ -253,6 +281,7 @@ "install_devices_router_list_1": "Otvorite podešavanja vašeg rutera. Obično im možete pristupiti iz vašeg preglednika preko URL (kao http://192.168.0.1/ ili http://192.168.1.1/). Možda će vam biti zatraženo da unesete lozinku. Ako je ne znate ili je se ne sećate, najčešće je možete resetovati pritiskom na dugme na samom ruteru. Neki ruteri zahtevaju određenu aplikaciju, koja bi u tom slučaju već trebalo da bude instalirana na vašem računaru ili telefonu.", "install_devices_router_list_2": "Pronađite DHCP ili DNS postavke. Potražite DNS slova pored polja koje dozvoljava dve ili tri skupine brojeva, a svaka može da sadrži četiri grupe od jedne do tri cifre.", "install_devices_router_list_3": "Tamo unesite adrese AdGuard home servera.", + "install_devices_router_list_4": "Na nekim ruterima ne možete postaviti prilagođeni DNS server.", "install_devices_windows_list_1": "Otvorite kontrolnu tablu iz startnog menija ili kroz Windows pretragu.", "install_devices_windows_list_2": "Otvorite kategoriju mreža i internet a onda otiđite u centar za mrežu i deljenje.", "install_devices_windows_list_3": "Na levoj strani ekrana pronađite Promena postavke adaptera i kliknite tu.", @@ -341,6 +370,7 @@ "form_enter_id": "Unesite identifikator", "form_add_id": "Dodaj identifikator", "form_client_name": "Unesite ime klijenta", + "name": "Ime", "client_global_settings": "Koristi globalne postavke", "client_deleted": "Klijent \"{{key}}\" uspešno izbrisan", "client_added": "Klijent \"{{key}}\" uspešno dodat", @@ -385,6 +415,7 @@ "rewrite_confirm_delete": "Jeste li sigurni da želite da izbrišete DNS prepisivanje za \"{{key}}\"?", "rewrite_desc": "Dozvoljava da jednostavno konfigurišete prilagođeni DNS odgovor za određeni domen.", "rewrite_applied": "Primenjeno pravilo prepisivanja", + "rewrite_hosts_applied": "Prepisano od pravila hosts datoteke", "dns_rewrites": "DNS prepisivanja", "form_domain": "Unesite domen", "form_answer": "Unesite IP adresu ili domen", @@ -439,6 +470,7 @@ "location": "Lokacija", "orgname": "Ime organizacije", "netname": "Ime mreže", + "network": "Mreža", "descr": "Opis", "whois": "Whois", "filtering_rules_learn_more": "<0>Saznajte više o stvaranju vaše lične blokliste hostova.", @@ -449,6 +481,8 @@ "example_rewrite_wildcard": "prepiši odgovore za sve poddomene na <0>example.org.", "disable_ipv6": "Isključi IPv6", "disable_ipv6_desc": "Ako je ovo uključeno, svi DNS unosi za IPv6 adrese (type AAAA) će biti odbačeni.", + "fastest_addr": "Najbrža IP adresa", + "fastest_addr_desc": "Pretražuje sve DNS servere i vraća najbržu IP adresu među svim odgovorima. Ovo će usporiti DNS pretragu jer moramo da čekamo na odgovore od svih DNS servera, ali će poboljšati sveukupnu povezanost.", "autofix_warning_text": "Ako kliknete \"Popravi\", AdGuardHome će konfigurisati vaš sistem da koristi AdGuardHome DNS server.", "autofix_warning_list": "To će izvršiti sledeće zadatke: <0>Deaktiviranje system DNSStubListener <0>Set DNS server address to 127.0.0.1 <0>Replace symbolic link target of /etc/resolv.conf to /run/systemd/resolve/resolv.conf <0>Stop DNSStubListener (reload systemd-resolved service)", "autofix_warning_result": "Kao rezultat, svi DNS zahtevi sa vašeg sistema će biti obrađeni od AdGuardHome.", @@ -480,7 +514,20 @@ "confirm_static_ip": "AdGuard Home će konfigurisati {{ip}} da bude vaša statička IP adresa. Želite li da nastavite?", "list_updated": "{{count}} lista ažurirana", "list_updated_plural": "{{count}} lista ažurirano", + "dnssec_enable": "Uključi DNSSEC", + "dnssec_enable_desc": "Postavlja DNSSEC zastavicu u odlaznim DNS zahtevima i proverava rezultat (DNSSEC rešavač je potreban)", + "validated_with_dnssec": "Potvrđeno sa DNSSEC", + "show_all_responses": "Svi odgovori", "show_blocked_responses": "Blokirano", + "show_whitelisted_responses": "Na beloj listi", + "show_processed_responses": "Obrađeno", + "blocked_safebrowsing": "Blokiralo bezbedno pregledanje", "blocked_adult_websites": "Blokiraj sajtove za odrasle", - "blocked_threats": "Blokiranih pretnji" + "blocked_threats": "Blokiranih pretnji", + "allowed": "Dozvoljeno", + "filtered": "Filtrirano", + "rewritten": "Prepisano", + "safe_search": "Sigurna pretraga", + "blocklist": "Lista blokiranih", + "milliseconds_abbreviation": "ms" } \ No newline at end of file diff --git a/client/src/__locales/zh-cn.json b/client/src/__locales/zh-cn.json index 8fd0c17108e..7766bce9916 100644 --- a/client/src/__locales/zh-cn.json +++ b/client/src/__locales/zh-cn.json @@ -530,4 +530,4 @@ "safe_search": "安全搜索", "blocklist": "拦截列表", "milliseconds_abbreviation": "毫秒" -} \ No newline at end of file +} diff --git a/client/src/actions/filtering.js b/client/src/actions/filtering.js index b6941c77203..02bc97f8330 100644 --- a/client/src/actions/filtering.js +++ b/client/src/actions/filtering.js @@ -45,12 +45,14 @@ export const addFilterRequest = createAction('ADD_FILTER_REQUEST'); export const addFilterFailure = createAction('ADD_FILTER_FAILURE'); export const addFilterSuccess = createAction('ADD_FILTER_SUCCESS'); -export const addFilter = (url, name, whitelist = false) => async (dispatch) => { +export const addFilter = (url, name, whitelist = false) => async (dispatch, getState) => { dispatch(addFilterRequest()); try { await apiClient.addFilter({ url, name, whitelist }); dispatch(addFilterSuccess(url)); - dispatch(toggleFilteringModal()); + if (getState().filtering.isModalOpen) { + dispatch(toggleFilteringModal()); + } dispatch(addSuccessToast('filter_added_successfully')); dispatch(getFilteringStatus()); } catch (error) { @@ -63,11 +65,15 @@ export const removeFilterRequest = createAction('REMOVE_FILTER_REQUEST'); export const removeFilterFailure = createAction('REMOVE_FILTER_FAILURE'); export const removeFilterSuccess = createAction('REMOVE_FILTER_SUCCESS'); -export const removeFilter = (url, whitelist = false) => async (dispatch) => { +export const removeFilter = (url, whitelist = false) => async (dispatch, getState) => { dispatch(removeFilterRequest()); try { await apiClient.removeFilter({ url, whitelist }); dispatch(removeFilterSuccess(url)); + if (getState().filtering.isModalOpen) { + dispatch(toggleFilteringModal()); + } + dispatch(addSuccessToast('filter_removed_successfully')); dispatch(getFilteringStatus()); } catch (error) { dispatch(addErrorToast({ error })); @@ -95,12 +101,14 @@ export const editFilterRequest = createAction('EDIT_FILTER_REQUEST'); export const editFilterFailure = createAction('EDIT_FILTER_FAILURE'); export const editFilterSuccess = createAction('EDIT_FILTER_SUCCESS'); -export const editFilter = (url, data, whitelist = false) => async (dispatch) => { +export const editFilter = (url, data, whitelist = false) => async (dispatch, getState) => { dispatch(editFilterRequest()); try { await apiClient.setFilterUrl({ url, data, whitelist }); dispatch(editFilterSuccess(url)); - dispatch(toggleFilteringModal()); + if (getState().filtering.isModalOpen) { + dispatch(toggleFilteringModal()); + } dispatch(addSuccessToast('filter_updated')); dispatch(getFilteringStatus()); } catch (error) { diff --git a/client/src/components/App/index.css b/client/src/components/App/index.css index b24edfd380a..438496d7e25 100644 --- a/client/src/components/App/index.css +++ b/client/src/components/App/index.css @@ -53,6 +53,15 @@ body { } } +.modal-body--medium { + max-height: 20rem; + overflow-y: scroll; +} + +.modal-body__item:not(:first-child) { + padding-top: 1.5rem; +} + .font-monospace { font-family: var(--font-family-monospace); } diff --git a/client/src/components/Filters/DnsAllowlist.js b/client/src/components/Filters/DnsAllowlist.js index 8727ae4cc89..f8ac1a2cb18 100644 --- a/client/src/components/Filters/DnsAllowlist.js +++ b/client/src/components/Filters/DnsAllowlist.js @@ -21,7 +21,7 @@ class DnsAllowlist extends Component { const { filtering } = this.props; const whitelist = true; - if (filtering.modalType === MODAL_TYPE.EDIT) { + if (filtering.modalType === MODAL_TYPE.EDIT_FILTERS) { this.props.editFilter(filtering.modalFilterUrl, values, whitelist); } else { this.props.addFilter(url, name, whitelist); @@ -44,6 +44,10 @@ class DnsAllowlist extends Component { this.props.refreshFilters({ whitelist: true }); }; + openAddFiltersModal = () => { + this.props.toggleFilteringModal({ type: MODAL_TYPE.ADD_FILTERS }); + }; + render() { const { t, @@ -92,7 +96,7 @@ class DnsAllowlist extends Component { whitelist={whitelist} /> toggleFilteringModal({ type: MODAL_TYPE.ADD })} + handleAdd={this.openAddFiltersModal} handleRefresh={this.handleRefresh} processingRefreshFilters={processingRefreshFilters} whitelist={whitelist} @@ -102,8 +106,9 @@ class DnsAllowlist extends Component { { - const { name, url } = values; - const { filtering } = this.props; + handleSubmit = (values, _, { initialValues }) => { + const { filtering: { modalFilterUrl, modalType } } = this.props; - if (filtering.modalType === MODAL_TYPE.EDIT) { - this.props.editFilter(filtering.modalFilterUrl, values); - } else { - this.props.addFilter(url, name); + switch (modalType) { + case MODAL_TYPE.EDIT_FILTERS: + this.props.editFilter(modalFilterUrl, values); + break; + case MODAL_TYPE.ADD_FILTERS: { + const { name, url } = values; + this.props.addFilter(url, name); + break; + } + case MODAL_TYPE.CHOOSE_FILTERING_LIST: { + const changedValues = getObjDiff(initialValues, values); + + Object.keys(changedValues) + .forEach((fieldName) => { + // filterId is actually in the field name + const { source, name } = filtersCatalog.filters[fieldName]; + this.props.addFilter(source, name); + }); + break; + } + default: + break; } }; @@ -41,6 +64,10 @@ class DnsBlocklist extends Component { this.props.refreshFilters({ whitelist: false }); }; + openSelectTypeModal = () => { + this.props.toggleFilteringModal({ type: MODAL_TYPE.SELECT_MODAL_TYPE }); + }; + render() { const { t, @@ -67,7 +94,7 @@ class DnsBlocklist extends Component { || processingRefreshFilters; return ( - + <> toggleFilteringModal({ type: MODAL_TYPE.ADD })} + handleAdd={this.openSelectTypeModal} handleRefresh={this.handleRefresh} processingRefreshFilters={processingRefreshFilters} /> @@ -94,8 +121,10 @@ class DnsBlocklist extends Component { - + ); } } diff --git a/client/src/components/Filters/Form.js b/client/src/components/Filters/Form.js index 0237a5d6482..ac8cc1906da 100644 --- a/client/src/components/Filters/Form.js +++ b/client/src/components/Filters/Form.js @@ -1,11 +1,75 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Field, reduxForm } from 'redux-form'; -import { Trans, withTranslation } from 'react-i18next'; +import { withTranslation } from 'react-i18next'; import flow from 'lodash/flow'; -import { renderInputField } from '../../helpers/form'; +import classNames from 'classnames'; import { validatePath, validateRequiredValue } from '../../helpers/validators'; -import { FORM_NAME } from '../../helpers/constants'; +import { renderInputField, renderSelectField } from '../../helpers/form'; +import { MODAL_OPEN_TIMEOUT, MODAL_TYPE, FORM_NAME } from '../../helpers/constants'; + +const getIconsData = (homepage, source) => ([ + { + iconName: 'dashboard', + href: homepage, + className: 'ml-1', + }, + { + iconName: 'info', + href: source, + }, +]); + +const renderIcons = (iconsData) => iconsData.map(({ + iconName, + href, + className = '', +}) => + + + +); + +const renderFilters = ({ categories, filters }, selectedSources, t) => Object.keys(categories) + .map((categoryId) => { + const category = categories[categoryId]; + const categoryFilters = []; + Object.keys(filters) + .sort() + .forEach((key) => { + const filter = filters[key]; + filter.id = key; + if (filter.categoryId === categoryId) { + categoryFilters.push(filter); + } + }); + + return
+
{t(category.name)}
+

{t(category.description)}

+ {categoryFilters.map((filter) => { + const { homepage, source, name } = filter; + + const isSelected = Object.prototype.hasOwnProperty.call(selectedSources, source); + + const iconsData = getIconsData(homepage, source); + + return
+ + {renderIcons(iconsData)} +
; + })} +
; + }); const Form = (props) => { const { @@ -15,11 +79,38 @@ const Form = (props) => { processingAddFilter, processingConfigFilter, whitelist, + modalType, + toggleFilteringModal, + selectedSources, + filtersCatalog, } = props; - return ( -
-
+ const openModal = (modalType, timeout = MODAL_OPEN_TIMEOUT) => { + toggleFilteringModal(); + setTimeout(() => toggleFilteringModal({ type: modalType }), timeout); + }; + + const openFilteringListModal = () => openModal(MODAL_TYPE.CHOOSE_FILTERING_LIST); + + const openAddFiltersModal = () => openModal(MODAL_TYPE.ADD_FILTERS); + + return +
+ {modalType === MODAL_TYPE.SELECT_MODAL_TYPE + &&
+ + +
} + {modalType === MODAL_TYPE.CHOOSE_FILTERING_LIST + && renderFilters(filtersCatalog, selectedSources, t)} + {modalType !== MODAL_TYPE.CHOOSE_FILTERING_LIST + && modalType !== MODAL_TYPE.SELECT_MODAL_TYPE + && <>
{ />
- {whitelist ? enter_valid_allowlist - : enter_valid_blocklist} + {whitelist ? t('enter_valid_allowlist') : t('enter_valid_blocklist')}
-
-
- - -
- - ); + } +
+
+ + +
+ ; }; Form.propTypes = { @@ -76,6 +166,10 @@ Form.propTypes = { processingAddFilter: PropTypes.bool.isRequired, processingConfigFilter: PropTypes.bool.isRequired, whitelist: PropTypes.bool, + modalType: PropTypes.string.isRequired, + toggleFilteringModal: PropTypes.func.isRequired, + filtersCatalog: PropTypes.object, + selectedSources: PropTypes.object, }; export default flow([ diff --git a/client/src/components/Filters/Modal.js b/client/src/components/Filters/Modal.js index 2c3656044d2..0421f548f8c 100644 --- a/client/src/components/Filters/Modal.js +++ b/client/src/components/Filters/Modal.js @@ -1,17 +1,51 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import ReactModal from 'react-modal'; -import { Trans, withTranslation } from 'react-i18next'; +import { withTranslation } from 'react-i18next'; import { MODAL_TYPE } from '../../helpers/constants'; import Form from './Form'; import '../ui/Modal.css'; +import { getMap } from '../../helpers/helpers'; ReactModal.setAppElement('#root'); +const MODAL_TYPE_TO_TITLE_TYPE_MAP = { + [MODAL_TYPE.EDIT_FILTERS]: 'edit', + [MODAL_TYPE.ADD_FILTERS]: 'new', + [MODAL_TYPE.SELECT_MODAL_TYPE]: 'new', + [MODAL_TYPE.CHOOSE_FILTERING_LIST]: 'choose', +}; + +/** + * @param modalType {'EDIT_FILTERS' | 'ADD_FILTERS' | 'CHOOSE_FILTERING_LIST'} + * @param whitelist {boolean} + * @returns {'new_allowlist' | 'edit_allowlist' | 'choose_allowlist' | + * 'new_blocklist' | 'edit_blocklist' | 'choose_blocklist' | null} + */ +const getTitle = (modalType, whitelist) => { + const titleType = MODAL_TYPE_TO_TITLE_TYPE_MAP[modalType]; + if (!titleType) { + return null; + } + return `${titleType}_${whitelist ? 'allowlist' : 'blocklist'}`; +}; + +const getSelectedValues = (filters, catalogSourcesToIdMap) => filters.reduce((acc, { url }) => { + if (Object.prototype.hasOwnProperty.call(catalogSourcesToIdMap, url)) { + const fieldId = `filter${catalogSourcesToIdMap[url]}`; + acc.selectedFilterIds[fieldId] = true; + acc.selectedSources[url] = true; + } + return acc; +}, { + selectedFilterIds: {}, + selectedSources: {}, +}); + class Modal extends Component { closeModal = () => { - this.props.toggleModal(); + this.props.toggleFilteringModal(); }; render() { @@ -23,19 +57,30 @@ class Modal extends Component { modalType, currentFilterData, whitelist, + toggleFilteringModal, + filters, + t, + filtersCatalog, } = this.props; - const newListTitle = whitelist ? ( - new_allowlist - ) : ( - new_blocklist - ); + let initialValues; + let selectedSources; + switch (modalType) { + case MODAL_TYPE.EDIT_FILTERS: + initialValues = currentFilterData; + break; + case MODAL_TYPE.CHOOSE_FILTERING_LIST: { + const catalogSourcesToIdMap = getMap(Object.values(filtersCatalog.filters), 'source', 'id'); - const editListTitle = whitelist ? ( - edit_allowlist - ) : ( - edit_blocklist - ); + const selectedValues = getSelectedValues(filters, catalogSourcesToIdMap); + initialValues = selectedValues.selectedFilterIds; + selectedSources = selectedValues.selectedSources; + break; + } + default: + } + + const title = t(getTitle(modalType, whitelist)); return (
-

- {modalType === MODAL_TYPE.EDIT ? ( - editListTitle - ) : ( - newListTitle - )} -

+ {title &&

{title}

}
@@ -72,7 +115,7 @@ class Modal extends Component { } Modal.propTypes = { - toggleModal: PropTypes.func.isRequired, + toggleFilteringModal: PropTypes.func.isRequired, isOpen: PropTypes.bool.isRequired, addFilter: PropTypes.func.isRequired, isFilterAdded: PropTypes.bool.isRequired, @@ -83,6 +126,8 @@ Modal.propTypes = { currentFilterData: PropTypes.object.isRequired, t: PropTypes.func.isRequired, whitelist: PropTypes.bool, + filters: PropTypes.array.isRequired, + filtersCatalog: PropTypes.object, }; export default withTranslation()(Modal); diff --git a/client/src/components/Filters/Table.js b/client/src/components/Filters/Table.js index fbf89235728..cb86a9ea35c 100644 --- a/client/src/components/Filters/Table.js +++ b/client/src/components/Filters/Table.js @@ -92,7 +92,7 @@ class Table extends Component { className="btn btn-icon btn-outline-primary btn-sm mr-2" title={t('edit_table_action')} onClick={() => toggleFilteringModal({ - type: MODAL_TYPE.EDIT, + type: MODAL_TYPE.EDIT_FILTERS, url: value, }) } diff --git a/client/src/components/Header/Header.css b/client/src/components/Header/Header.css index ddf858c2966..08b0b1fca76 100644 --- a/client/src/components/Header/Header.css +++ b/client/src/components/Header/Header.css @@ -160,6 +160,10 @@ display: none; } + .nav-icon--gray { + color: #9aa0ac; + } + .header-brand-img { height: 32px; } diff --git a/client/src/components/Settings/Clients/ClientsTable.js b/client/src/components/Settings/Clients/ClientsTable.js index 6d3fc01aecf..2fda1bd6ea0 100644 --- a/client/src/components/Settings/Clients/ClientsTable.js +++ b/client/src/components/Settings/Clients/ClientsTable.js @@ -41,7 +41,7 @@ class ClientsTable extends Component { } } - if (this.props.modalType === MODAL_TYPE.EDIT) { + if (this.props.modalType === MODAL_TYPE.EDIT_FILTERS) { this.handleFormUpdate(config, this.props.modalClientName); } else { this.handleFormAdd(config); @@ -221,7 +221,7 @@ class ClientsTable extends Component { type="button" className="btn btn-icon btn-outline-primary btn-sm mr-2" onClick={() => toggleClientModal({ - type: MODAL_TYPE.EDIT, + type: MODAL_TYPE.EDIT_FILTERS, name: clientName, }) } @@ -306,7 +306,7 @@ class ClientsTable extends Component {