From d1e969c38ecd7db89bc53ec5108d67f88f04f342 Mon Sep 17 00:00:00 2001 From: Ildar Kamalov Date: Mon, 16 Oct 2023 18:00:28 +0300 Subject: [PATCH] Pull request: 684 move block/unblock button to the tooltip menu Updates #684 Squashed commit of the following: commit 2c5ac44d3edb55d0d3be169fb0bbfb336920964d Merge: 0fce61dfa 733d6c1fc Author: Ildar Kamalov Date: Mon Oct 16 10:08:58 2023 +0300 Merge branch 'master' into ADG-7200 commit 0fce61dfad31951c3d5a484a14383c58964b47f0 Author: Ildar Kamalov Date: Fri Oct 13 16:38:13 2023 +0300 fix dashboard clients table block/unblock button commit ef5d72fd7cac81b70503c8813cf6e96952ec3b65 Merge: f49281b88 506d71310 Author: Ildar Kamalov Date: Fri Oct 13 16:16:21 2023 +0300 Merge branch 'master' into ADG-7200 commit f49281b8818728ab298d769b8164919ea415d6c9 Author: Ildar Kamalov Date: Thu Oct 12 11:25:05 2023 +0300 fix disabled commit 0031861174108214e9741852f6e00c5873c3b20f Author: Ildar Kamalov Date: Thu Oct 12 11:20:50 2023 +0300 fix icon color commit 2916937b0d6a0d126bd48e59f41a6fcbc4622ea1 Author: Ildar Kamalov Date: Thu Oct 12 11:15:55 2023 +0300 changelog commit 34493c974fb9304267e9149360c802d9364dd7de Merge: d3267bbe9 d3fabdda4 Author: Ildar Kamalov Date: Thu Oct 12 11:13:43 2023 +0300 Merge branch 'master' into ADG-7200 commit d3267bbe9477d6db0783534cb4ab4f7afc4d63b0 Merge: 58a6c766f 6a3661562 Author: Ildar Kamalov Date: Wed Oct 11 16:46:39 2023 +0300 Merge branch 'master' into ADG-7200 commit 58a6c766f3b783f0e2fdc36d40889042f3c74f2f Author: Ildar Kamalov Date: Wed Oct 11 16:46:13 2023 +0300 ADG-7200 move block/unblock button to the tooltip menu --- CHANGELOG.md | 5 ++ client/src/components/App/index.css | 9 --- client/src/components/Dashboard/Clients.js | 47 +++++++++--- client/src/components/Dashboard/Dashboard.css | 12 +-- .../src/components/Logs/Cells/ClientCell.js | 76 +++++++++---------- .../src/components/Logs/Cells/IconTooltip.css | 1 + .../src/components/Logs/Cells/IconTooltip.js | 6 ++ client/src/components/Logs/Logs.css | 59 ++++++-------- client/src/components/ui/Icons.js | 6 ++ client/src/components/ui/Tooltip.js | 3 + .../src/helpers/renderFormattedClientCell.js | 2 +- 11 files changed, 124 insertions(+), 102 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb067fe85e3..51bb4c407ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,12 +23,17 @@ See also the [v0.107.40 GitHub milestone][ms-v0.107.40]. NOTE: Add new changes BELOW THIS COMMENT. --> +### Changed + +- "Block" and "Unblock" buttons of the query log moved to the tooltip menu ([#684]). + ### Fixed - The time shown in the statistics is one hour less than the current time ([#6296]). - Issues with QUIC and HTTP/3 upstreams on FreeBSD ([#6301]). - Panic on clearing query log ([#6304]). +[#684]: https://github.com/AdguardTeam/AdGuardHome/issues/684 [#6296]: https://github.com/AdguardTeam/AdGuardHome/issues/6296 [#6301]: https://github.com/AdguardTeam/AdGuardHome/issues/6301 [#6304]: https://github.com/AdguardTeam/AdGuardHome/issues/6304 diff --git a/client/src/components/App/index.css b/client/src/components/App/index.css index 78bd0096e8d..91cd17490fe 100644 --- a/client/src/components/App/index.css +++ b/client/src/components/App/index.css @@ -134,15 +134,6 @@ body { cursor: not-allowed; } -.button-action { - visibility: hidden; -} - -.logs__row:hover .button-action, -.button-action--active { - visibility: visible; -} - .ReactModal__Body--open { overflow: hidden; } diff --git a/client/src/components/Dashboard/Clients.js b/client/src/components/Dashboard/Clients.js index 76cf998a533..ac2434912c4 100644 --- a/client/src/components/Dashboard/Clients.js +++ b/client/src/components/Dashboard/Clients.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import ReactTable from 'react-table'; import PropTypes from 'prop-types'; import { Trans, useTranslation } from 'react-i18next'; @@ -13,6 +13,7 @@ import { BLOCK_ACTIONS, STATUS_COLORS } from '../../helpers/constants'; import { toggleClientBlock } from '../../actions/access'; import { renderFormattedClientCell } from '../../helpers/renderFormattedClientCell'; import { getStats } from '../../actions/stats'; +import IconTooltip from '../Logs/Cells/IconTooltip'; const getClientsPercentColor = (percent) => { if (percent > 50) { @@ -40,9 +41,7 @@ const renderBlockingButton = (ip, disallowed, disallowed_rule) => { const processingSet = useSelector((state) => state.access.processingSet); const allowedСlients = useSelector((state) => state.access.allowed_clients, shallowEqual); - const buttonClass = classNames('button-action button-action--main', { - 'button-action--unblock': disallowed, - }); + const [isOptionsOpened, setOptionsOpened] = useState(false); const toggleClientStatus = async (ip, disallowed, disallowed_rule) => { let confirmMessage; @@ -62,23 +61,49 @@ const renderBlockingButton = (ip, disallowed, disallowed_rule) => { } }; - const onClick = () => toggleClientStatus(ip, disallowed, disallowed_rule); + const onClick = () => { + toggleClientStatus(ip, disallowed, disallowed_rule); + setOptionsOpened(false); + }; const text = disallowed ? BLOCK_ACTIONS.UNBLOCK : BLOCK_ACTIONS.BLOCK; const lastRuleInAllowlist = !disallowed && allowedСlients === disallowed_rule; const disabled = processingSet || lastRuleInAllowlist; return ( -
+
+ {isOptionsOpened && ( + + {text} + + )} + placement="bottom-end" + trigger="click" + onVisibilityChange={setOptionsOpened} + defaultTooltipShown={true} + delayHide={0} + /> + )}
); }; diff --git a/client/src/components/Dashboard/Dashboard.css b/client/src/components/Dashboard/Dashboard.css index 765c9ed1322..67a69aec406 100644 --- a/client/src/components/Dashboard/Dashboard.css +++ b/client/src/components/Dashboard/Dashboard.css @@ -28,11 +28,13 @@ border-bottom: 6px solid #585965; } -@media (max-width: 1279.98px) { - .table__action { - position: absolute; - right: 0; - } +.table__action { + position: relative; + margin-left: auto; +} + +.table__action .btn-icon { + margin: 2px; } .page-title--dashboard { diff --git a/client/src/components/Logs/Cells/ClientCell.js b/client/src/components/Logs/Cells/ClientCell.js index 3590df4890f..d0dd316850a 100644 --- a/client/src/components/Logs/Cells/ClientCell.js +++ b/client/src/components/Logs/Cells/ClientCell.js @@ -26,9 +26,7 @@ const ClientCell = ({ const { t } = useTranslation(); const dispatch = useDispatch(); const autoClients = useSelector((state) => state.dashboard.autoClients, shallowEqual); - const processingRules = useSelector((state) => state.filtering.processingRules); const isDetailed = useSelector((state) => state.queryLogs.isDetailed); - const processingSet = useSelector((state) => state.access.processingSet); const allowedСlients = useSelector((state) => state.access.allowed_clients, shallowEqual); const [isOptionsOpened, setOptionsOpened] = useState(false); @@ -84,11 +82,23 @@ const ClientCell = ({ const blockingForClientKey = isFiltered ? 'unblock_for_this_client_only' : 'block_for_this_client_only'; const clientNameBlockingFor = getBlockingClientName(clients, client); + const onClick = async () => { + await dispatch(toggleBlocking(buttonType, domain)); + await dispatch(getStats()); + setOptionsOpened(false); + }; + const BUTTON_OPTIONS = [ + { + name: buttonType, + onClick, + className: isFiltered ? 'bg--green' : 'bg--danger', + }, { name: blockingForClientKey, onClick: () => { dispatch(toggleBlockingForClient(buttonType, domain, clientNameBlockingFor)); + setOptionsOpened(false); }, }, { @@ -101,27 +111,25 @@ const ClientCell = ({ client_info?.disallowed_rule || '', )); await dispatch(updateLogs()); + setOptionsOpened(false); } }, - disabled: processingSet || lastRuleInAllowlist, + disabled: lastRuleInAllowlist, }, ]; - const onClick = async () => { - await dispatch(toggleBlocking(buttonType, domain)); - await dispatch(getStats()); - }; - const getOptions = (options) => { if (options.length === 0) { return null; } return ( <> - {options.map(({ name, onClick, disabled }) => ( + {options.map(({ + name, onClick, disabled, className, + }) => ( - {content && ( - + {isOptionsOpened && ( + )}
); @@ -198,7 +196,7 @@ const ClientCell = ({ {isDetailed && clientName && !whoisAvailable && ( diff --git a/client/src/components/Logs/Cells/IconTooltip.css b/client/src/components/Logs/Cells/IconTooltip.css index 0b55ee6a0fe..bbaf1604f69 100644 --- a/client/src/components/Logs/Cells/IconTooltip.css +++ b/client/src/components/Logs/Cells/IconTooltip.css @@ -1,4 +1,5 @@ .tooltip-custom__container { + min-width: 150px; padding: 1rem 1.5rem 1.25rem 1.5rem; font-size: 16px !important; box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.2); diff --git a/client/src/components/Logs/Cells/IconTooltip.js b/client/src/components/Logs/Cells/IconTooltip.js index 8bb3d624395..304aded8609 100644 --- a/client/src/components/Logs/Cells/IconTooltip.js +++ b/client/src/components/Logs/Cells/IconTooltip.js @@ -21,6 +21,8 @@ const IconTooltip = ({ content, trigger, onVisibilityChange, + defaultTooltipShown, + delayHide, renderContent = content ? React.Children.map( processContent(content), (item, idx) =>
@@ -44,6 +46,8 @@ const IconTooltip = ({ trigger={trigger} onVisibilityChange={onVisibilityChange} delayShow={trigger === 'click' ? 0 : SHOW_TOOLTIP_DELAY} + delayHide={delayHide} + defaultTooltipShown={defaultTooltipShown} > {xlinkHref && @@ -65,6 +69,8 @@ IconTooltip.propTypes = { content: PropTypes.node, renderContent: PropTypes.arrayOf(PropTypes.element), onVisibilityChange: PropTypes.func, + defaultTooltipShown: PropTypes.bool, + delayHide: PropTypes.number, }; export default IconTooltip; diff --git a/client/src/components/Logs/Logs.css b/client/src/components/Logs/Logs.css index 762dfa503ca..4935192a3bd 100644 --- a/client/src/components/Logs/Logs.css +++ b/client/src/components/Logs/Logs.css @@ -80,6 +80,10 @@ color: var(--gray-f3); } +.logs__text--client { + padding-right: 32px; +} + .icon--selected { background-color: var(--gray-f3); border: solid 1px var(--gray-d8); @@ -261,9 +265,8 @@ .button-action__container { display: flex; position: absolute; - right: 0; + right: 2px; bottom: 0.5rem; - height: 1.6rem; } @media screen and (max-width: 1024px) { @@ -307,45 +310,10 @@ border-bottom-right-radius: 0; } -.button-action--arrow { - border-top-left-radius: 0; - border-bottom-left-radius: 0; - border-left: 1px solid var(--white); - width: 1.5625rem; - padding: 0; - display: flex; - align-items: center; - justify-content: center; -} - .button-action:hover { cursor: pointer; } -.button-action--arrow .button-action--icon { - width: 100%; - height: 100%; - display: flex; - justify-content: center; -} - -.button-action:active { - background: var(--btn-block-active); -} - -.button-action--unblock:active { - background: var(--btn-unblock-active); -} - -.button-action:disabled { - background: var(--btn-block-disabled); - cursor: default; -} - -.button-action--unblock:disabled { - background: var(--btn-unblock-disabled); -} - .button-action--arrow-option { background: transparent; border: 0; @@ -551,3 +519,20 @@ padding: 1rem 1.5rem; background-color: var(--card-bgcolor); } + +.button-action__hidden-trigger { + position: absolute; + top: 0; + right: 0; + width: 1px; + height: 33px; + margin: -1px; + padding: 0; + overflow: hidden; + border: 0; + clip: rect(0 0 0 0); +} + +[data-theme="dark"] .button-action__icon { + color: var(--gray-f3); +} diff --git a/client/src/components/ui/Icons.js b/client/src/components/ui/Icons.js index 288eadfc231..af5ca52c2b0 100644 --- a/client/src/components/ui/Icons.js +++ b/client/src/components/ui/Icons.js @@ -239,6 +239,12 @@ const Icons = () => ( + + + + + + ); diff --git a/client/src/components/ui/Tooltip.js b/client/src/components/ui/Tooltip.js index 87b353de20f..b72a36670bd 100644 --- a/client/src/components/ui/Tooltip.js +++ b/client/src/components/ui/Tooltip.js @@ -21,6 +21,7 @@ const Tooltip = ({ delayShow = SHOW_TOOLTIP_DELAY, delayHide = HIDE_TOOLTIP_DELAY, onVisibilityChange, + defaultTooltipShown, }) => { const { t } = useTranslation(); const touchEventsAvailable = 'ontouchstart' in window; @@ -75,6 +76,7 @@ const Tooltip = ({ delayShow={delayShowValue} tooltip={renderTooltip} onVisibilityChange={onVisibilityChange} + defaultTooltipShown={defaultTooltipShown} > {renderTrigger} @@ -97,6 +99,7 @@ Tooltip.propTypes = { className: propTypes.string, triggerClass: propTypes.string, onVisibilityChange: propTypes.func, + defaultTooltipShown: propTypes.bool, }; export default Tooltip; diff --git a/client/src/helpers/renderFormattedClientCell.js b/client/src/helpers/renderFormattedClientCell.js index 3e610430b90..e70b6548ccb 100644 --- a/client/src/helpers/renderFormattedClientCell.js +++ b/client/src/helpers/renderFormattedClientCell.js @@ -43,7 +43,7 @@ export const renderFormattedClientCell = (value, info, isDetailed = false, isLog const whoisAvailable = whois_info && Object.keys(whois_info).length > 0; if (name) { - const nameValue =
+ const nameValue =
{name} {`(${value})`}
;