+
{value}
{trackerData &&
}
diff --git a/client/src/components/Logs/Cells/getClientCell.js b/client/src/components/Logs/Cells/getClientCell.js
index 2ebca672..00d5536c 100644
--- a/client/src/components/Logs/Cells/getClientCell.js
+++ b/client/src/components/Logs/Cells/getClientCell.js
@@ -33,7 +33,7 @@ const getClientCell = ({
const isFiltered = checkFiltered(reason);
const nameClass = classNames('w-90 o-hidden d-flex flex-column', {
- 'mt-2': isDetailed && !name,
+ 'mt-2': isDetailed && !name && !whois_info,
'white-space--nowrap': isDetailed,
});
@@ -80,9 +80,9 @@ const getClientCell = ({
})}
-
{formatClientCell(row, t, isDetailed)}
+
{formatClientCell(row, isDetailed)}
{isDetailed && name
- &&
{name}
}
{renderBlockingButton(isFiltered, domain)}
diff --git a/client/src/components/Logs/Cells/getResponseCell.js b/client/src/components/Logs/Cells/getResponseCell.js
index fcc2e5a0..6690c0f6 100644
--- a/client/src/components/Logs/Cells/getResponseCell.js
+++ b/client/src/components/Logs/Cells/getResponseCell.js
@@ -9,8 +9,7 @@ import getHintElement from './getHintElement';
const getResponseCell = (row, filtering, t, isDetailed, getFilterName) => {
const {
- reason, filterId, rule, status, upstream, elapsedMs,
- domain, response, originalResponse,
+ reason, filterId, rule, status, upstream, elapsedMs, response, originalResponse,
} = row.original;
const { filters, whitelistFilters } = filtering;
@@ -41,7 +40,6 @@ const getResponseCell = (row, filtering, t, isDetailed, getFilterName) => {
const FILTERED_STATUS_TO_FIELDS_MAP = {
[FILTERED_STATUS.NOT_FILTERED_NOT_FOUND]: {
- domain,
encryption_status: boldStatusLabel,
install_settings_dns: upstream,
elapsed: formattedElapsedMs,
@@ -49,7 +47,6 @@ const getResponseCell = (row, filtering, t, isDetailed, getFilterName) => {
response_table_header: renderResponses(response),
},
[FILTERED_STATUS.FILTERED_BLOCKED_SERVICE]: {
- domain,
encryption_status: boldStatusLabel,
install_settings_dns: upstream,
elapsed: formattedElapsedMs,
@@ -59,7 +56,6 @@ const getResponseCell = (row, filtering, t, isDetailed, getFilterName) => {
original_response: renderResponses(originalResponse),
},
[FILTERED_STATUS.NOT_FILTERED_WHITE_LIST]: {
- domain,
encryption_status: boldStatusLabel,
install_settings_dns: upstream,
elapsed: formattedElapsedMs,
@@ -68,21 +64,19 @@ const getResponseCell = (row, filtering, t, isDetailed, getFilterName) => {
response_code: status,
},
[FILTERED_STATUS.NOT_FILTERED_WHITE_LIST]: {
- domain,
encryption_status: boldStatusLabel,
filter,
rule_label: rule,
response_code: status,
},
[FILTERED_STATUS.FILTERED_SAFE_SEARCH]: {
- domain,
encryption_status: boldStatusLabel,
install_settings_dns: upstream,
elapsed: formattedElapsedMs,
response_code: status,
+ response_table_header: renderResponses(response),
},
[FILTERED_STATUS.FILTERED_BLACK_LIST]: {
- domain,
encryption_status: boldStatusLabel,
filter,
rule_label: rule,
@@ -93,7 +87,7 @@ const getResponseCell = (row, filtering, t, isDetailed, getFilterName) => {
},
};
- const fields = FILTERED_STATUS_TO_FIELDS_MAP[reason]
+ const content = FILTERED_STATUS_TO_FIELDS_MAP[reason]
? Object.entries(FILTERED_STATUS_TO_FIELDS_MAP[reason])
: Object.entries(FILTERED_STATUS_TO_FIELDS_MAP.NotFilteredNotFound);
@@ -108,7 +102,7 @@ const getResponseCell = (row, filtering, t, isDetailed, getFilterName) => {
contentItemClass: 'text-truncate key-colon o-hidden',
xlinkHref: 'question',
title: 'response_details',
- content: fields,
+ content,
placement: 'bottom',
})}
diff --git a/client/src/components/Logs/Filters/Form.js b/client/src/components/Logs/Filters/Form.js
index 42145c64..d70153c1 100644
--- a/client/src/components/Logs/Filters/Form.js
+++ b/client/src/components/Logs/Filters/Form.js
@@ -144,18 +144,20 @@ const Form = (props) => {
e.preventDefault();
}}
>
-
+
+
+
.-loading-inner {
top: 10rem !important;
bottom: initial !important;
diff --git a/client/src/components/Logs/Table.js b/client/src/components/Logs/Table.js
index 131db854..fcf8daa4 100644
--- a/client/src/components/Logs/Table.js
+++ b/client/src/components/Logs/Table.js
@@ -25,7 +25,7 @@ import {
formatDateTime,
formatElapsedMs,
formatTime,
-
+ processContent,
} from '../../helpers/helpers';
import Loading from '../ui/Loading';
import { getSourceData } from '../../helpers/trackers/trackers';
@@ -302,6 +302,7 @@ const Table = (props) => {
filterId,
rule,
originalResponse,
+ status,
} = rowInfo.original;
const hasTracker = !!tracker;
@@ -328,17 +329,20 @@ const Table = (props) => {
};
const isBlockedByResponse = originalResponse.length > 0 && isBlocked;
- const status = t(isBlockedByResponse ? 'blocked_by_cname_or_ip' : FILTERED_STATUS_TO_META_MAP[reason]?.label || reason);
- const statusBlocked = {status}
;
+ const requestStatus = t(isBlockedByResponse ? 'blocked_by_cname_or_ip' : FILTERED_STATUS_TO_META_MAP[reason]?.label || reason);
const protocol = t(SCHEME_TO_PROTOCOL_MAP[client_proto]) || '';
const sourceData = getSourceData(tracker);
+ const { filters, whitelistFilters } = filtering;
+ const filter = getFilterName(filters, whitelistFilters, filterId, t);
+
const detailedData = {
time_table_header: formatTime(time, LONG_TIME_FORMAT),
date: formatDateTime(time, DEFAULT_SHORT_DATE_FORMAT_OPTIONS),
- encryption_status: status,
+ encryption_status: isBlocked
+ ? {requestStatus}
: requestStatus,
domain,
type_table_header: type,
protocol,
@@ -346,12 +350,19 @@ const Table = (props) => {
table_name: tracker?.name,
category_label: hasTracker && captitalizeWords(tracker.category),
tracker_source: hasTracker && sourceData
- && {sourceData.name},
+ && {sourceData.name}
+ ,
response_details: 'title',
install_settings_dns: upstream,
elapsed: formattedElapsedMs,
+ filter: isBlocked ? filter : null,
+ rule_label: rule,
response_table_header: response?.join('\n'),
+ response_code: status,
client_details: 'title',
ip_address: client,
name: info?.name,
@@ -360,41 +371,14 @@ const Table = (props) => {
network,
source_label: source,
validated_with_dnssec: dnssec_enabled ? Boolean(answer_dnssec) : false,
- [buttonType]: {t(buttonType)}
,
- };
-
- const { filters, whitelistFilters } = filtering;
-
- const filter = getFilterName(filters, whitelistFilters, filterId, t);
-
- const detailedDataBlocked = {
- time_table_header: formatTime(time, LONG_TIME_FORMAT),
- date: formatDateTime(time, DEFAULT_SHORT_DATE_FORMAT_OPTIONS),
- encryption_status: statusBlocked,
- domain,
- type_table_header: type,
- protocol,
- known_tracker: 'title',
- table_name: tracker?.name,
- category_label: hasTracker && captitalizeWords(tracker.category),
- source_label: hasTracker && sourceData
- && {sourceData.name},
- response_details: 'title',
- install_settings_dns: upstream,
- elapsed: formattedElapsedMs,
- filter,
- rule_label: rule,
- response_table_header: response?.join('\n'),
original_response: originalResponse?.join('\n'),
[buttonType]: {t(buttonType)}
,
+ className={classNames('title--border text-center', {
+ 'bg--danger': isBlocked,
+ })}>{t(buttonType)} ,
};
- const detailedDataCurrent = isBlocked ? detailedDataBlocked : detailedData;
-
- setDetailedDataCurrent(detailedDataCurrent);
+ setDetailedDataCurrent(processContent(detailedData));
setButtonType(buttonType);
setModalOpened(true);
}
diff --git a/client/src/components/Logs/index.js b/client/src/components/Logs/index.js
index b328e34e..f889fead 100644
--- a/client/src/components/Logs/index.js
+++ b/client/src/components/Logs/index.js
@@ -5,6 +5,7 @@ import Modal from 'react-modal';
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom';
import queryString from 'query-string';
+import classNames from 'classnames';
import {
BLOCK_ACTIONS,
TABLE_DEFAULT_PAGE_SIZE,
@@ -27,7 +28,7 @@ import {
import { addSuccessToast } from '../../actions/toasts';
import './Logs.css';
-export const processContent = (data, buttonType) => Object.entries(data)
+const processContent = (data, buttonType) => Object.entries(data)
.map(([key, value]) => {
if (!value) {
return null;
@@ -49,7 +50,9 @@ export const processContent = (data, buttonType) => Object.entries(data)
return isHidden ? null :
+ className={classNames(`key__${key}`, keyClass, {
+ 'font-weight-bold': isBoolean && value === true,
+ })}>
{isButton ? value : key}
@@ -133,7 +136,16 @@ const Logs = (props) => {
};
useEffect(() => {
- mediaQuery.addEventListener('change', mediaQueryHandler);
+ try {
+ mediaQuery.addEventListener('change', mediaQueryHandler);
+ } catch (e1) {
+ try {
+ // Safari 13.1 do not support mediaQuery.addEventListener('change', handler)
+ mediaQuery.addListener(mediaQueryHandler);
+ } catch (e2) {
+ console.error(e2);
+ }
+ }
(async () => {
setIsLoading(true);
@@ -153,7 +165,16 @@ const Logs = (props) => {
})();
return () => {
- mediaQuery.removeEventListener('change', mediaQueryHandler);
+ try {
+ mediaQuery.removeEventListener('change', mediaQueryHandler);
+ } catch (e1) {
+ try {
+ mediaQuery.removeListener(mediaQueryHandler);
+ } catch (e2) {
+ console.error(e2);
+ }
+ }
+
dispatch(resetFilteredLogs());
};
}, []);
diff --git a/client/src/components/Settings/Clients/ClientsTable.js b/client/src/components/Settings/Clients/ClientsTable.js
index e767cfb9..a179ac30 100644
--- a/client/src/components/Settings/Clients/ClientsTable.js
+++ b/client/src/components/Settings/Clients/ClientsTable.js
@@ -4,7 +4,7 @@ import { Trans, withTranslation } from 'react-i18next';
import ReactTable from 'react-table';
import { MODAL_TYPE } from '../../../helpers/constants';
-import { normalizeTextarea } from '../../../helpers/helpers';
+import { splitByNewLine } from '../../../helpers/helpers';
import Card from '../../ui/Card';
import Modal from './Modal';
import CellWrap from '../../ui/CellWrap';
@@ -30,7 +30,7 @@ class ClientsTable extends Component {
}
if (values.upstreams && typeof values.upstreams === 'string') {
- config.upstreams = normalizeTextarea(values.upstreams);
+ config.upstreams = splitByNewLine(values.upstreams);
} else {
config.upstreams = [];
}
diff --git a/client/src/components/Settings/Dns/Access/Form.js b/client/src/components/Settings/Dns/Access/Form.js
index 8edc3189..4f8342f0 100644
--- a/client/src/components/Settings/Dns/Access/Form.js
+++ b/client/src/components/Settings/Dns/Access/Form.js
@@ -4,7 +4,10 @@ import { Field, reduxForm } from 'redux-form';
import { Trans, withTranslation } from 'react-i18next';
import flow from 'lodash/flow';
import { renderTextareaField } from '../../../../helpers/form';
-import { normalizeMultiline } from '../../../../helpers/helpers';
+import {
+ trimMultilineString,
+ removeEmptyLines,
+} from '../../../../helpers/helpers';
import { FORM_NAME } from '../../../../helpers/constants';
const fields = [
@@ -12,16 +15,19 @@ const fields = [
id: 'allowed_clients',
title: 'access_allowed_title',
subtitle: 'access_allowed_desc',
+ normalizeOnBlur: removeEmptyLines,
},
{
id: 'disallowed_clients',
title: 'access_disallowed_title',
subtitle: 'access_disallowed_desc',
+ normalizeOnBlur: trimMultilineString,
},
{
id: 'blocked_hosts',
title: 'access_blocked_title',
subtitle: 'access_blocked_desc',
+ normalizeOnBlur: removeEmptyLines,
},
];
@@ -31,7 +37,7 @@ const Form = (props) => {
} = props;
const renderField = ({
- id, title, subtitle, disabled = processingSet,
+ id, title, subtitle, disabled = processingSet, normalizeOnBlur,
}) =>
;
@@ -55,6 +61,7 @@ const Form = (props) => {
title: PropTypes.string,
subtitle: PropTypes.string,
disabled: PropTypes.bool,
+ normalizeOnBlur: PropTypes.func,
};
return (
diff --git a/client/src/components/Settings/Dns/Upstream/Form.js b/client/src/components/Settings/Dns/Upstream/Form.js
index 99ae9a95..8174b54e 100644
--- a/client/src/components/Settings/Dns/Upstream/Form.js
+++ b/client/src/components/Settings/Dns/Upstream/Form.js
@@ -6,9 +6,10 @@ import { Trans, useTranslation } from 'react-i18next';
import classnames from 'classnames';
import Examples from './Examples';
-import { renderRadioField } from '../../../../helpers/form';
+import { renderRadioField, renderTextareaField } from '../../../../helpers/form';
import { DNS_REQUEST_OPTIONS, FORM_NAME } from '../../../../helpers/constants';
import { testUpstream } from '../../../../actions';
+import { removeEmptyLines } from '../../../../helpers/helpers';
const getInputFields = () => [{
// eslint-disable-next-line react/display-name
@@ -17,9 +18,10 @@ const getInputFields = () => [{
,
name: 'upstream_dns',
type: 'text',
- component: 'textarea',
+ component: renderTextareaField,
className: 'form-control form-control--textarea font-monospace',
placeholder: 'upstream_dns',
+ normalizeOnBlur: removeEmptyLines,
},
{
name: 'upstream_mode',
@@ -69,7 +71,8 @@ const Form = ({
return