Files
AdGuardHome/client/src/components/Logs/Cells/DomainCell.js
Ildar Kamalov cc2388e0c8 Pull request: 4815 fix query log modal on tablet
Updates #4815

Squashed commit of the following:

commit 148c39ac40963a593885b86a0c851b4010b68ab0
Merge: 3447611d ab6da05b
Author: Ildar Kamalov <ik@adguard.com>
Date:   Tue Sep 20 13:21:06 2022 +0300

    Merge branch 'master' into 4815-tablet-view

commit 3447611dc0b1c7d2cc1f8235d1c469dd92736166
Author: Ildar Kamalov <ik@adguard.com>
Date:   Fri Sep 16 17:01:05 2022 +0300

    client: fix query log modal on tablet
2022-09-20 13:48:57 +03:00

183 lines
5.5 KiB
JavaScript

import React from 'react';
import { useSelector } from 'react-redux';
import classNames from 'classnames';
import propTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import {
DEFAULT_SHORT_DATE_FORMAT_OPTIONS,
LONG_TIME_FORMAT,
SCHEME_TO_PROTOCOL_MAP,
} from '../../../helpers/constants';
import { captitalizeWords, formatDateTime, formatTime } from '../../../helpers/helpers';
import { getSourceData } from '../../../helpers/trackers/trackers';
import IconTooltip from './IconTooltip';
const DomainCell = ({
answer_dnssec,
client_proto,
domain,
unicodeName,
time,
tracker,
type,
ecs,
}) => {
const { t } = useTranslation();
const dnssec_enabled = useSelector((state) => state.dnsConfig.dnssec_enabled);
const isDetailed = useSelector((state) => state.queryLogs.isDetailed);
const hasTracker = !!tracker;
const lockIconClass = classNames('icons icon--24 d-none d-sm-block', {
'icon--green': answer_dnssec,
'icon--disabled': !answer_dnssec,
'my-3': isDetailed,
});
const privacyIconClass = classNames('icons mx-2 icon--24 d-none d-sm-block logs__question', {
'icon--green': hasTracker,
'icon--disabled': !hasTracker,
'my-3': isDetailed,
});
const protocol = t(SCHEME_TO_PROTOCOL_MAP[client_proto]) || '';
const ip = type ? `${t('type_table_header')}: ${type}` : '';
let requestDetailsObj = {
time_table_header: formatTime(time, LONG_TIME_FORMAT),
date: formatDateTime(time, DEFAULT_SHORT_DATE_FORMAT_OPTIONS),
domain,
};
if (domain && unicodeName) {
requestDetailsObj = {
...requestDetailsObj,
domain: unicodeName,
punycode: domain,
};
}
if (ecs) {
requestDetailsObj = {
...requestDetailsObj,
ecs,
};
}
requestDetailsObj = {
...requestDetailsObj,
type_table_header: type,
protocol,
};
const sourceData = getSourceData(tracker);
const knownTrackerDataObj = {
name_table_header: tracker?.name,
category_label: hasTracker && captitalizeWords(tracker.category),
source_label: sourceData && (
<a
href={sourceData.url}
target="_blank"
rel="noopener noreferrer"
className="link--green"
>
{sourceData.name}
</a>
),
};
const renderGrid = (content, idx) => {
const preparedContent = typeof content === 'string' ? t(content) : content;
const className = classNames(
'text-truncate o-hidden',
{ 'overflow-break': preparedContent?.length > 100 },
);
return (
<div key={idx} className={className}>
{preparedContent}
</div>
);
};
const getGrid = (contentObj, title, className) => [
<div key={title} className={classNames('pb-2 grid--title', className)}>
{t(title)}
</div>,
<div key={`${title}-1`} className="grid grid--limited">
{React.Children.map(Object.entries(contentObj), renderGrid)}
</div>,
];
const requestDetails = getGrid(requestDetailsObj, 'request_details');
const renderContent = hasTracker ? requestDetails.concat(getGrid(knownTrackerDataObj, 'known_tracker', 'pt-4')) : requestDetails;
const valueClass = classNames('w-100 text-truncate', {
'px-2 d-flex justify-content-center flex-column': isDetailed,
});
const details = [ip, protocol].filter(Boolean).join(', ');
return (
<div
className="d-flex o-hidden logs__cell logs__cell logs__cell--domain"
role="gridcell"
>
{dnssec_enabled && (
<IconTooltip
className={lockIconClass}
tooltipClass="py-4 px-5 pb-45"
canShowTooltip={!!answer_dnssec}
xlinkHref="lock"
columnClass="w-100"
content="validated_with_dnssec"
placement="bottom"
/>
)}
<IconTooltip
className={privacyIconClass}
tooltipClass="pt-4 pb-5 px-5 mw-75"
xlinkHref="privacy"
contentItemClass="key-colon"
renderContent={renderContent}
place="bottom"
/>
<div className={valueClass}>
{unicodeName ? (
<div className="text-truncate overflow-break-mobile" title={unicodeName}>
{unicodeName}
</div>
) : (
<div className="text-truncate overflow-break-mobile" title={domain}>
{domain}
</div>
)}
{details && isDetailed && (
<div
className="detailed-info d-none d-sm-block text-truncate"
title={details}
>
{details}
</div>
)}
</div>
</div>
);
};
DomainCell.propTypes = {
answer_dnssec: propTypes.bool.isRequired,
client_proto: propTypes.string.isRequired,
domain: propTypes.string.isRequired,
unicodeName: propTypes.string,
time: propTypes.string.isRequired,
type: propTypes.string.isRequired,
tracker: propTypes.object,
ecs: propTypes.string,
};
export default DomainCell;