Merge: fix #1421
Full rework of the query log Squashed commit of the following: commit e8a72eb223551f17e637136713dae03accf8ab9e Author: Andrey Meshkov <am@adguard.com> Date: Thu Jun 18 00:31:53 2020 +0300 fix race in whois test commit 801d28197f888fa21f83c9a0b49e3c9472c08513 Merge: 9d9787fdb1c951fbAuthor: Andrey Meshkov <am@adguard.com> Date: Thu Jun 18 00:28:13 2020 +0300 Merge branch 'master' into feature/1421 commit 9d9787fd79b17f76c7baed52c12ac462fd00a5e4 Merge: 4ce337ca 08e238ab Author: Andrey Meshkov <am@adguard.com> Date: Thu Jun 18 00:27:32 2020 +0300 Merge commit 4ce337ca7aec163edf87a038bb25fb44e64f8613 Author: Andrey Meshkov <am@adguard.com> Date: Thu Jun 18 00:22:49 2020 +0300 -(home): fix whois test commit 08e238ab0e723b1e354f58245e9a8d5017b392c9 Author: ArtemBaskal <a.baskal@adguard.com> Date: Thu Jun 18 00:13:41 2020 +0300 Add comments commit 5f108065952bcc25dce1c2eee3f9401d2641a6e9 Author: ArtemBaskal <a.baskal@adguard.com> Date: Wed Jun 17 23:47:50 2020 +0300 Make tooltip position absolute for touch commit 4c30a583165e5d007d4b01b657de8751a7bd8c7b Author: ArtemBaskal <a.baskal@adguard.com> Date: Wed Jun 17 20:39:44 2020 +0300 Prevent scroll hide for touch devices commit 62da97931f5921613762614717c62c77ddb6b8db Author: ArtemBaskal <a.baskal@adguard.com> Date: Wed Jun 17 20:06:24 2020 +0300 Review changes: ipad tooltip commit 12dddcca8caca51c157b5d25dfa3ca03ba7f0c06 Author: ArtemBaskal <a.baskal@adguard.com> Date: Wed Jun 17 16:59:16 2020 +0300 Add close tooltip event for ipad commit 62191e41d5bf67317f9f1dc6c6af08cbabb4bf90 Author: ArtemBaskal <a.baskal@adguard.com> Date: Wed Jun 17 16:39:40 2020 +0300 Add success toast on logs refresh commit 2ebdd6a8124269d737c8060c3247aaf35d85cb8b Author: ArtemBaskal <a.baskal@adguard.com> Date: Wed Jun 17 16:01:37 2020 +0300 Fix pagination commit 5820c92bacd93d05a3d66d42ee95f099e1c5d9e9 Author: ArtemBaskal <a.baskal@adguard.com> Date: Wed Jun 17 11:31:15 2020 +0300 Revert "Render table in chunks" This reverts commit cdfcd849ccddc1bc35591edac7904129431470c9. commit cdfcd849ccddc1bc35591edac7904129431470c9 Author: ArtemBaskal <a.baskal@adguard.com> Date: Tue Jun 16 18:42:18 2020 +0300 Render table in chunks commit cc8c5e64274bf6e806e2e8a4bf305af745c3ed2a Author: ArtemBaskal <a.baskal@adguard.com> Date: Tue Jun 16 17:35:24 2020 +0300 Add pagination button hover effect commit f7e134091a1556784a5fea9d83c50353536126ef Author: ArtemBaskal <a.baskal@adguard.com> Date: Tue Jun 16 16:28:00 2020 +0300 Make loader position absolute commit a7b887b57d903f1f7ac967b861b5cc677728efc4 Author: ArtemBaskal <a.baskal@adguard.com> Date: Tue Jun 16 15:42:20 2020 +0300 Ignore clients find without params commit ecb322fefd4a161d79f28d17fe27827ee91701e4 Author: ArtemBaskal <a.baskal@adguard.com> Date: Tue Jun 16 15:30:48 2020 +0300 Styles changes commit 9323ce3938bf04e1290eade09201ba0790a250c0 Author: ArtemBaskal <a.baskal@adguard.com> Date: Tue Jun 16 14:32:23 2020 +0300 Review styles changes commit e0faa04ba3643f01b2ca99524cdd52b0731725c7 Merge: 9857682315e71435Author: ArtemBaskal <a.baskal@adguard.com> Date: Tue Jun 16 12:08:45 2020 +0300 Merge branch '1421-new-qlog-v2' into feature/1421 commit 9857682371e8d9a3a91933cfb58a26b3470675d9 Author: ArtemBaskal <a.baskal@adguard.com> Date: Mon Jun 15 18:32:02 2020 +0300 Fix response cell ... and 88 more commits
This commit is contained in:
@@ -55,7 +55,8 @@ export const EMPTY_DATE = '0001-01-01T00:00:00Z';
|
||||
export const DEBOUNCE_TIMEOUT = 300;
|
||||
export const DEBOUNCE_FILTER_TIMEOUT = 500;
|
||||
export const CHECK_TIMEOUT = 1000;
|
||||
export const STOP_TIMEOUT = 10000;
|
||||
export const SUCCESS_TOAST_TIMEOUT = 5000;
|
||||
export const FAILURE_TOAST_TIMEOUT = 30000;
|
||||
|
||||
export const UNSAFE_PORTS = [
|
||||
1,
|
||||
@@ -256,18 +257,6 @@ export const ENCRYPTION_SOURCE = {
|
||||
CONTENT: 'content',
|
||||
};
|
||||
|
||||
export const FILTERED_STATUS = {
|
||||
FILTERED_BLACK_LIST: 'FilteredBlackList',
|
||||
NOT_FILTERED_WHITE_LIST: 'NotFilteredWhiteList',
|
||||
NOT_FILTERED_NOT_FOUND: 'NotFilteredNotFound',
|
||||
FILTERED_BLOCKED_SERVICE: 'FilteredBlockedService',
|
||||
REWRITE: 'Rewrite',
|
||||
REWRITE_HOSTS: 'RewriteEtcHosts',
|
||||
FILTERED_SAFE_SEARCH: 'FilteredSafeSearch',
|
||||
FILTERED_SAFE_BROWSING: 'FilteredSafeBrowsing',
|
||||
FILTERED_PARENTAL: 'FilteredParental',
|
||||
};
|
||||
|
||||
export const FILTERED = 'Filtered';
|
||||
export const NOT_FILTERED = 'NotFiltered';
|
||||
|
||||
@@ -336,25 +325,124 @@ export const DNS_RECORD_TYPES = [
|
||||
];
|
||||
|
||||
export const DEFAULT_LOGS_FILTER = {
|
||||
filter_domain: '',
|
||||
filter_client: '',
|
||||
filter_question_type: '',
|
||||
filter_response_status: '',
|
||||
search: '',
|
||||
response_status: '',
|
||||
};
|
||||
|
||||
export const DEFAULT_LANGUAGE = 'en';
|
||||
|
||||
export const TABLE_DEFAULT_PAGE_SIZE = 100;
|
||||
export const TABLE_DEFAULT_PAGE_SIZE = 50;
|
||||
|
||||
export const SMALL_TABLE_DEFAULT_PAGE_SIZE = 20;
|
||||
export const TABLE_FIRST_PAGE = 0;
|
||||
|
||||
export const LEASES_TABLE_DEFAULT_PAGE_SIZE = 20;
|
||||
|
||||
export const FILTERED_STATUS = {
|
||||
FILTERED_BLACK_LIST: 'FilteredBlackList',
|
||||
NOT_FILTERED_WHITE_LIST: 'NotFilteredWhiteList',
|
||||
NOT_FILTERED_NOT_FOUND: 'NotFilteredNotFound',
|
||||
FILTERED_BLOCKED_SERVICE: 'FilteredBlockedService',
|
||||
REWRITE: 'Rewrite',
|
||||
REWRITE_HOSTS: 'RewriteEtcHosts',
|
||||
FILTERED_SAFE_SEARCH: 'FilteredSafeSearch',
|
||||
FILTERED_SAFE_BROWSING: 'FilteredSafeBrowsing',
|
||||
FILTERED_PARENTAL: 'FilteredParental',
|
||||
};
|
||||
|
||||
export const RESPONSE_FILTER = {
|
||||
ALL: 'all',
|
||||
FILTERED: 'filtered',
|
||||
ALL: {
|
||||
query: 'all',
|
||||
label: 'show_all_responses',
|
||||
},
|
||||
FILTERED: {
|
||||
query: 'filtered',
|
||||
label: 'filtered',
|
||||
},
|
||||
PROCESSED: {
|
||||
query: 'processed',
|
||||
label: 'show_processed_responses',
|
||||
},
|
||||
SPACE: {
|
||||
query: 'all',
|
||||
label: '',
|
||||
disabled: true,
|
||||
},
|
||||
BLOCKED: {
|
||||
query: 'blocked',
|
||||
label: 'show_blocked_responses',
|
||||
},
|
||||
BLOCKED_THREATS: {
|
||||
query: 'blocked_safebrowsing',
|
||||
label: 'blocked_threats',
|
||||
},
|
||||
BLOCKED_ADULT_WEBSITES: {
|
||||
query: 'blocked_parental',
|
||||
label: 'blocked_adult_websites',
|
||||
},
|
||||
ALLOWED: {
|
||||
query: 'whitelisted',
|
||||
label: 'allowed',
|
||||
},
|
||||
REWRITTEN: {
|
||||
query: 'rewritten',
|
||||
label: 'rewritten',
|
||||
},
|
||||
SAFE_SEARCH: {
|
||||
query: 'safe_search',
|
||||
label: 'safe_search',
|
||||
},
|
||||
};
|
||||
|
||||
export const FILTERED_STATUS_TO_META_MAP = {
|
||||
[FILTERED_STATUS.NOT_FILTERED_WHITE_LIST]: {
|
||||
label: RESPONSE_FILTER.ALLOWED.label,
|
||||
color: 'green',
|
||||
},
|
||||
[FILTERED_STATUS.NOT_FILTERED_NOT_FOUND]: {
|
||||
label: RESPONSE_FILTER.PROCESSED.label,
|
||||
color: 'white',
|
||||
},
|
||||
[FILTERED_STATUS.FILTERED_BLOCKED_SERVICE]: {
|
||||
label: RESPONSE_FILTER.BLOCKED.label,
|
||||
color: 'red',
|
||||
},
|
||||
[FILTERED_STATUS.FILTERED_SAFE_SEARCH]: {
|
||||
label: RESPONSE_FILTER.SAFE_SEARCH.label,
|
||||
color: 'yellow',
|
||||
},
|
||||
[FILTERED_STATUS.FILTERED_BLACK_LIST]: {
|
||||
label: RESPONSE_FILTER.BLOCKED.label,
|
||||
color: 'red',
|
||||
},
|
||||
[FILTERED_STATUS.REWRITE]: {
|
||||
label: RESPONSE_FILTER.REWRITTEN.label,
|
||||
color: 'blue',
|
||||
},
|
||||
[FILTERED_STATUS.REWRITE_HOSTS]: {
|
||||
label: RESPONSE_FILTER.REWRITTEN.label,
|
||||
color: 'blue',
|
||||
},
|
||||
[FILTERED_STATUS.FILTERED_SAFE_BROWSING]: {
|
||||
label: RESPONSE_FILTER.BLOCKED_THREATS.label,
|
||||
color: 'yellow',
|
||||
},
|
||||
[FILTERED_STATUS.FILTERED_PARENTAL]: {
|
||||
label: RESPONSE_FILTER.BLOCKED_ADULT_WEBSITES.label,
|
||||
color: 'yellow',
|
||||
},
|
||||
};
|
||||
|
||||
export const DEFAULT_TIME_FORMAT = 'HH:mm:ss';
|
||||
|
||||
export const LONG_TIME_FORMAT = 'HH:mm:ss.SSS';
|
||||
|
||||
export const DEFAULT_SHORT_DATE_FORMAT_OPTIONS = {
|
||||
year: 'numeric',
|
||||
month: 'numeric',
|
||||
day: 'numeric',
|
||||
hour12: false,
|
||||
};
|
||||
|
||||
export const DEFAULT_DATE_FORMAT_OPTIONS = {
|
||||
year: 'numeric',
|
||||
month: 'numeric',
|
||||
@@ -371,9 +459,15 @@ export const DETAILED_DATE_FORMAT_OPTIONS = {
|
||||
|
||||
export const CUSTOM_FILTERING_RULES_ID = 0;
|
||||
|
||||
export const ACTION = {
|
||||
block: 'block',
|
||||
unblock: 'unblock',
|
||||
export const BLOCK_ACTIONS = {
|
||||
BLOCK: 'block',
|
||||
UNBLOCK: 'unblock',
|
||||
};
|
||||
|
||||
export const SCHEME_TO_PROTOCOL_MAP = {
|
||||
doh: 'dns_over_https',
|
||||
dot: 'dns_over_tls',
|
||||
'': 'plain_dns',
|
||||
};
|
||||
|
||||
export const DNS_REQUEST_OPTIONS = {
|
||||
@@ -407,3 +501,7 @@ export const FORM_NAME = {
|
||||
INSTALL: 'install',
|
||||
LOGIN: 'login',
|
||||
};
|
||||
|
||||
export const smallScreenSize = 767;
|
||||
|
||||
export const touchMediaQuery = '(hover: none)';
|
||||
|
||||
@@ -85,10 +85,10 @@ export const renderGroupField = ({
|
||||
&& <span className="input-group-append">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary btn-icon"
|
||||
className="btn btn-secondary btn-icon btn-icon--green"
|
||||
onClick={removeField}
|
||||
>
|
||||
<svg className="icon icon--close">
|
||||
<svg className="icon icon--small">
|
||||
<use xlinkHref="#cross" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
@@ -5,37 +5,40 @@ import { WHOIS_ICONS } from './constants';
|
||||
const getFormattedWhois = (whois, t) => {
|
||||
const whoisInfo = normalizeWhois(whois);
|
||||
return (
|
||||
Object.keys(whoisInfo).map((key) => {
|
||||
const icon = WHOIS_ICONS[key];
|
||||
return (
|
||||
<span className="logs__whois text-muted" key={key} title={t(key)}>
|
||||
Object.keys(whoisInfo)
|
||||
.map((key) => {
|
||||
const icon = WHOIS_ICONS[key];
|
||||
return (
|
||||
<span className="logs__whois text-muted" key={key} title={t(key)}>
|
||||
{icon && (
|
||||
<Fragment>
|
||||
<svg className="logs__whois-icon icons">
|
||||
<use xlinkHref={`#${icon}`} />
|
||||
</svg>
|
||||
</svg>
|
||||
|
||||
</Fragment>
|
||||
)}{whoisInfo[key]}
|
||||
</span>
|
||||
);
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export const formatClientCell = (row, t) => {
|
||||
const { value, original: { info } } = row;
|
||||
export const formatClientCell = (row, t, isDetailed = false) => {
|
||||
const { info, client } = row.original;
|
||||
let whoisContainer = '';
|
||||
let nameContainer = value;
|
||||
let nameContainer = client;
|
||||
|
||||
if (info) {
|
||||
const { name, whois_info } = info;
|
||||
|
||||
if (name) {
|
||||
nameContainer = (
|
||||
<span className="logs__text logs__text--wrap" title={`${name} (${value})`}>
|
||||
{name} <small>({value})</small>
|
||||
</span>
|
||||
);
|
||||
nameContainer = isDetailed ? <small title={client}>{client}</small>
|
||||
: <div className="logs__text logs__text--nowrap"
|
||||
title={`${name} (${client})`}>
|
||||
{name}
|
||||
<small>{`(${client})`}</small>
|
||||
</div>;
|
||||
}
|
||||
|
||||
if (whois_info) {
|
||||
@@ -48,11 +51,11 @@ export const formatClientCell = (row, t) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<span className="logs__text">
|
||||
<Fragment>
|
||||
<div className="logs__text" title={client}>
|
||||
<>
|
||||
{nameContainer}
|
||||
{whoisContainer}
|
||||
</Fragment>
|
||||
</span>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-bitwise */
|
||||
import 'url-polyfill';
|
||||
import dateParse from 'date-fns/parse';
|
||||
import dateFormat from 'date-fns/format';
|
||||
@@ -13,29 +12,30 @@ import i18n from 'i18next';
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
import ipaddr from 'ipaddr.js';
|
||||
import versionCompare from './versionCompare';
|
||||
import { getTrackerData } from './trackers/trackers';
|
||||
|
||||
import {
|
||||
STANDARD_DNS_PORT,
|
||||
STANDARD_WEB_PORT,
|
||||
STANDARD_HTTPS_PORT,
|
||||
CHECK_TIMEOUT,
|
||||
DNS_RECORD_TYPES,
|
||||
DEFAULT_TIME_FORMAT,
|
||||
DEFAULT_DATE_FORMAT_OPTIONS,
|
||||
DETAILED_DATE_FORMAT_OPTIONS,
|
||||
DEFAULT_LANGUAGE,
|
||||
FILTERED_STATUS,
|
||||
DEFAULT_TIME_FORMAT,
|
||||
DETAILED_DATE_FORMAT_OPTIONS,
|
||||
DNS_RECORD_TYPES,
|
||||
FILTERED,
|
||||
FILTERED_STATUS,
|
||||
IP_MATCH_LIST_STATUS,
|
||||
STANDARD_DNS_PORT,
|
||||
STANDARD_HTTPS_PORT,
|
||||
STANDARD_WEB_PORT,
|
||||
} from './constants';
|
||||
|
||||
/**
|
||||
* @param time {string} The time to format
|
||||
* @returns {string} Returns the time in the format HH:mm:ss
|
||||
*/
|
||||
export const formatTime = (time) => {
|
||||
export const formatTime = (time, options = DEFAULT_TIME_FORMAT) => {
|
||||
const parsedTime = dateParse(time);
|
||||
return dateFormat(parsedTime, DEFAULT_TIME_FORMAT);
|
||||
return dateFormat(parsedTime, options);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -68,34 +68,48 @@ export const isToday = (date) => isSameDay(new Date(date), new Date());
|
||||
|
||||
export const normalizeLogs = (logs) => logs.map((log) => {
|
||||
const {
|
||||
time,
|
||||
question,
|
||||
answer: response,
|
||||
reason,
|
||||
answer,
|
||||
answer_dnssec,
|
||||
client,
|
||||
client_proto,
|
||||
elapsedMs,
|
||||
question,
|
||||
reason,
|
||||
status,
|
||||
time,
|
||||
filterId,
|
||||
rule,
|
||||
service_name,
|
||||
status,
|
||||
original_answer,
|
||||
upstream,
|
||||
} = log;
|
||||
|
||||
const { host: domain, type } = question;
|
||||
const responsesArray = response ? response.map((response) => {
|
||||
|
||||
const response = answer ? answer.map((response) => {
|
||||
const { value, type, ttl } = response;
|
||||
return `${type}: ${value} (ttl=${ttl})`;
|
||||
}) : [];
|
||||
|
||||
const tracker = getTrackerData(domain);
|
||||
|
||||
return {
|
||||
time,
|
||||
domain,
|
||||
type,
|
||||
response: responsesArray,
|
||||
response,
|
||||
reason,
|
||||
client,
|
||||
client_proto,
|
||||
filterId,
|
||||
rule,
|
||||
status,
|
||||
serviceName: service_name,
|
||||
originalAnswer: original_answer,
|
||||
tracker,
|
||||
answer_dnssec,
|
||||
elapsedMs,
|
||||
upstream,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -562,3 +576,15 @@ export const getIpMatchListStatus = (ip, list) => {
|
||||
return IP_MATCH_LIST_STATUS.NOT_FOUND;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} elapsedMs
|
||||
* @param {function} t translate
|
||||
* @returns {string}
|
||||
*/
|
||||
export const formatElapsedMs = (elapsedMs, t) => {
|
||||
const formattedElapsedMs = parseInt(elapsedMs, 10) || parseFloat(elapsedMs)
|
||||
.toFixed(2);
|
||||
return `${formattedElapsedMs} ${t('milliseconds_abbreviation')}`;
|
||||
};
|
||||
|
||||
@@ -3,13 +3,13 @@ import adguardDb from './adguard.json';
|
||||
import { REPOSITORY } from '../constants';
|
||||
|
||||
/**
|
||||
@typedef TrackerData
|
||||
@type {object}
|
||||
@property {string} id - tracker ID.
|
||||
@property {string} name - tracker name.
|
||||
@property {string} url - tracker website url.
|
||||
@property {number} category - tracker category.
|
||||
@property {source} source - tracker data source.
|
||||
@typedef TrackerData
|
||||
@type {object}
|
||||
@property {string} id - tracker ID.
|
||||
@property {string} name - tracker name.
|
||||
@property {string} url - tracker website url.
|
||||
@property {number} category - tracker category.
|
||||
@property {source} source - tracker data source.
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -20,45 +20,6 @@ export const sources = {
|
||||
ADGUARD: 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets tracker data in the specified database
|
||||
*
|
||||
* @param {String} domainName domain name to check
|
||||
* @param {*} trackersDb trackers database
|
||||
* @param {number} source source ID
|
||||
* @returns {TrackerData} tracker data or null if no matching tracker found
|
||||
*/
|
||||
const getTrackerDataFromDb = (domainName, trackersDb, source) => {
|
||||
if (!domainName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const parts = domainName.split(/\./g).reverse();
|
||||
let hostToCheck = '';
|
||||
|
||||
// Check every subdomain
|
||||
for (let i = 0; i < parts.length; i += 1) {
|
||||
hostToCheck = parts[i] + (i > 0 ? '.' : '') + hostToCheck;
|
||||
const trackerId = trackersDb.trackerDomains[hostToCheck];
|
||||
|
||||
if (trackerId) {
|
||||
const trackerData = trackersDb.trackers[trackerId];
|
||||
const categoryName = trackersDb.categories[trackerData.categoryId];
|
||||
|
||||
return {
|
||||
id: trackerId,
|
||||
name: trackerData.name,
|
||||
url: trackerData.url,
|
||||
category: categoryName,
|
||||
source,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// No tracker found for the specified domain
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the source metadata for the specified tracker
|
||||
* @param {TrackerData} trackerData tracker data
|
||||
@@ -74,7 +35,8 @@ export const getSourceData = (trackerData) => {
|
||||
name: 'Whotracks.me',
|
||||
url: `https://whotracks.me/trackers/${trackerData.id}.html`,
|
||||
};
|
||||
} if (trackerData.source === sources.ADGUARD) {
|
||||
}
|
||||
if (trackerData.source === sources.ADGUARD) {
|
||||
return {
|
||||
name: 'AdGuard',
|
||||
url: REPOSITORY.TRACKERS_DB,
|
||||
@@ -84,6 +46,49 @@ export const getSourceData = (trackerData) => {
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets tracker data in the specified database
|
||||
*
|
||||
* @param {String} domainName domain name to check
|
||||
* @param {*} trackersDb trackers database
|
||||
* @param {number} source source ID
|
||||
* @returns {TrackerData} tracker data or null if no matching tracker found
|
||||
*/
|
||||
const getTrackerDataFromDb = (domainName, trackersDb, source) => {
|
||||
if (!domainName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const parts = domainName.split(/\./g)
|
||||
.reverse();
|
||||
let hostToCheck = '';
|
||||
|
||||
// Check every subdomain
|
||||
for (let i = 0; i < parts.length; i += 1) {
|
||||
hostToCheck = parts[i] + (i > 0 ? '.' : '') + hostToCheck;
|
||||
const trackerId = trackersDb.trackerDomains[hostToCheck];
|
||||
|
||||
if (trackerId) {
|
||||
const trackerData = trackersDb.trackers[trackerId];
|
||||
const categoryName = trackersDb.categories[trackerData.categoryId];
|
||||
trackerData.source = source;
|
||||
const sourceData = getSourceData(trackerData);
|
||||
|
||||
return {
|
||||
id: trackerId,
|
||||
name: trackerData.name,
|
||||
url: trackerData.url,
|
||||
category: categoryName,
|
||||
source,
|
||||
sourceData,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// No tracker found for the specified domain
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets tracker data from the trackers database
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user