From 27fbabe7cfdb87a84fd6f065538c2c246edc3d7e Mon Sep 17 00:00:00 2001 From: Ildar Kamalov Date: Fri, 25 Sep 2026 15:53:56 +0300 Subject: [PATCH 1/2] AGH-177 design review UI fixes --- client_v2/AGENTS.md | 12 + client_v2/src/__locales/ar.json | 14 +- client_v2/src/__locales/en.json | 25 +- client_v2/src/__locales/hr.json | 14 +- .../common/controls/Textarea.test.tsx | 32 ++ .../src/__tests__/common/ui/Banners.test.tsx | 29 ++ .../common/ui/ClientBlockMenuItem.test.tsx | 44 +++ .../__tests__/common/ui/ConfigDialog.test.tsx | 27 ++ .../src/__tests__/common/ui/link.test.tsx | 75 +++++ .../common/ui/truncated-text.test.tsx | 53 ++++ .../components/Clients/service-icons.test.tsx | 107 +++++++ .../Dashboard/stats-period.test.tsx | 254 +++++++++++++++ .../components/encryption-page.test.tsx | 170 ++++++++++ .../encryption-server-settings-modal.test.tsx | 217 +++++++++++-- .../encryption-tls-cert-section.test.tsx | 47 ++- .../__tests__/dashboard-show-more.test.tsx | 150 +++++++-- .../dashboard-stat-row-tooltips.test.tsx | 160 ++++++++++ .../dashboard-top-clients-actions.test.tsx | 121 ++++++++ .../src/__tests__/dns-config-store.test.ts | 68 +++- .../src/__tests__/dynamic-leases-tab.test.tsx | 2 +- client_v2/src/__tests__/helpers/matchMedia.ts | 91 ++++++ .../redirect-to-current-protocol.test.ts | 56 ++++ .../src/__tests__/helpers/statistics.test.ts | 77 +++++ .../__tests__/hooks/use-is-truncated.test.tsx | 74 +++++ .../__tests__/hooks/use-media-query.test.tsx | 118 +++++++ .../__tests__/hooks/use-scroll-edges.test.tsx | 215 +++++++++++++ .../__tests__/hooks/use-switch-state.test.tsx | 71 +++++ .../src/__tests__/hooks/use-theme.test.tsx | 61 ++++ client_v2/src/__tests__/login-form.test.tsx | 74 +++++ .../__tests__/query-log-detail-modal.test.tsx | 94 ++++++ client_v2/src/__tests__/select.test.tsx | 40 +++ client_v2/src/__tests__/setup.ts | 6 +- .../src/__tests__/static-lease-modal.test.tsx | 9 + .../stats-pages/stat-mobile-card.test.tsx | 58 ++++ .../__tests__/stats-pages/stats-page.test.tsx | 79 ++++- client_v2/src/__tests__/stats-store.test.ts | 68 +++- client_v2/src/__tests__/toasts-store.test.ts | 22 ++ client_v2/src/__tests__/tooltip.test.tsx | 33 +- .../common/controls/Input/Input.module.pcss | 45 ++- client_v2/src/common/controls/Input/Input.tsx | 2 + .../common/controls/Radio/Radio.module.pcss | 6 +- .../src/common/controls/Select/Select.pcss | 53 +++- .../src/common/controls/Select/Select.tsx | 2 + client_v2/src/common/controls/Select/types.ts | 4 + .../common/controls/Switch/Switch.module.pcss | 24 +- .../src/common/controls/Textarea/Textarea.tsx | 3 + .../controls/Textarea/styles.module.pcss | 32 +- client_v2/src/common/styles/colors/dark.css | 1 + client_v2/src/common/styles/colors/light.css | 1 + .../ui/AuthLayout/AuthLayout.module.pcss | 51 +++ .../src/common/ui/AuthLayout/AuthLayout.tsx | 33 ++ client_v2/src/common/ui/AuthLayout/index.ts | 1 + client_v2/src/common/ui/Banners/Banners.tsx | 11 +- .../src/common/ui/Breadcrumbs/Breadcrumbs.tsx | 6 +- .../src/common/ui/Button/Button.module.pcss | 17 + client_v2/src/common/ui/Button/Button.tsx | 3 + .../ClientBlockMenuItem.module.pcss | 29 ++ .../ClientBlockMenuItem.tsx | 37 +++ .../src/common/ui/ClientBlockConfirm/index.ts | 1 + .../common/ui/ConfigDialog/ConfigDialog.tsx | 5 +- .../common/ui/ConfirmDialog/ConfirmDialog.tsx | 1 + .../ui/CopiedText/CopiedText.module.pcss | 6 +- .../ui/DangerLink/DangerLink.module.pcss | 30 ++ .../src/common/ui/DangerLink/DangerLink.tsx | 26 ++ client_v2/src/common/ui/DangerLink/index.ts | 1 + client_v2/src/common/ui/Dialog/Dialog.pcss | 2 +- .../common/ui/Dropdown/Dropdown.module.pcss | 1 - .../common/ui/Dropzone/Dropzone.module.pcss | 4 +- client_v2/src/common/ui/Guide/Guide.tsx | 52 ++-- client_v2/src/common/ui/Icon/Icon.module.pcss | 1 - client_v2/src/common/ui/Icons/Icons.tsx | 3 +- client_v2/src/common/ui/Link/Link.tsx | 7 +- .../ui/PublicHeader/PublicHeader.module.pcss | 40 +++ .../common/ui/PublicHeader/PublicHeader.tsx | 9 +- .../ui/SettingRow/SettingRow.module.pcss | 10 +- .../ui/SettingsGroup/styles.module.pcss | 7 +- .../src/common/ui/Table/Table.module.pcss | 28 +- client_v2/src/common/ui/Table/Table.tsx | 84 +++-- .../HeaderLabel/HeaderLabel.module.pcss | 5 - .../Table/blocks/HeaderLabel/HeaderLabel.tsx | 16 +- .../ui/Table/blocks/Pagination/Pagination.tsx | 2 +- client_v2/src/common/ui/Tooltip/Tooltip.tsx | 4 +- .../TruncatedText/TruncatedText.module.pcss | 13 + .../common/ui/TruncatedText/TruncatedText.tsx | 51 +++ .../src/common/ui/TruncatedText/index.ts | 1 + .../BlockedServices.module.pcss | 4 +- .../InactivitySchedule/ScheduleModal.tsx | 9 + .../PersistentClientsTable.module.pcss | 10 +- .../PersistentClientsTable.tsx | 13 +- .../PersistentClientsTable/ServiceIcons.tsx | 18 +- .../RuntimeClientsTable.module.pcss | 10 +- .../src/components/Dashboard/Dashboard.tsx | 96 +++--- .../GeneralStatistics/GeneralStatistics.tsx | 18 +- .../Dashboard/blocks/Header/Header.tsx | 2 +- .../blocks/RowTooltip/RowTooltip.module.pcss | 9 + .../blocks/RowTooltip/RowTooltip.tsx | 37 +++ .../Dashboard/blocks/RowTooltip/index.ts | 1 + .../Dashboard/blocks/StatCards/StatCards.tsx | 15 +- .../blocks/StatRow/StatRow.module.pcss | 25 +- .../Dashboard/blocks/StatRow/StatRow.tsx | 72 +++-- .../Dashboard/blocks/TableCard.module.pcss | 56 ++-- .../TopBlockedDomains/TopBlockedDomains.tsx | 120 +++---- .../blocks/TopClients/TopClients.module.pcss | 122 ++++---- .../blocks/TopClients/TopClients.tsx | 293 +++++++++--------- .../TopQueriedDomains/TopQueriedDomains.tsx | 111 ++++--- .../blocks/TopUpstreams/TopUpstreams.tsx | 23 +- .../TrackerTooltip/TrackerTooltip.module.pcss | 9 + .../blocks/TrackerTooltip/TrackerTooltip.tsx | 102 +++--- .../UpstreamAvgTime/UpstreamAvgTime.tsx | 23 +- .../Dashboard/hooks/useSortedData.ts | 8 +- client_v2/src/components/Dhcp/Dhcp.tsx | 38 +-- .../Dhcp/LeasesPage/DynamicLeasesTab.tsx | 2 +- .../Dhcp/LeasesPage/StaticLeaseModal.tsx | 4 + .../Dhcp/LeasesPage/StaticLeasesTab.tsx | 2 +- .../Dhcp/LeasesPage/StaticLeasesTable.tsx | 9 +- .../Dhcp/blocks/DhcpV4Modal/DhcpV4Modal.tsx | 5 + .../components/Dhcp/blocks/DhcpV6Modal.tsx | 2 + .../Access/blocks/AllowedClientsDialog.tsx | 1 + .../Access/blocks/DisallowedClientsDialog.tsx | 1 + .../Access/blocks/DisallowedDomainsDialog.tsx | 1 + .../components/DnsSettings/Cache/Cache.tsx | 28 +- .../Cache/blocks/CacheInputDialog.tsx | 20 +- .../PrivateReverse/PrivateReverse.tsx | 57 +++- .../DnsSettings/ServerConfig/ServerConfig.tsx | 41 ++- .../blocks/BlockingModeDialog.tsx | 3 + .../ServerConfig/blocks/EdnsDialog.tsx | 29 +- .../blocks/RateLimitAllowlistDialog.tsx | 1 + .../ServerConfig/blocks/RateLimitDialog.tsx | 1 + .../blocks/SubnetPrefixV4Dialog.tsx | 1 + .../blocks/SubnetPrefixV6Dialog.tsx | 1 + .../DnsSettings/Upstream/Upstream.tsx | 49 ++- .../Upstream/blocks/BootstrapDnsDialog.tsx | 1 + .../Upstream/blocks/FallbackDnsDialog.tsx | 1 + .../blocks/PrivateReverseServersDialog.tsx | 26 +- .../Upstream/blocks/ServerAddressesDialog.tsx | 1 + .../Upstream/blocks/TimeoutDialog.tsx | 1 + .../src/components/DnsSettings/helpers.ts | 17 + .../src/components/Encryption/Encryption.tsx | 92 ++---- .../blocks/ServerSettingsFields.tsx | 9 + .../Encryption/blocks/ServerSettingsModal.tsx | 32 +- .../blocks/SetupWizard/PemSourceFields.tsx | 2 + .../blocks/SetupWizard/TlsSetupWizard.tsx | 4 +- .../blocks/SetupWizard/mapStepResult.ts | 65 ++-- .../Encryption/blocks/TlsCertSection.tsx | 16 +- .../components/Encryption/blocks/helpers.ts | 32 ++ .../Encryption/blocks/useServerNameCheck.ts | 122 ++++++++ .../ConfigureAllowlistModal.tsx | 3 + .../ConfigureBlocklistModal.tsx | 1 + .../ManualFilterForm/ManualFilterForm.tsx | 2 + .../ConfigureRewritesModal.tsx | 3 + .../FilterUpdateModal/FilterIntervalInput.tsx | 1 + .../FilterUpdateModal/FilterUpdateModal.tsx | 1 + .../DetailModal/DetailModal.module.pcss | 52 +++- .../blocks/DetailModal/DetailModal.tsx | 14 +- .../QueryLog/blocks/Header/Header.tsx | 2 +- .../blocks/LogCard/LogCard.module.pcss | 2 - .../QueryLog/blocks/LogCard/LogCard.tsx | 28 +- .../blocks/LogTable/LogTable.module.pcss | 32 +- client_v2/src/components/Routes/Paths.ts | 3 + .../IgnoredDomainsModal.tsx | 1 + .../Settings/RetentionCustomInput.tsx | 1 + .../SafeSearchModal.module.pcss | 9 +- .../components/Settings/Settings.module.pcss | 8 +- .../SetupGuide/MobileConfigForm.module.pcss | 7 +- .../SetupGuide/MobileConfigForm.tsx | 10 +- .../components/Stats/StatsPage/StatsPage.tsx | 20 +- .../TopBlockedDomainsPage.tsx | 11 +- .../TopClientsPage/TopClientsPage.module.pcss | 41 +-- .../Stats/TopClientsPage/TopClientsPage.tsx | 141 ++++----- .../TopQueriedDomainsPage.tsx | 11 +- .../CountWithPercent.module.pcss | 11 - .../CountWithPercent/CountWithPercent.tsx | 16 +- .../blocks/NameCell/NameCell.module.pcss | 12 - .../Stats/blocks/NameCell/NameCell.tsx | 38 +-- .../StatMobileCard/StatMobileCard.module.pcss | 10 +- .../blocks/StatMobileCard/StatMobileCard.tsx | 124 ++++---- .../UserRules/blocks/CheckForm/CheckForm.tsx | 3 + .../forgot_password/ForgotPassword/index.tsx | 87 +++--- .../ForgotPassword/styles.module.pcss | 113 +------ client_v2/src/helpers/breakpoints.ts | 25 ++ client_v2/src/helpers/helpers.tsx | 10 + client_v2/src/helpers/statistics.ts | 11 +- client_v2/src/helpers/useMediaQuery.ts | 21 -- client_v2/src/hooks/useIsMobile.ts | 29 -- client_v2/src/hooks/useIsTruncated.ts | 44 ++- client_v2/src/hooks/useMediaQuery.ts | 54 ++++ client_v2/src/hooks/useScrollEdges.ts | 66 ++++ client_v2/src/hooks/useSwitchState.ts | 36 +++ client_v2/src/hooks/useTheme.ts | 34 ++ client_v2/src/index.pcss | 4 + .../install/Setup/blocks/Banner/DnsBanner.tsx | 2 + .../install/Setup/blocks/Banner/WebBanner.tsx | 2 + client_v2/src/lib/theme/Auth.module.pcss | 64 ++++ client_v2/src/lib/theme/Link.module.pcss | 1 - .../src/lib/theme/Pagination.module.pcss | 9 +- client_v2/src/lib/theme/Table.module.pcss | 11 +- client_v2/src/lib/theme/index.ts | 2 + client_v2/src/login/Login/Form.tsx | 114 +++---- client_v2/src/login/Login/Login.tsx | 25 +- client_v2/src/login/Login/styles.module.pcss | 125 -------- client_v2/src/stores/dnsConfig.ts | 70 +++-- client_v2/src/stores/stats.ts | 18 +- client_v2/src/stores/toasts.ts | 49 +-- client_v2/tests/e2e/blocked-services.spec.ts | 96 +++++- client_v2/tests/e2e/clients.spec.ts | 118 ++++++- client_v2/tests/e2e/dns-rewrites.spec.ts | 7 +- client_v2/tests/e2e/login.spec.ts | 1 - client_v2/tests/e2e/query-log.spec.ts | 102 ++---- 208 files changed, 5713 insertions(+), 1816 deletions(-) create mode 100644 client_v2/src/__tests__/common/ui/ClientBlockMenuItem.test.tsx create mode 100644 client_v2/src/__tests__/common/ui/link.test.tsx create mode 100644 client_v2/src/__tests__/common/ui/truncated-text.test.tsx create mode 100644 client_v2/src/__tests__/components/Clients/service-icons.test.tsx create mode 100644 client_v2/src/__tests__/components/Dashboard/stats-period.test.tsx create mode 100644 client_v2/src/__tests__/components/encryption-page.test.tsx create mode 100644 client_v2/src/__tests__/dashboard-stat-row-tooltips.test.tsx create mode 100644 client_v2/src/__tests__/dashboard-top-clients-actions.test.tsx create mode 100644 client_v2/src/__tests__/helpers/matchMedia.ts create mode 100644 client_v2/src/__tests__/helpers/redirect-to-current-protocol.test.ts create mode 100644 client_v2/src/__tests__/helpers/statistics.test.ts create mode 100644 client_v2/src/__tests__/hooks/use-media-query.test.tsx create mode 100644 client_v2/src/__tests__/hooks/use-scroll-edges.test.tsx create mode 100644 client_v2/src/__tests__/hooks/use-switch-state.test.tsx create mode 100644 client_v2/src/__tests__/hooks/use-theme.test.tsx create mode 100644 client_v2/src/__tests__/login-form.test.tsx create mode 100644 client_v2/src/__tests__/stats-pages/stat-mobile-card.test.tsx create mode 100644 client_v2/src/common/ui/AuthLayout/AuthLayout.module.pcss create mode 100644 client_v2/src/common/ui/AuthLayout/AuthLayout.tsx create mode 100644 client_v2/src/common/ui/AuthLayout/index.ts create mode 100644 client_v2/src/common/ui/ClientBlockConfirm/ClientBlockMenuItem.module.pcss create mode 100644 client_v2/src/common/ui/ClientBlockConfirm/ClientBlockMenuItem.tsx create mode 100644 client_v2/src/common/ui/DangerLink/DangerLink.module.pcss create mode 100644 client_v2/src/common/ui/DangerLink/DangerLink.tsx create mode 100644 client_v2/src/common/ui/DangerLink/index.ts create mode 100644 client_v2/src/common/ui/TruncatedText/TruncatedText.module.pcss create mode 100644 client_v2/src/common/ui/TruncatedText/TruncatedText.tsx create mode 100644 client_v2/src/common/ui/TruncatedText/index.ts create mode 100644 client_v2/src/components/Dashboard/blocks/RowTooltip/RowTooltip.module.pcss create mode 100644 client_v2/src/components/Dashboard/blocks/RowTooltip/RowTooltip.tsx create mode 100644 client_v2/src/components/Dashboard/blocks/RowTooltip/index.ts create mode 100644 client_v2/src/components/Encryption/blocks/useServerNameCheck.ts create mode 100644 client_v2/src/helpers/breakpoints.ts delete mode 100644 client_v2/src/helpers/useMediaQuery.ts delete mode 100644 client_v2/src/hooks/useIsMobile.ts create mode 100644 client_v2/src/hooks/useMediaQuery.ts create mode 100644 client_v2/src/hooks/useScrollEdges.ts create mode 100644 client_v2/src/hooks/useSwitchState.ts create mode 100644 client_v2/src/hooks/useTheme.ts create mode 100644 client_v2/src/lib/theme/Auth.module.pcss delete mode 100644 client_v2/src/login/Login/styles.module.pcss diff --git a/client_v2/AGENTS.md b/client_v2/AGENTS.md index d1e2caa4eb1..49b4b57d7e6 100644 --- a/client_v2/AGENTS.md +++ b/client_v2/AGENTS.md @@ -324,6 +324,10 @@ must not depend on stores or components. Helpers are pure and dependency-free. './Foo.module.pcss'` — and reference classes as `s.button`, `s[variant]`. Compose conditional classes with `clsx`, imported as `cn`: `import cn from 'clsx'` (e.g. `cn(s.button, s.primary, { [s.active]: on() })`). +- **Hover styles**: Wrap `:hover` styling in `@media (hover: hover)` so touch + devices do not keep a stuck highlight after a tap. Gate `:hover` together + with `:focus` on row links, since a tap also focuses an `` in Chrome; + leave `:focus-visible` outlines ungated for keyboard users. - **Colors**: Never hardcode color hex values in `.pcss` or inline styles. Always reference the CSS custom properties defined in `src/common/styles/vars.css` and `src/common/styles/colors/*.css` @@ -346,6 +350,14 @@ must not depend on stores or components. Helpers are pure and dependency-free. a conditional class via `cn(...)`, not an inline `style`. Exception: a single computed pixel offset for a dragging/positioning edge case may be acceptable when no class-based solution exists — justify it in a comment. +- **Comments**: Write comments only where they earn their place, and keep + them useful and compact — one or two lines explaining a non-obvious + *why*: a workaround, a browser quirk, or a cross-file constraint a + reader would otherwise break. Do not narrate what a rule or function + does, restate selector/property names, or spell out measurements, + arithmetic, and design history; that belongs with the value it + constrains or in the PR description. Applies to `.pcss`, `.tsx`, and + tests alike. Delete a comment once the code it describes changes. - **Reactivity**: Use `createSignal` for local state, `createMemo` for derived values, `createEffect` for side effects, `onMount` for initial data fetches, and `onCleanup` for teardown. Do not read signals imperatively diff --git a/client_v2/src/__locales/ar.json b/client_v2/src/__locales/ar.json index 4f5e0a1503f..aa79b8deffd 100644 --- a/client_v2/src/__locales/ar.json +++ b/client_v2/src/__locales/ar.json @@ -460,11 +460,11 @@ "ip_address": "عنوان IP", "known_tracker": "متعقب معروف", "language": "اللغة", - "last_days": "| آخر 0 يوم | آخر يوم واحد | آخر يومين | آخر %count% أيام | آخر %count% يومًا | آخر %count% يوم", - "last_hours": "| آخر 0 ساعة | آخر ساعة واحدة | آخر ساعتين | آخر %count% ساعات | آخر %count% ساعة | آخر %count% ساعة", + "last_days": "| آخر يوم واحد | آخر يومين | آخر %count% أيام | آخر %count% يومًا | آخر %count% يوم", + "last_hours": "| آخر ساعة واحدة | آخر ساعتين | آخر %count% ساعات | آخر %count% ساعة | آخر %count% ساعة", "last_updated_label": "آخر تحديث", "light_theme": "المظهر فاتح", - "list_updated": "| لا توجد قوائم محدثة | تم تحديث قائمة واحدة | تم تحديث قائمتين | تم تحديث %count% قوائم | تم تحديث %count% قائمة | تم تحديث %count% قائمة", + "list_updated": "| تم تحديث قائمة واحدة | تم تحديث قائمتين | تم تحديث %count% قوائم | تم تحديث %count% قائمة | تم تحديث %count% قائمة", "login": "تسجيل الدخول", "logout": "تسجيل خروج", "make_static": "اجعلها ثابتة", @@ -513,8 +513,8 @@ "password_requirements_uppercase": "على الأقل 1 حرف كبير", "path_to_file_placeholder": "طريق الملف: عنوان محلي أو عنوان على الشبكة العنكبوتية", "pause_for_hour": "إيقاف مؤقت لمدة %count% ساعة", - "pause_for_minutes": "| إيقاف مؤقت لمدة 0 دقيقة | إيقاف مؤقت لمدة دقيقة واحدة | إيقاف مؤقت لمدة دقيقتين | إيقاف مؤقت لمدة %count% دقائق | إيقاف مؤقت لمدة %count% دقيقة | إيقاف مؤقت لمدة %count% دقيقة", - "pause_for_seconds": "| إيقاف مؤقت لمدة 0 ثانية | إيقاف مؤقت لمدة ثانية واحدة | إيقاف مؤقت لمدة ثانيتين | إيقاف مؤقت لمدة %count% ثوانٍ | إيقاف مؤقت لمدة %count% ثانية | إيقاف مؤقت لمدة %count% ثانية", + "pause_for_minutes": "| إيقاف مؤقت لمدة دقيقة واحدة | إيقاف مؤقت لمدة دقيقتين | إيقاف مؤقت لمدة %count% دقائق | إيقاف مؤقت لمدة %count% دقيقة | إيقاف مؤقت لمدة %count% دقيقة", + "pause_for_seconds": "| إيقاف مؤقت لمدة ثانية واحدة | إيقاف مؤقت لمدة ثانيتين | إيقاف مؤقت لمدة %count% ثوانٍ | إيقاف مؤقت لمدة %count% ثانية | إيقاف مؤقت لمدة %count% ثانية", "pause_until_tomorrow": "إيقاف مؤقت حتى الغد، %time%", "period_notify": "لتغيير المدة الزمنية المعروضة، قم بتحرير الاحتفاظ بالاحصائيات في إعدادات الوضع العام", "plain_dns": "عنوان DNS العادي", @@ -635,14 +635,14 @@ "settings_confirm_decrease_stats_rotation_interval": "تقليل فترة الاحتفاظ بالإحصائيات؟", "settings_confirm_decrease_stats_rotation_interval_desc": "سيؤدي هذا إلى حذف جميع الاحصائيات الأقدم من %value%", "settings_custom": "مخصص", - "settings_days": "| 0 يوم | يوم واحد | يومان | %count% أيام | %count% يومًا | %count% يوم", + "settings_days": "| يوم واحد | يومان | %count% أيام | %count% يومًا | %count% يوم", "settings_domain_names": "أسماء النطاقات، واحد في كل سطر", "settings_filter_requests": "تصفية الطلبات", "settings_filter_requests_desc": "يمكنك استخدام Blocklists و Allowlists و قواعد المستخدم لإعداد قواعد التصفية", "settings_filtering_and_security": "التصفية والأمان", "settings_general_short": "الوضع العام", "settings_global": "عالمي", - "settings_hours": "| 0 ساعة | ساعة واحدة | ساعتان | %count% ساعات | %count% ساعة | %count% ساعة", + "settings_hours": "| ساعة واحدة | ساعتان | %count% ساعات | %count% ساعة | %count% ساعة", "settings_log_rotation_hours": "تدوير السجل، بالساعات", "settings_notify_changes_saved": "تم حفظ التغييرات", "settings_notify_query_log_cleared": "تم مسح سجل الاستعلام", diff --git a/client_v2/src/__locales/en.json b/client_v2/src/__locales/en.json index bbaacddcb2f..de98913edd5 100644 --- a/client_v2/src/__locales/en.json +++ b/client_v2/src/__locales/en.json @@ -3,7 +3,6 @@ "add_allowlist": "Add allowlist", "add_blocklist": "Add blocklist", "add_persistent_client": "Add as persistent client", - "add_to_allowlist": "Add to allowlist", "ads_blocked": "Blocked ads", "ads_blocked_card": "Blocked ads", "ads_blocked_tooltip": "The number of DNS queries blocked by adblock filters and hosts blocklist", @@ -12,7 +11,6 @@ "all_lists_up_to_date_toast": "All lists are already up-to-date", "all_rewrites_disabled": "All custom DNS responses will be disabled", "all_rewrites_enabled": "All custom DNS responses will be enabled", - "allow_service": "Allow service", "allowed": "Allowed", "allowlist_add": "Add allowlist", "allowlist_edit": "Edit allowlist", @@ -137,7 +135,7 @@ "dashboard": "Dashboard", "dashboard_statistics_disabled": "Statistics retention is disabled in General settings", "delete_btn": "Delete", - "delete_confirm": "Delete lease?", + "delete_confirm": "Remove lease?", "delete_confirm_desc": "This will free %ip%", "delete_table_action": "Delete", "delete_table_action_confirm": "Yes, delete", @@ -271,6 +269,7 @@ "dns_override_min_ttl_placeholder": "Time-to-live (TTL)", "dns_override_min_ttl_title": "Override minimum TTL", "dns_privacy": "DNS Privacy", + "dns_private_reverse_no_default_resolvers": "AdGuard Home could not determine suitable private reverse DNS resolvers for this system. Specify them to enable this setting.", "dns_private_reverse_resolve_clients_desc": "Resolves client IP addresses to their hostnames using PTR queries. Uses private DNS servers for local clients and upstream servers for clients with public IP addresses", "dns_private_reverse_resolve_clients_title": "Reverse lookup of client IP addresses", "dns_private_reverse_resolvers": "Private reverse DNS resolvers", @@ -280,9 +279,8 @@ "dns_private_reverse_servers_desc_2": "If this field is empty, your operating system's default DNS resolvers are used, except for AdGuard Home IP addresses. By default, AdGuard Home uses the following reverse DNS resolvers: %value_1% and %value_2%", "dns_private_reverse_servers_label": "Private reverse DNS servers, one per line", "dns_private_reverse_servers_placeholder": "IP addresses, sdns://, quic://, https://, h3://, or tls://", + "dns_private_reverse_servers_required": "Specify at least one private reverse DNS server or turn off private reverse DNS resolvers", "dns_private_reverse_servers_resolvers": "Default DNS resolvers: %value_1% and %value_2%", - "dns_private_reverse_servers_title": "Private reverse DNS servers", - "dns_protocols_title": "DNS protocols", "dns_queries": "DNS queries", "dns_queries_tooltip": "The number of DNS queries processed for the last 24 hours", "dns_query": "DNS queries", @@ -299,7 +297,6 @@ "dns_rate_limit_title": "Rate limit", "dns_rate_limit_value": "%value% req/s", "dns_rewrite_exists": "This DNS rewrite already exists", - "dns_rewrite_removed": "DNS rewrite removed", "dns_rewrite_same": "You can’t rewrite to the same domain or wildcard", "dns_rewrites": "DNS rewrites", "dns_rewrites_desc": "Lists your custom DNS responses for specific domain names", @@ -372,8 +369,6 @@ "encryption_server_tooltip": "The domain name of your server. It must match a DNS name in the certificate. If set, AdGuard Home will detect ClientIDs, respond to DDR queries, and perform additional connection validations", "encryption_subject": "Subject: %value%", "encryption_title": "Encryption", - "encryption_unable_read_cert": "Unable to read certificate file", - "encryption_unable_read_key": "Unable to read private key file", "error": "Error", "filter_added_successfully": "Added blocklist: %value%", "filter_added_successfully_allowlist": "Added allowlist: %value%", @@ -404,7 +399,6 @@ "form_error_answer_format": "Invalid result format", "form_error_client_id_format": "ClientID must contain only numbers, lowercase letters, and hyphens", "form_error_domain_format": "Invalid domain format", - "form_error_equal": "Must not be equal", "form_error_format": "Invalid format", "form_error_format_line": "Invalid format on line %line%", "form_error_format_lines": "Invalid format on lines %lines%", @@ -447,15 +441,14 @@ "inactivity_schedule_edit": "Edit schedule", "inactivity_schedule_no_schedules": "No schedule", "inactivity_schedule_replace_desc": "This schedule will replace any existing schedules for the same day of the week. Each day can have only one inactivity period", - "inactivity_schedule_time_from": "Time from", - "inactivity_schedule_time_to": "Time to", + "inactivity_schedule_time_from": "Time from (HH:mm)", + "inactivity_schedule_time_to": "Time to (HH:mm)", "inactivity_schedule_timezone": "Timezone", "install_auth_confirm": "Confirm password", "install_auth_password": "Password", "install_auth_password_enter": "Enter password", "install_auth_username": "Username", "install_auth_username_enter": "Enter username", - "install_saved": "Saved successfully", "install_settings_all_interfaces": "All interfaces", "install_settings_port": "Port", "install_static_configure": "AdGuard Home has detected that the dynamic IP address %ip% is used. Do you want it to be set as your static address?", @@ -519,7 +512,6 @@ "password_requirements_match": "Passwords match", "password_requirements_special": "English letters, numbers, and special characters", "password_requirements_uppercase": "At least 1 uppercase letter", - "path_to_file_placeholder": "Path to file: local or Internet address", "pause_for_hour": "Pause for %count% hour", "pause_for_minutes": "| Pause for %count% minute | Pause for %count% minutes", "pause_for_seconds": "| Pause for %count% second | Pause for %count% seconds", @@ -582,7 +574,7 @@ "remove": "Remove", "remove_tag": "Remove %value%", "remove_tls_certificate": "Remove TLS certificate?", - "remove_tls_certificate_desc": "Clients using encrypted DNS won’t be able to connect until a new TLS certificate is added", + "remove_tls_certificate_desc": "Removing the certificate will disable HTTPS and reset TLS settings. If you are connected over HTTPS, your session will end and you will be redirected to http://%host%:%port%", "report_an_issue": "Report a problem", "request_table_header": "Request", "requests_table_header": "Requests", @@ -621,6 +613,7 @@ "safe_search_used_tooltip": "The number of DNS queries to search engines for which Safe Search was enforced", "saturday": "Saturday", "save": "Save", + "save_anyway": "Save anyway", "save_btn": "Save", "search_placeholder": "Search", "select_language": "Select language", @@ -658,7 +651,7 @@ "settings_notify_query_log_cleared": "Query log cleared", "settings_notify_statistics_cleared": "Statistics cleared", "settings_parental_control": "Parental control", - "settings_parental_control_desc": "Block websites with content inappropriate for children", + "settings_parental_control_desc": "Block websites with inappropriate content, such as pornography, violence, gore, and other disturbing material, using AdGuard’s continuously updated family filter database", "settings_rotation_placeholder": "Use numbers", "settings_rule_syntax": "Rule syntax", "settings_safe_search": "Safe search", @@ -793,7 +786,7 @@ "tls_setup_config_title": "Enable encrypted DNS", "tls_setup_enable_anyway": "Enable anyway", "tls_setup_error_cert_incomplete": "Certificate is incomplete. Paste the full text, including the BEGIN and END lines", - "tls_setup_error_duplicate_port": "Port %port% is used by multiple DNS protocols. It must be unique", + "tls_setup_error_duplicate_port": "Port %port% is used by more than one protocol. Choose a different port for each encrypted DNS protocol", "tls_setup_error_ed25519_key": "This key type is not supported by browsers. Use an RSA or ECDSA key instead", "tls_setup_error_enable_failed": "Unable to enable encrypted DNS. Check the settings and try again", "tls_setup_error_key_incomplete": "Private key is incomplete. Paste the full text, including the BEGIN and END lines", diff --git a/client_v2/src/__locales/hr.json b/client_v2/src/__locales/hr.json index 2f61c282675..6cba256b700 100644 --- a/client_v2/src/__locales/hr.json +++ b/client_v2/src/__locales/hr.json @@ -460,11 +460,11 @@ "ip_address": "IP adresa", "known_tracker": "Poznati pratitelj", "language": "Jezik", - "last_days": "| Zadnji %count% dan | Zadnjih %count% dana", - "last_hours": "| Zadnjih %count% sat | Zadnjih %count% sati", + "last_days": "| Zadnji %count% dan | Zadnja %count% dana | Zadnjih %count% dana", + "last_hours": "| Zadnjih %count% sat | Zadnja %count% sata | Zadnjih %count% sati", "last_updated_label": "Zadnja izmjena", "light_theme": "Svijetla tema", - "list_updated": "| %count% popis ažuriran | %count% popisi ažurirani", + "list_updated": "| %count% popis ažuriran | %count% popisa ažurirana | %count% popisi ažurirani", "login": "PRIJAVA", "logout": "Odjava", "make_static": "Učini statičnim", @@ -513,8 +513,8 @@ "password_requirements_uppercase": "Najmanje jedno veliko slovo", "path_to_file_placeholder": "Put do datoteke: lokalna ili internetska adresa", "pause_for_hour": "Pauza na %count% sat", - "pause_for_minutes": "| Pauza od %count% minute | Pauza od %count% minuta", - "pause_for_seconds": "| Pauza %count% sekunde | Pauza na %count% sekunde", + "pause_for_minutes": "| Pauza od %count% minute | Pauza od %count% minute | Pauza od %count% minuta", + "pause_for_seconds": "| Pauza %count% sekunde | Pauza na %count% sekunde | Pauza na %count% sekunde", "pause_until_tomorrow": "Pauza do sutra, %time%", "period_notify": "Za promjenu prikazanih razdoblja uredite Zadržavanje statistike u Općim postavkama", "plain_dns": "Obični DNS", @@ -635,14 +635,14 @@ "settings_confirm_decrease_stats_rotation_interval": "Smanjiti interval zadržavanja statistika?", "settings_confirm_decrease_stats_rotation_interval_desc": "To će izbrisati sve statistike starije od %value%", "settings_custom": "Prilagođeno", - "settings_days": "| %count% dan | %count% dana", + "settings_days": "| %count% dan | %count% dana | %count% dana", "settings_domain_names": "Domene, po jedna po liniji", "settings_filter_requests": "Zahtjevi za filtriranje", "settings_filter_requests_desc": "Možete koristiti Blocklists, Allowlists i Korisnička pravila za postavljanje pravila filtriranja", "settings_filtering_and_security": "Filtriranje i sigurnost", "settings_general_short": "Općenito", "settings_global": "Globalno", - "settings_hours": "| %count% sat | %count% sati", + "settings_hours": "| %count% sat | %count% sata | %count% sati", "settings_log_rotation_hours": "Rotacija trupaca, u satima", "settings_notify_changes_saved": "Promjene su spremljene", "settings_notify_query_log_cleared": "Dnevnik upita očišćen", diff --git a/client_v2/src/__tests__/common/controls/Textarea.test.tsx b/client_v2/src/__tests__/common/controls/Textarea.test.tsx index 1aaa17ad70f..461001beb79 100644 --- a/client_v2/src/__tests__/common/controls/Textarea.test.tsx +++ b/client_v2/src/__tests__/common/controls/Textarea.test.tsx @@ -115,3 +115,35 @@ describe('Textarea — comment highlight', () => { expect(overlay?.parentElement).toBe(textarea?.parentElement); }); }); + +describe('Textarea — onCard', () => { + it('applies the onCard class to the field when set', () => { + const { container } = render(() =>