+ client: functional components for dashboard
This commit is contained in:
parent
75df5e8292
commit
6bce41bb0a
|
@ -66,19 +66,21 @@
|
||||||
"disabled_protection": "Disabled protection",
|
"disabled_protection": "Disabled protection",
|
||||||
"refresh_statics": "Refresh statistics",
|
"refresh_statics": "Refresh statistics",
|
||||||
"dns_query": "DNS Queries",
|
"dns_query": "DNS Queries",
|
||||||
"blocked_by": "Blocked by Filters",
|
"blocked_by": "<0>Blocked by Filters</0>",
|
||||||
"stats_malware_phishing": "Blocked malware/phishing",
|
"stats_malware_phishing": "Blocked malware/phishing",
|
||||||
"stats_adult": "Blocked adult websites",
|
"stats_adult": "Blocked adult websites",
|
||||||
"stats_query_domain": "Top queried domains",
|
"stats_query_domain": "Top queried domains",
|
||||||
"for_last_24_hours": "for the last 24 hours",
|
"for_last_24_hours": "for the last 24 hours",
|
||||||
"for_last_days": "for the last {{value}} days",
|
"for_last_days": "for the last {{count}} day",
|
||||||
|
"for_last_days_plural": "for the last {{count}} days",
|
||||||
"no_domains_found": "No domains found",
|
"no_domains_found": "No domains found",
|
||||||
"requests_count": "Requests count",
|
"requests_count": "Requests count",
|
||||||
"top_blocked_domains": "Top blocked domains",
|
"top_blocked_domains": "Top blocked domains",
|
||||||
"top_clients": "Top clients",
|
"top_clients": "Top clients",
|
||||||
"no_clients_found": "No clients found",
|
"no_clients_found": "No clients found",
|
||||||
"general_statistics": "General statistics",
|
"general_statistics": "General statistics",
|
||||||
"number_of_dns_query_days": "A number of DNS queries processed for the last {{value}} days",
|
"number_of_dns_query_days": "A number of DNS queries processed for the last {{count}} day",
|
||||||
|
"number_of_dns_query_days_plural": "A number of DNS queries processed for the last {{count}} days",
|
||||||
"number_of_dns_query_24_hours": "A number of DNS queries processed for the last 24 hours",
|
"number_of_dns_query_24_hours": "A number of DNS queries processed for the last 24 hours",
|
||||||
"number_of_dns_query_blocked_24_hours": "A number of DNS requests blocked by adblock filters and hosts blocklists",
|
"number_of_dns_query_blocked_24_hours": "A number of DNS requests blocked by adblock filters and hosts blocklists",
|
||||||
"number_of_dns_query_blocked_24_hours_by_sec": "A number of DNS requests blocked by the AdGuard browsing security module",
|
"number_of_dns_query_blocked_24_hours_by_sec": "A number of DNS requests blocked by the AdGuard browsing security module",
|
||||||
|
@ -365,7 +367,8 @@
|
||||||
"stats_params": "Statistics configuration",
|
"stats_params": "Statistics configuration",
|
||||||
"config_successfully_saved": "Configuration successfully saved",
|
"config_successfully_saved": "Configuration successfully saved",
|
||||||
"interval_24_hour": "24 hours",
|
"interval_24_hour": "24 hours",
|
||||||
"interval_days": "{{value}} days",
|
"interval_days": "{{count}} day",
|
||||||
|
"interval_days_plural": "{{count}} days",
|
||||||
"time_period": "Time period",
|
"time_period": "Time period",
|
||||||
"domain": "Domain",
|
"domain": "Domain",
|
||||||
"answer": "Answer",
|
"answer": "Answer",
|
||||||
|
|
|
@ -22,7 +22,6 @@ export default class Api {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Global methods
|
// Global methods
|
||||||
GLOBAL_RESTART = { path: 'restart', method: 'POST' };
|
|
||||||
GLOBAL_START = { path: 'start', method: 'POST' };
|
GLOBAL_START = { path: 'start', method: 'POST' };
|
||||||
GLOBAL_STATUS = { path: 'status', method: 'GET' };
|
GLOBAL_STATUS = { path: 'status', method: 'GET' };
|
||||||
GLOBAL_STOP = { path: 'stop', method: 'POST' };
|
GLOBAL_STOP = { path: 'stop', method: 'POST' };
|
||||||
|
@ -36,11 +35,6 @@ export default class Api {
|
||||||
GLOBAL_DISABLE_PROTECTION = { path: 'disable_protection', method: 'POST' };
|
GLOBAL_DISABLE_PROTECTION = { path: 'disable_protection', method: 'POST' };
|
||||||
GLOBAL_UPDATE = { path: 'update', method: 'POST' };
|
GLOBAL_UPDATE = { path: 'update', method: 'POST' };
|
||||||
|
|
||||||
restartGlobalFiltering() {
|
|
||||||
const { path, method } = this.GLOBAL_RESTART;
|
|
||||||
return this.makeRequest(path, method);
|
|
||||||
}
|
|
||||||
|
|
||||||
startGlobalFiltering() {
|
startGlobalFiltering() {
|
||||||
const { path, method } = this.GLOBAL_START;
|
const { path, method } = this.GLOBAL_START;
|
||||||
return this.makeRequest(path, method);
|
return this.makeRequest(path, method);
|
||||||
|
|
|
@ -1,76 +1,67 @@
|
||||||
import React, { Component } from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { withNamespaces, Trans } from 'react-i18next';
|
import { withNamespaces, Trans } from 'react-i18next';
|
||||||
|
|
||||||
import Card from '../ui/Card';
|
import Card from '../ui/Card';
|
||||||
import Cell from '../ui/Cell';
|
import Cell from '../ui/Cell';
|
||||||
import Popover from '../ui/Popover';
|
import DomainCell from './DomainCell';
|
||||||
|
|
||||||
import { getTrackerData } from '../../helpers/trackers/trackers';
|
|
||||||
import { getPercent } from '../../helpers/helpers';
|
import { getPercent } from '../../helpers/helpers';
|
||||||
import { STATUS_COLORS } from '../../helpers/constants';
|
import { STATUS_COLORS } from '../../helpers/constants';
|
||||||
|
|
||||||
class BlockedDomains extends Component {
|
const CountCell = totalBlocked =>
|
||||||
columns = [
|
function cell(row) {
|
||||||
{
|
const { value } = row;
|
||||||
Header: <Trans>domain</Trans>,
|
const percent = getPercent(totalBlocked, value);
|
||||||
accessor: 'domain',
|
|
||||||
Cell: (row) => {
|
|
||||||
const { value } = row;
|
|
||||||
const trackerData = getTrackerData(value);
|
|
||||||
|
|
||||||
return (
|
return <Cell value={value} percent={percent} color={STATUS_COLORS.red} />;
|
||||||
<div className="logs__row">
|
};
|
||||||
<div className="logs__text" title={value}>
|
|
||||||
{value}
|
|
||||||
</div>
|
|
||||||
{trackerData && <Popover data={trackerData} />}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Header: <Trans>requests_count</Trans>,
|
|
||||||
accessor: 'count',
|
|
||||||
maxWidth: 190,
|
|
||||||
Cell: ({ value }) => {
|
|
||||||
const { blockedFiltering, replacedSafebrowsing, replacedParental } = this.props;
|
|
||||||
const blocked = blockedFiltering + replacedSafebrowsing + replacedParental;
|
|
||||||
const percent = getPercent(blocked, value);
|
|
||||||
|
|
||||||
return <Cell value={value} percent={percent} color={STATUS_COLORS.red} />;
|
const BlockedDomains = ({
|
||||||
},
|
t,
|
||||||
},
|
refreshButton,
|
||||||
];
|
topBlockedDomains,
|
||||||
|
subtitle,
|
||||||
|
blockedFiltering,
|
||||||
|
replacedSafebrowsing,
|
||||||
|
replacedParental,
|
||||||
|
}) => {
|
||||||
|
const totalBlocked = blockedFiltering + replacedSafebrowsing + replacedParental;
|
||||||
|
|
||||||
render() {
|
return (
|
||||||
const {
|
<Card
|
||||||
t, refreshButton, topBlockedDomains, subtitle,
|
title={t('top_blocked_domains')}
|
||||||
} = this.props;
|
subtitle={subtitle}
|
||||||
|
bodyType="card-table"
|
||||||
return (
|
refresh={refreshButton}
|
||||||
<Card
|
>
|
||||||
title={t('top_blocked_domains')}
|
<ReactTable
|
||||||
subtitle={subtitle}
|
data={topBlockedDomains.map(({ name: domain, count }) => ({
|
||||||
bodyType="card-table"
|
domain,
|
||||||
refresh={refreshButton}
|
count,
|
||||||
>
|
}))}
|
||||||
<ReactTable
|
columns={[
|
||||||
data={topBlockedDomains.map(item => ({
|
{
|
||||||
domain: item.name,
|
Header: <Trans>domain</Trans>,
|
||||||
count: item.count,
|
accessor: 'domain',
|
||||||
}))}
|
Cell: DomainCell,
|
||||||
columns={this.columns}
|
},
|
||||||
showPagination={false}
|
{
|
||||||
noDataText={t('no_domains_found')}
|
Header: <Trans>requests_count</Trans>,
|
||||||
minRows={6}
|
accessor: 'count',
|
||||||
className="-striped -highlight card-table-overflow stats__table"
|
maxWidth: 190,
|
||||||
/>
|
Cell: CountCell(totalBlocked),
|
||||||
</Card>
|
},
|
||||||
);
|
]}
|
||||||
}
|
showPagination={false}
|
||||||
}
|
noDataText={t('no_domains_found')}
|
||||||
|
minRows={6}
|
||||||
|
className="-striped -highlight card-table-overflow stats__table"
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
BlockedDomains.propTypes = {
|
BlockedDomains.propTypes = {
|
||||||
topBlockedDomains: PropTypes.array.isRequired,
|
topBlockedDomains: PropTypes.array.isRequired,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { Component } from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Trans, withNamespaces } from 'react-i18next';
|
import { Trans, withNamespaces } from 'react-i18next';
|
||||||
|
@ -9,86 +9,84 @@ import Cell from '../ui/Cell';
|
||||||
import { getPercent, getClientName } from '../../helpers/helpers';
|
import { getPercent, getClientName } from '../../helpers/helpers';
|
||||||
import { STATUS_COLORS } from '../../helpers/constants';
|
import { STATUS_COLORS } from '../../helpers/constants';
|
||||||
|
|
||||||
class Clients extends Component {
|
const getClientsPercentColor = (percent) => {
|
||||||
getPercentColor = (percent) => {
|
if (percent > 50) {
|
||||||
if (percent > 50) {
|
return STATUS_COLORS.green;
|
||||||
return STATUS_COLORS.green;
|
} else if (percent > 10) {
|
||||||
} else if (percent > 10) {
|
return STATUS_COLORS.yellow;
|
||||||
return STATUS_COLORS.yellow;
|
}
|
||||||
|
return STATUS_COLORS.red;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ipCell = (clients, autoClients) =>
|
||||||
|
function cell(row) {
|
||||||
|
let client;
|
||||||
|
const { value } = row;
|
||||||
|
const clientName = getClientName(clients, value) || getClientName(autoClients, value);
|
||||||
|
|
||||||
|
if (clientName) {
|
||||||
|
client = (
|
||||||
|
<span>
|
||||||
|
{clientName} <small>({value})</small>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
client = value;
|
||||||
}
|
}
|
||||||
return STATUS_COLORS.red;
|
|
||||||
};
|
|
||||||
|
|
||||||
columns = [
|
|
||||||
{
|
|
||||||
Header: 'IP',
|
|
||||||
accessor: 'ip',
|
|
||||||
Cell: ({ value }) => {
|
|
||||||
const clientName =
|
|
||||||
getClientName(this.props.clients, value) ||
|
|
||||||
getClientName(this.props.autoClients, value);
|
|
||||||
let client;
|
|
||||||
|
|
||||||
if (clientName) {
|
|
||||||
client = (
|
|
||||||
<span>
|
|
||||||
{clientName} <small>({value})</small>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
client = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="logs__row logs__row--overflow">
|
|
||||||
<span className="logs__text" title={value}>
|
|
||||||
{client}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
sortMethod: (a, b) =>
|
|
||||||
parseInt(a.replace(/\./g, ''), 10) - parseInt(b.replace(/\./g, ''), 10),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Header: <Trans>requests_count</Trans>,
|
|
||||||
accessor: 'count',
|
|
||||||
Cell: ({ value }) => {
|
|
||||||
const percent = getPercent(this.props.dnsQueries, value);
|
|
||||||
const percentColor = this.getPercentColor(percent);
|
|
||||||
|
|
||||||
return <Cell value={value} percent={percent} color={percentColor} />;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
t, refreshButton, topClients, subtitle,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<div className="logs__row logs__row--overflow">
|
||||||
title={t('top_clients')}
|
<span className="logs__text" title={value}>
|
||||||
subtitle={subtitle}
|
{client}
|
||||||
bodyType="card-table"
|
</span>
|
||||||
refresh={refreshButton}
|
</div>
|
||||||
>
|
|
||||||
<ReactTable
|
|
||||||
data={topClients.map(item => ({
|
|
||||||
ip: item.name,
|
|
||||||
count: item.count,
|
|
||||||
}))}
|
|
||||||
columns={this.columns}
|
|
||||||
showPagination={false}
|
|
||||||
noDataText={t('no_clients_found')}
|
|
||||||
minRows={6}
|
|
||||||
className="-striped -highlight card-table-overflow"
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
const countCell = dnsQueries =>
|
||||||
|
function cell(row) {
|
||||||
|
const { value } = row;
|
||||||
|
const percent = getPercent(dnsQueries, value);
|
||||||
|
const percentColor = getClientsPercentColor(percent);
|
||||||
|
|
||||||
|
return <Cell value={value} percent={percent} color={percentColor} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Clients = ({
|
||||||
|
t, refreshButton, topClients, subtitle, clients, autoClients, dnsQueries,
|
||||||
|
}) => (
|
||||||
|
<Card
|
||||||
|
title={t('top_clients')}
|
||||||
|
subtitle={subtitle}
|
||||||
|
bodyType="card-table"
|
||||||
|
refresh={refreshButton}
|
||||||
|
>
|
||||||
|
<ReactTable
|
||||||
|
data={topClients.map(({ name: ip, count }) => ({
|
||||||
|
ip,
|
||||||
|
count,
|
||||||
|
}))}
|
||||||
|
columns={[
|
||||||
|
{
|
||||||
|
Header: 'IP',
|
||||||
|
accessor: 'ip',
|
||||||
|
sortMethod: (a, b) =>
|
||||||
|
parseInt(a.replace(/\./g, ''), 10) - parseInt(b.replace(/\./g, ''), 10),
|
||||||
|
Cell: ipCell(clients, autoClients),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: <Trans>requests_count</Trans>,
|
||||||
|
accessor: 'count',
|
||||||
|
Cell: countCell(dnsQueries),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
showPagination={false}
|
||||||
|
noDataText={t('no_clients_found')}
|
||||||
|
minRows={6}
|
||||||
|
className="-striped -highlight card-table-overflow"
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
|
||||||
Clients.propTypes = {
|
Clients.propTypes = {
|
||||||
topClients: PropTypes.array.isRequired,
|
topClients: PropTypes.array.isRequired,
|
||||||
|
|
|
@ -25,7 +25,7 @@ const Counters = (props) => {
|
||||||
const tooltipTitle =
|
const tooltipTitle =
|
||||||
interval === 1
|
interval === 1
|
||||||
? t('number_of_dns_query_24_hours')
|
? t('number_of_dns_query_24_hours')
|
||||||
: t('number_of_dns_query_days', { value: interval });
|
: t('number_of_dns_query_days', { count: interval });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
|
@ -47,9 +47,9 @@ const Counters = (props) => {
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="#filters">
|
<Trans components={[<a href="#filters" key="0">link</a>]}>
|
||||||
<Trans>blocked_by</Trans>
|
blocked_by
|
||||||
</a>
|
</Trans>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
text={t('number_of_dns_query_blocked_24_hours')}
|
text={t('number_of_dns_query_blocked_24_hours')}
|
||||||
type={tooltipType}
|
type={tooltipType}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import { getTrackerData } from '../../helpers/trackers/trackers';
|
||||||
|
import Popover from '../ui/Popover';
|
||||||
|
|
||||||
|
const DomainCell = ({ value }) => {
|
||||||
|
const trackerData = getTrackerData(value);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="logs__row">
|
||||||
|
<div className="logs__text" title={value}>
|
||||||
|
{value}
|
||||||
|
</div>
|
||||||
|
{trackerData && <Popover data={trackerData} />}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
DomainCell.propTypes = {
|
||||||
|
value: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DomainCell;
|
|
@ -1,83 +1,67 @@
|
||||||
import React, { Component } from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { withNamespaces, Trans } from 'react-i18next';
|
import { withNamespaces, Trans } from 'react-i18next';
|
||||||
|
|
||||||
import Card from '../ui/Card';
|
import Card from '../ui/Card';
|
||||||
import Cell from '../ui/Cell';
|
import Cell from '../ui/Cell';
|
||||||
import Popover from '../ui/Popover';
|
import DomainCell from './DomainCell';
|
||||||
|
|
||||||
import { getTrackerData } from '../../helpers/trackers/trackers';
|
|
||||||
import { getPercent } from '../../helpers/helpers';
|
|
||||||
import { STATUS_COLORS } from '../../helpers/constants';
|
import { STATUS_COLORS } from '../../helpers/constants';
|
||||||
|
import { getPercent } from '../../helpers/helpers';
|
||||||
|
|
||||||
class QueriedDomains extends Component {
|
const getQueriedPercentColor = (percent) => {
|
||||||
getPercentColor = (percent) => {
|
if (percent > 10) {
|
||||||
if (percent > 10) {
|
return STATUS_COLORS.red;
|
||||||
return STATUS_COLORS.red;
|
} else if (percent > 5) {
|
||||||
} else if (percent > 5) {
|
return STATUS_COLORS.yellow;
|
||||||
return STATUS_COLORS.yellow;
|
}
|
||||||
}
|
return STATUS_COLORS.green;
|
||||||
return STATUS_COLORS.green;
|
};
|
||||||
|
|
||||||
|
const countCell = dnsQueries =>
|
||||||
|
function cell(row) {
|
||||||
|
const { value } = row;
|
||||||
|
const percent = getPercent(dnsQueries, value);
|
||||||
|
const percentColor = getQueriedPercentColor(percent);
|
||||||
|
|
||||||
|
return <Cell value={value} percent={percent} color={percentColor} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
columns = [
|
const QueriedDomains = ({
|
||||||
{
|
t, refreshButton, topQueriedDomains, subtitle, dnsQueries,
|
||||||
Header: <Trans>domain</Trans>,
|
}) => (
|
||||||
accessor: 'domain',
|
<Card
|
||||||
Cell: (row) => {
|
title={t('stats_query_domain')}
|
||||||
const { value } = row;
|
subtitle={subtitle}
|
||||||
const trackerData = getTrackerData(value);
|
bodyType="card-table"
|
||||||
|
refresh={refreshButton}
|
||||||
return (
|
>
|
||||||
<div className="logs__row">
|
<ReactTable
|
||||||
<div className="logs__text" title={value}>
|
data={topQueriedDomains.map(({ name: domain, count }) => ({
|
||||||
{value}
|
domain,
|
||||||
</div>
|
count,
|
||||||
{trackerData && <Popover data={trackerData} />}
|
}))}
|
||||||
</div>
|
columns={[
|
||||||
);
|
{
|
||||||
},
|
Header: <Trans>domain</Trans>,
|
||||||
},
|
accessor: 'domain',
|
||||||
{
|
Cell: DomainCell,
|
||||||
Header: <Trans>requests_count</Trans>,
|
},
|
||||||
accessor: 'count',
|
{
|
||||||
maxWidth: 190,
|
Header: <Trans>requests_count</Trans>,
|
||||||
Cell: ({ value }) => {
|
accessor: 'count',
|
||||||
const percent = getPercent(this.props.dnsQueries, value);
|
maxWidth: 190,
|
||||||
const percentColor = this.getPercentColor(percent);
|
Cell: countCell(dnsQueries),
|
||||||
|
},
|
||||||
return <Cell value={value} percent={percent} color={percentColor} />;
|
]}
|
||||||
},
|
showPagination={false}
|
||||||
},
|
noDataText={t('no_domains_found')}
|
||||||
];
|
minRows={6}
|
||||||
|
className="-striped -highlight card-table-overflow stats__table"
|
||||||
render() {
|
/>
|
||||||
const {
|
</Card>
|
||||||
t, refreshButton, topQueriedDomains, subtitle,
|
);
|
||||||
} = this.props;
|
|
||||||
return (
|
|
||||||
<Card
|
|
||||||
title={t('stats_query_domain')}
|
|
||||||
subtitle={subtitle}
|
|
||||||
bodyType="card-table"
|
|
||||||
refresh={refreshButton}
|
|
||||||
>
|
|
||||||
<ReactTable
|
|
||||||
data={topQueriedDomains.map(item => ({
|
|
||||||
domain: item.name,
|
|
||||||
count: item.count,
|
|
||||||
}))}
|
|
||||||
columns={this.columns}
|
|
||||||
showPagination={false}
|
|
||||||
noDataText={t('no_domains_found')}
|
|
||||||
minRows={6}
|
|
||||||
className="-striped -highlight card-table-overflow stats__table"
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QueriedDomains.propTypes = {
|
QueriedDomains.propTypes = {
|
||||||
topQueriedDomains: PropTypes.array.isRequired,
|
topQueriedDomains: PropTypes.array.isRequired,
|
||||||
|
|
|
@ -1,130 +1,67 @@
|
||||||
import React, { Component } from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Trans, withNamespaces } from 'react-i18next';
|
import { withNamespaces, Trans } from 'react-i18next';
|
||||||
|
|
||||||
import Card from '../ui/Card';
|
|
||||||
import Line from '../ui/Line';
|
|
||||||
|
|
||||||
|
import StatsCard from './StatsCard';
|
||||||
import { getPercent, normalizeHistory } from '../../helpers/helpers';
|
import { getPercent, normalizeHistory } from '../../helpers/helpers';
|
||||||
import { STATUS_COLORS } from '../../helpers/constants';
|
|
||||||
|
|
||||||
class Statistics extends Component {
|
const getNormalizedHistory = (data, interval, id) => [
|
||||||
getNormalizedHistory = (data, interval, id) => [{ data: normalizeHistory(data, interval), id }];
|
{ data: normalizeHistory(data, interval), id },
|
||||||
|
];
|
||||||
|
|
||||||
render() {
|
const Statistics = ({
|
||||||
const {
|
interval,
|
||||||
interval,
|
dnsQueries,
|
||||||
dnsQueries,
|
blockedFiltering,
|
||||||
blockedFiltering,
|
replacedSafebrowsing,
|
||||||
replacedSafebrowsing,
|
replacedParental,
|
||||||
replacedParental,
|
numDnsQueries,
|
||||||
numDnsQueries,
|
numBlockedFiltering,
|
||||||
numBlockedFiltering,
|
numReplacedSafebrowsing,
|
||||||
numReplacedSafebrowsing,
|
numReplacedParental,
|
||||||
numReplacedParental,
|
}) => (
|
||||||
} = this.props;
|
<div className="row">
|
||||||
|
<div className="col-sm-6 col-lg-3">
|
||||||
return (
|
<StatsCard
|
||||||
<div className="row">
|
total={numDnsQueries}
|
||||||
<div className="col-sm-6 col-lg-3">
|
lineData={getNormalizedHistory(dnsQueries, interval, 'dnsQuery')}
|
||||||
<Card type="card--full" bodyType="card-wrap">
|
title={<Trans>dns_query</Trans>}
|
||||||
<div className="card-body-stats">
|
color="blue"
|
||||||
<div className="card-value card-value-stats text-blue">
|
/>
|
||||||
{numDnsQueries}
|
</div>
|
||||||
</div>
|
<div className="col-sm-6 col-lg-3">
|
||||||
<div className="card-title-stats">
|
<StatsCard
|
||||||
<Trans>dns_query</Trans>
|
total={numBlockedFiltering}
|
||||||
</div>
|
lineData={getNormalizedHistory(blockedFiltering, interval, 'blockedFiltering')}
|
||||||
</div>
|
percent={getPercent(numDnsQueries, numBlockedFiltering)}
|
||||||
<div className="card-chart-bg">
|
title={<Trans components={[<a href="#filters" key="0">link</a>]}>blocked_by</Trans>}
|
||||||
<Line
|
color="red"
|
||||||
data={this.getNormalizedHistory(dnsQueries, interval, 'dnsQueries')}
|
/>
|
||||||
color={STATUS_COLORS.blue}
|
</div>
|
||||||
/>
|
<div className="col-sm-6 col-lg-3">
|
||||||
</div>
|
<StatsCard
|
||||||
</Card>
|
total={numReplacedSafebrowsing}
|
||||||
</div>
|
lineData={getNormalizedHistory(
|
||||||
<div className="col-sm-6 col-lg-3">
|
replacedSafebrowsing,
|
||||||
<Card type="card--full" bodyType="card-wrap">
|
interval,
|
||||||
<div className="card-body-stats">
|
'replacedSafebrowsing',
|
||||||
<div className="card-value card-value-stats text-red">
|
)}
|
||||||
{numBlockedFiltering}
|
percent={getPercent(numDnsQueries, numReplacedSafebrowsing)}
|
||||||
</div>
|
title={<Trans>stats_malware_phishing</Trans>}
|
||||||
<div className="card-value card-value-percent text-red">
|
color="green"
|
||||||
{getPercent(numDnsQueries, numBlockedFiltering)}
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="card-title-stats">
|
<div className="col-sm-6 col-lg-3">
|
||||||
<a href="#filters">
|
<StatsCard
|
||||||
<Trans>blocked_by</Trans>
|
total={numReplacedParental}
|
||||||
</a>
|
lineData={getNormalizedHistory(replacedParental, interval, 'replacedParental')}
|
||||||
</div>
|
percent={getPercent(numDnsQueries, numReplacedParental)}
|
||||||
</div>
|
title={<Trans>stats_adult</Trans>}
|
||||||
<div className="card-chart-bg">
|
color="yellow"
|
||||||
<Line
|
/>
|
||||||
data={this.getNormalizedHistory(
|
</div>
|
||||||
blockedFiltering,
|
</div>
|
||||||
interval,
|
);
|
||||||
'blockedFiltering',
|
|
||||||
)}
|
|
||||||
color={STATUS_COLORS.red}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
<div className="col-sm-6 col-lg-3">
|
|
||||||
<Card type="card--full" bodyType="card-wrap">
|
|
||||||
<div className="card-body-stats">
|
|
||||||
<div className="card-value card-value-stats text-green">
|
|
||||||
{numReplacedSafebrowsing}
|
|
||||||
</div>
|
|
||||||
<div className="card-value card-value-percent text-green">
|
|
||||||
{getPercent(numDnsQueries, numReplacedSafebrowsing)}
|
|
||||||
</div>
|
|
||||||
<div className="card-title-stats">
|
|
||||||
<Trans>stats_malware_phishing</Trans>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="card-chart-bg">
|
|
||||||
<Line
|
|
||||||
data={this.getNormalizedHistory(
|
|
||||||
replacedSafebrowsing,
|
|
||||||
interval,
|
|
||||||
'replacedSafebrowsing',
|
|
||||||
)}
|
|
||||||
color={STATUS_COLORS.green}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
<div className="col-sm-6 col-lg-3">
|
|
||||||
<Card type="card--full" bodyType="card-wrap">
|
|
||||||
<div className="card-body-stats">
|
|
||||||
<div className="card-value card-value-stats text-yellow">
|
|
||||||
{numReplacedParental}
|
|
||||||
</div>
|
|
||||||
<div className="card-value card-value-percent text-yellow">
|
|
||||||
{getPercent(numDnsQueries, numReplacedParental)}
|
|
||||||
</div>
|
|
||||||
<div className="card-title-stats">
|
|
||||||
<Trans>stats_adult</Trans>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="card-chart-bg">
|
|
||||||
<Line
|
|
||||||
data={this.getNormalizedHistory(
|
|
||||||
replacedParental,
|
|
||||||
interval,
|
|
||||||
'replacedParental',
|
|
||||||
)}
|
|
||||||
color={STATUS_COLORS.yellow}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Statistics.propTypes = {
|
Statistics.propTypes = {
|
||||||
interval: PropTypes.number.isRequired,
|
interval: PropTypes.number.isRequired,
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import { STATUS_COLORS } from '../../helpers/constants';
|
||||||
|
import Card from '../ui/Card';
|
||||||
|
import Line from '../ui/Line';
|
||||||
|
|
||||||
|
const StatsCard = ({
|
||||||
|
total, lineData, percent, title, color,
|
||||||
|
}) => (
|
||||||
|
<Card type="card--full" bodyType="card-wrap">
|
||||||
|
<div className="card-body-stats">
|
||||||
|
<div className={`card-value card-value-stats text-${color}`}>{total}</div>
|
||||||
|
<div className="card-title-stats">{title}</div>
|
||||||
|
</div>
|
||||||
|
{percent >= 0 && (<div className={`card-value card-value-percent text-${color}`}>{percent}</div>)}
|
||||||
|
<div className="card-chart-bg">
|
||||||
|
<Line data={lineData} color={STATUS_COLORS[color]} />
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
|
||||||
|
StatsCard.propTypes = {
|
||||||
|
total: PropTypes.number.isRequired,
|
||||||
|
lineData: PropTypes.array.isRequired,
|
||||||
|
title: PropTypes.object.isRequired,
|
||||||
|
color: PropTypes.string.isRequired,
|
||||||
|
percent: PropTypes.number,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StatsCard;
|
|
@ -51,7 +51,7 @@ class Dashboard extends Component {
|
||||||
const subtitle =
|
const subtitle =
|
||||||
stats.interval === 1
|
stats.interval === 1
|
||||||
? t('for_last_24_hours')
|
? t('for_last_24_hours')
|
||||||
: t('for_last_days', { value: stats.interval });
|
: t('for_last_days', { count: stats.interval });
|
||||||
|
|
||||||
const refreshFullButton = (
|
const refreshFullButton = (
|
||||||
<button
|
<button
|
||||||
|
|
|
@ -3,29 +3,9 @@ import PropTypes from 'prop-types';
|
||||||
import { withNamespaces } from 'react-i18next';
|
import { withNamespaces } from 'react-i18next';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
|
|
||||||
import { CLIENT_ID } from '../../../helpers/constants';
|
|
||||||
import Card from '../../ui/Card';
|
import Card from '../../ui/Card';
|
||||||
|
|
||||||
class AutoClients extends Component {
|
class AutoClients extends Component {
|
||||||
getClient = (name, clients) => {
|
|
||||||
const client = clients.find(item => name === item.name);
|
|
||||||
|
|
||||||
if (client) {
|
|
||||||
const identifier = client.mac ? CLIENT_ID.MAC : CLIENT_ID.IP;
|
|
||||||
|
|
||||||
return {
|
|
||||||
identifier,
|
|
||||||
use_global_settings: true,
|
|
||||||
...client,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
identifier: 'ip',
|
|
||||||
use_global_settings: true,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
getStats = (ip, stats) => {
|
getStats = (ip, stats) => {
|
||||||
if (stats) {
|
if (stats) {
|
||||||
const statsForCurrentIP = stats.find(item => item.name === ip);
|
const statsForCurrentIP = stats.find(item => item.name === ip);
|
||||||
|
|
|
@ -5,13 +5,13 @@ import { Trans, withNamespaces } from 'react-i18next';
|
||||||
import flow from 'lodash/flow';
|
import flow from 'lodash/flow';
|
||||||
|
|
||||||
import { renderRadioField, toNumber } from '../../../helpers/form';
|
import { renderRadioField, toNumber } from '../../../helpers/form';
|
||||||
import { STATS_INTERVALS } from '../../../helpers/constants';
|
import { STATS_INTERVALS_DAYS } from '../../../helpers/constants';
|
||||||
|
|
||||||
const getIntervalFields = (processing, t, handleChange, toNumber) =>
|
const getIntervalFields = (processing, t, handleChange, toNumber) =>
|
||||||
STATS_INTERVALS.map((interval) => {
|
STATS_INTERVALS_DAYS.map((interval) => {
|
||||||
const title = interval === 1
|
const title = interval === 1
|
||||||
? t('interval_24_hour')
|
? t('interval_24_hour')
|
||||||
: t('interval_days', { value: interval });
|
: t('interval_days', { count: interval });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Field
|
<Field
|
||||||
|
|
|
@ -5,9 +5,7 @@ const Cell = props => (
|
||||||
<div className="stats__row">
|
<div className="stats__row">
|
||||||
<div className="stats__row-value mb-1">
|
<div className="stats__row-value mb-1">
|
||||||
<strong>{props.value}</strong>
|
<strong>{props.value}</strong>
|
||||||
<small className="ml-3 text-muted">
|
<small className="ml-3 text-muted">{props.percent}%</small>
|
||||||
{props.percent}%
|
|
||||||
</small>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="progress progress-xs">
|
<div className="progress progress-xs">
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -261,4 +261,4 @@ export const FILTERED_STATUS = {
|
||||||
REWRITE: 'Rewrite',
|
REWRITE: 'Rewrite',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const STATS_INTERVALS = [1, 7, 30, 90];
|
export const STATS_INTERVALS_DAYS = [1, 7, 30, 90];
|
||||||
|
|
Loading…
Reference in New Issue