+ client: handle the new statistics format

This commit is contained in:
Ildar Kamalov
2019-08-22 16:10:47 +03:00
parent 011bc3e36b
commit 6b2496d050
22 changed files with 563 additions and 488 deletions

View File

@@ -1,7 +1,6 @@
import React, { Component } from 'react';
import ReactTable from 'react-table';
import PropTypes from 'prop-types';
import map from 'lodash/map';
import { withNamespaces, Trans } from 'react-i18next';
import Card from '../ui/Card';
@@ -13,52 +12,58 @@ import { getPercent } from '../../helpers/helpers';
import { STATUS_COLORS } from '../../helpers/constants';
class BlockedDomains extends Component {
columns = [{
Header: 'IP',
accessor: 'ip',
Cell: (row) => {
const { value } = row;
const trackerData = getTrackerData(value);
columns = [
{
Header: <Trans>domain</Trans>,
accessor: 'domain',
Cell: (row) => {
const { value } = row;
const trackerData = getTrackerData(value);
return (
<div className="logs__row">
<div className="logs__text" title={value}>
{value}
return (
<div className="logs__row">
<div className="logs__text" title={value}>
{value}
</div>
{trackerData && <Popover data={trackerData} />}
</div>
{trackerData && <Popover data={trackerData} />}
</div>
);
);
},
},
}, {
Header: <Trans>requests_count</Trans>,
accessor: 'domain',
maxWidth: 190,
Cell: ({ value }) => {
const {
blockedFiltering,
replacedSafebrowsing,
replacedParental,
} = this.props;
const blocked = blockedFiltering + replacedSafebrowsing + replacedParental;
const percent = getPercent(blocked, value);
{
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} />
);
return <Cell value={value} percent={percent} color={STATUS_COLORS.red} />;
},
},
}];
];
render() {
const { t } = this.props;
const {
t, refreshButton, topBlockedDomains, subtitle,
} = this.props;
return (
<Card title={ t('top_blocked_domains') } subtitle={ t('for_last_24_hours') } bodyType="card-table" refresh={this.props.refreshButton}>
<Card
title={t('top_blocked_domains')}
subtitle={subtitle}
bodyType="card-table"
refresh={refreshButton}
>
<ReactTable
data={map(this.props.topBlockedDomains, (value, prop) => (
{ ip: prop, domain: value }
))}
data={topBlockedDomains.map(item => ({
domain: item.name,
count: item.count,
}))}
columns={this.columns}
showPagination={false}
noDataText={ t('no_domains_found') }
noDataText={t('no_domains_found')}
minRows={6}
className="-striped -highlight card-table-overflow stats__table"
/>
@@ -68,12 +73,13 @@ class BlockedDomains extends Component {
}
BlockedDomains.propTypes = {
topBlockedDomains: PropTypes.object.isRequired,
topBlockedDomains: PropTypes.array.isRequired,
blockedFiltering: PropTypes.number.isRequired,
replacedSafebrowsing: PropTypes.number.isRequired,
replacedParental: PropTypes.number.isRequired,
refreshButton: PropTypes.node.isRequired,
t: PropTypes.func,
subtitle: PropTypes.string.isRequired,
t: PropTypes.func.isRequired,
};
export default withNamespaces()(BlockedDomains);

View File

@@ -1,7 +1,6 @@
import React, { Component } from 'react';
import ReactTable from 'react-table';
import PropTypes from 'prop-types';
import map from 'lodash/map';
import { Trans, withNamespaces } from 'react-i18next';
import Card from '../ui/Card';
@@ -18,55 +17,71 @@ class Clients extends Component {
return STATUS_COLORS.yellow;
}
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;
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;
}
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>
);
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),
},
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);
{
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} />
);
return <Cell value={value} percent={percent} color={percentColor} />;
},
},
}];
];
render() {
const { t } = this.props;
const {
t, refreshButton, topClients, subtitle,
} = this.props;
return (
<Card title={ t('top_clients') } subtitle={ t('for_last_24_hours') } bodyType="card-table" refresh={this.props.refreshButton}>
<Card
title={t('top_clients')}
subtitle={subtitle}
bodyType="card-table"
refresh={refreshButton}
>
<ReactTable
data={map(this.props.topClients, (value, prop) => (
{ ip: prop, count: value }
))}
data={topClients.map(item => ({
ip: item.name,
count: item.count,
}))}
columns={this.columns}
showPagination={false}
noDataText={ t('no_clients_found') }
noDataText={t('no_clients_found')}
minRows={6}
className="-striped -highlight card-table-overflow"
/>
@@ -76,12 +91,13 @@ class Clients extends Component {
}
Clients.propTypes = {
topClients: PropTypes.object.isRequired,
topClients: PropTypes.array.isRequired,
dnsQueries: PropTypes.number.isRequired,
refreshButton: PropTypes.node.isRequired,
clients: PropTypes.array.isRequired,
autoClients: PropTypes.array.isRequired,
t: PropTypes.func,
subtitle: PropTypes.string.isRequired,
t: PropTypes.func.isRequired,
};
export default withNamespaces()(Clients);

View File

@@ -1,88 +1,116 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Trans, withNamespaces } from 'react-i18next';
import round from 'lodash/round';
import Card from '../ui/Card';
import Tooltip from '../ui/Tooltip';
const tooltipType = 'tooltip-custom--narrow';
const Counters = props => (
<Card title={ props.t('general_statistics') } subtitle={ props.t('for_last_24_hours') } bodyType="card-table" refresh={props.refreshButton}>
<table className="table card-table">
<tbody>
<tr>
<td>
<Trans>dns_query</Trans>
<Tooltip text={ props.t('number_of_dns_query_24_hours') } type={tooltipType} />
</td>
<td className="text-right">
<span className="text-muted">
{props.dnsQueries}
</span>
</td>
</tr>
<tr>
<td>
<a href="#filters">
<Trans>blocked_by</Trans>
</a>
<Tooltip text={ props.t('number_of_dns_query_blocked_24_hours') } type={tooltipType} />
</td>
<td className="text-right">
<span className="text-muted">
{props.blockedFiltering}
</span>
</td>
</tr>
<tr>
<td>
<Trans>stats_malware_phishing</Trans>
<Tooltip text={ props.t('number_of_dns_query_blocked_24_hours_by_sec') } type={tooltipType} />
</td>
<td className="text-right">
<span className="text-muted">
{props.replacedSafebrowsing}
</span>
</td>
</tr>
<tr>
<td>
<Trans>stats_adult</Trans>
<Tooltip text={ props.t('number_of_dns_query_blocked_24_hours_adult') } type={tooltipType} />
</td>
<td className="text-right">
<span className="text-muted">
{props.replacedParental}
</span>
</td>
</tr>
<tr>
<td>
<Trans>enforced_save_search</Trans>
<Tooltip text={ props.t('number_of_dns_query_to_safe_search') } type={tooltipType} />
</td>
<td className="text-right">
<span className="text-muted">
{props.replacedSafesearch}
</span>
</td>
</tr>
<tr>
<td>
<Trans>average_processing_time</Trans>
<Tooltip text={ props.t('average_processing_time_hint') } type={tooltipType} />
</td>
<td className="text-right">
<span className="text-muted">
{props.avgProcessingTime}
</span>
</td>
</tr>
</tbody>
</table>
</Card>
);
const Counters = (props) => {
const {
t,
interval,
refreshButton,
subtitle,
dnsQueries,
blockedFiltering,
replacedSafebrowsing,
replacedParental,
replacedSafesearch,
avgProcessingTime,
} = props;
const tooltipTitle =
interval === 1
? t('number_of_dns_query_24_hours')
: t('number_of_dns_query_days', { value: interval });
return (
<Card
title={t('general_statistics')}
subtitle={subtitle}
bodyType="card-table"
refresh={refreshButton}
>
<table className="table card-table">
<tbody>
<tr>
<td>
<Trans>dns_query</Trans>
<Tooltip text={tooltipTitle} type={tooltipType} />
</td>
<td className="text-right">
<span className="text-muted">{dnsQueries}</span>
</td>
</tr>
<tr>
<td>
<a href="#filters">
<Trans>blocked_by</Trans>
</a>
<Tooltip
text={t('number_of_dns_query_blocked_24_hours')}
type={tooltipType}
/>
</td>
<td className="text-right">
<span className="text-muted">{blockedFiltering}</span>
</td>
</tr>
<tr>
<td>
<Trans>stats_malware_phishing</Trans>
<Tooltip
text={t('number_of_dns_query_blocked_24_hours_by_sec')}
type={tooltipType}
/>
</td>
<td className="text-right">
<span className="text-muted">{replacedSafebrowsing}</span>
</td>
</tr>
<tr>
<td>
<Trans>stats_adult</Trans>
<Tooltip
text={t('number_of_dns_query_blocked_24_hours_adult')}
type={tooltipType}
/>
</td>
<td className="text-right">
<span className="text-muted">{replacedParental}</span>
</td>
</tr>
<tr>
<td>
<Trans>enforced_save_search</Trans>
<Tooltip
text={t('number_of_dns_query_to_safe_search')}
type={tooltipType}
/>
</td>
<td className="text-right">
<span className="text-muted">{replacedSafesearch}</span>
</td>
</tr>
<tr>
<td>
<Trans>average_processing_time</Trans>
<Tooltip text={t('average_processing_time_hint')} type={tooltipType} />
</td>
<td className="text-right">
<span className="text-muted">
{avgProcessingTime ? `${round(avgProcessingTime, 2)} ms` : 0}
</span>
</td>
</tr>
</tbody>
</table>
</Card>
);
};
Counters.propTypes = {
dnsQueries: PropTypes.number.isRequired,
@@ -92,6 +120,8 @@ Counters.propTypes = {
replacedSafesearch: PropTypes.number.isRequired,
avgProcessingTime: PropTypes.number.isRequired,
refreshButton: PropTypes.node.isRequired,
subtitle: PropTypes.string.isRequired,
interval: PropTypes.number.isRequired,
t: PropTypes.func.isRequired,
};

View File

@@ -20,3 +20,8 @@
border-top: 6px solid transparent;
border-bottom: 6px solid #585965;
}
.card-chart-bg {
left: -20px;
width: calc(100% + 20px);
}

View File

@@ -1,7 +1,6 @@
import React, { Component } from 'react';
import ReactTable from 'react-table';
import PropTypes from 'prop-types';
import map from 'lodash/map';
import { withNamespaces, Trans } from 'react-i18next';
import Card from '../ui/Card';
@@ -20,49 +19,58 @@ class QueriedDomains extends Component {
return STATUS_COLORS.yellow;
}
return STATUS_COLORS.green;
}
};
columns = [{
Header: 'IP',
accessor: 'ip',
Cell: (row) => {
const { value } = row;
const trackerData = getTrackerData(value);
columns = [
{
Header: <Trans>domain</Trans>,
accessor: 'domain',
Cell: (row) => {
const { value } = row;
const trackerData = getTrackerData(value);
return (
<div className="logs__row">
<div className="logs__text" title={value}>
{value}
return (
<div className="logs__row">
<div className="logs__text" title={value}>
{value}
</div>
{trackerData && <Popover data={trackerData} />}
</div>
{trackerData && <Popover data={trackerData} />}
</div>
);
);
},
},
}, {
Header: <Trans>requests_count</Trans>,
accessor: 'count',
maxWidth: 190,
Cell: ({ value }) => {
const percent = getPercent(this.props.dnsQueries, value);
const percentColor = this.getPercentColor(percent);
{
Header: <Trans>requests_count</Trans>,
accessor: 'count',
maxWidth: 190,
Cell: ({ value }) => {
const percent = getPercent(this.props.dnsQueries, value);
const percentColor = this.getPercentColor(percent);
return (
<Cell value={value} percent={percent} color={percentColor} />
);
return <Cell value={value} percent={percent} color={percentColor} />;
},
},
}];
];
render() {
const { t } = this.props;
const {
t, refreshButton, topQueriedDomains, subtitle,
} = this.props;
return (
<Card title={ t('stats_query_domain') } subtitle={ t('for_last_24_hours') } bodyType="card-table" refresh={this.props.refreshButton}>
<Card
title={t('stats_query_domain')}
subtitle={subtitle}
bodyType="card-table"
refresh={refreshButton}
>
<ReactTable
data={map(this.props.topQueriedDomains, (value, prop) => (
{ ip: prop, count: value }
))}
data={topQueriedDomains.map(item => ({
domain: item.name,
count: item.count,
}))}
columns={this.columns}
showPagination={false}
noDataText={ t('no_domains_found') }
noDataText={t('no_domains_found')}
minRows={6}
className="-striped -highlight card-table-overflow stats__table"
/>
@@ -72,10 +80,11 @@ class QueriedDomains extends Component {
}
QueriedDomains.propTypes = {
topQueriedDomains: PropTypes.object.isRequired,
topQueriedDomains: PropTypes.array.isRequired,
dnsQueries: PropTypes.number.isRequired,
refreshButton: PropTypes.node.isRequired,
t: PropTypes.func,
subtitle: PropTypes.string.isRequired,
t: PropTypes.func.isRequired,
};
export default withNamespaces()(QueriedDomains);

View File

@@ -5,37 +5,42 @@ import { Trans, withNamespaces } from 'react-i18next';
import Card from '../ui/Card';
import Line from '../ui/Line';
import { getPercent } from '../../helpers/helpers';
import { getPercent, normalizeHistory } from '../../helpers/helpers';
import { STATUS_COLORS } from '../../helpers/constants';
class Statistics extends Component {
getNormalizedHistory = (data, interval, id) => [{ data: normalizeHistory(data, interval), id }];
render() {
const {
interval,
dnsQueries,
blockedFiltering,
replacedSafebrowsing,
replacedParental,
numDnsQueries,
numBlockedFiltering,
numReplacedSafebrowsing,
numReplacedParental,
} = this.props;
const filteringData = [this.props.history[1]];
const queriesData = [this.props.history[2]];
const parentalData = [this.props.history[3]];
const safebrowsingData = [this.props.history[4]];
return (
<div className="row">
<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-blue">
{dnsQueries}
{numDnsQueries}
</div>
<div className="card-title-stats">
<Trans>dns_query</Trans>
</div>
</div>
<div className="card-chart-bg">
<Line data={queriesData} color={STATUS_COLORS.blue}/>
<Line
data={this.getNormalizedHistory(dnsQueries, interval, 'dnsQueries')}
color={STATUS_COLORS.blue}
/>
</div>
</Card>
</div>
@@ -43,10 +48,10 @@ class Statistics extends Component {
<Card type="card--full" bodyType="card-wrap">
<div className="card-body-stats">
<div className="card-value card-value-stats text-red">
{blockedFiltering}
{numBlockedFiltering}
</div>
<div className="card-value card-value-percent text-red">
{getPercent(dnsQueries, blockedFiltering)}
{getPercent(numDnsQueries, numBlockedFiltering)}
</div>
<div className="card-title-stats">
<a href="#filters">
@@ -55,7 +60,14 @@ class Statistics extends Component {
</div>
</div>
<div className="card-chart-bg">
<Line data={filteringData} color={STATUS_COLORS.red}/>
<Line
data={this.getNormalizedHistory(
blockedFiltering,
interval,
'blockedFiltering',
)}
color={STATUS_COLORS.red}
/>
</div>
</Card>
</div>
@@ -63,17 +75,24 @@ class Statistics extends Component {
<Card type="card--full" bodyType="card-wrap">
<div className="card-body-stats">
<div className="card-value card-value-stats text-green">
{replacedSafebrowsing}
{numReplacedSafebrowsing}
</div>
<div className="card-value card-value-percent text-green">
{getPercent(dnsQueries, replacedSafebrowsing)}
{getPercent(numDnsQueries, numReplacedSafebrowsing)}
</div>
<div className="card-title-stats">
<Trans>stats_malware_phishing</Trans>
</div>
</div>
<div className="card-chart-bg">
<Line data={safebrowsingData} color={STATUS_COLORS.green}/>
<Line
data={this.getNormalizedHistory(
replacedSafebrowsing,
interval,
'replacedSafebrowsing',
)}
color={STATUS_COLORS.green}
/>
</div>
</Card>
</div>
@@ -81,17 +100,24 @@ class Statistics extends Component {
<Card type="card--full" bodyType="card-wrap">
<div className="card-body-stats">
<div className="card-value card-value-stats text-yellow">
{replacedParental}
{numReplacedParental}
</div>
<div className="card-value card-value-percent text-yellow">
{getPercent(dnsQueries, replacedParental)}
{getPercent(numDnsQueries, numReplacedParental)}
</div>
<div className="card-title-stats">
<Trans>stats_adult</Trans>
</div>
</div>
<div className="card-chart-bg">
<Line data={parentalData} color={STATUS_COLORS.yellow}/>
<Line
data={this.getNormalizedHistory(
replacedParental,
interval,
'replacedParental',
)}
color={STATUS_COLORS.yellow}
/>
</div>
</Card>
</div>
@@ -101,11 +127,15 @@ class Statistics extends Component {
}
Statistics.propTypes = {
history: PropTypes.array.isRequired,
dnsQueries: PropTypes.number.isRequired,
blockedFiltering: PropTypes.number.isRequired,
replacedSafebrowsing: PropTypes.number.isRequired,
replacedParental: PropTypes.number.isRequired,
interval: PropTypes.number.isRequired,
dnsQueries: PropTypes.array.isRequired,
blockedFiltering: PropTypes.array.isRequired,
replacedSafebrowsing: PropTypes.array.isRequired,
replacedParental: PropTypes.array.isRequired,
numDnsQueries: PropTypes.number.isRequired,
numBlockedFiltering: PropTypes.number.isRequired,
numReplacedSafebrowsing: PropTypes.number.isRequired,
numReplacedParental: PropTypes.number.isRequired,
refreshButton: PropTypes.node.isRequired,
};

View File

@@ -19,10 +19,9 @@ class Dashboard extends Component {
getAllStats = () => {
this.props.getStats();
this.props.getStatsHistory();
this.props.getTopStats();
this.props.getStatsConfig();
this.props.getClients();
}
};
getToggleFilteringButton = () => {
const { protectionEnabled, processingProtection } = this.props.dashboard;
@@ -39,16 +38,20 @@ class Dashboard extends Component {
<Trans>{buttonText}</Trans>
</button>
);
}
};
render() {
const { dashboard, t } = this.props;
const { dashboard, stats, t } = this.props;
const dashboardProcessing =
dashboard.processing ||
dashboard.processingStats ||
dashboard.processingStatsHistory ||
dashboard.processingClients ||
dashboard.processingTopStats;
stats.processingStats ||
stats.processingGetConfig;
const subtitle =
stats.interval === 1
? t('for_last_24_hours')
: t('for_last_days', { value: stats.interval });
const refreshFullButton = (
<button
@@ -59,6 +62,7 @@ class Dashboard extends Component {
<Trans>refresh_statics</Trans>
</button>
);
const refreshButton = (
<button
type="button"
@@ -73,87 +77,85 @@ class Dashboard extends Component {
return (
<Fragment>
<PageTitle title={ t('dashboard') }>
<PageTitle title={t('dashboard')}>
<div className="page-title__actions">
{this.getToggleFilteringButton()}
{refreshFullButton}
</div>
</PageTitle>
{dashboardProcessing && <Loading />}
{!dashboardProcessing &&
{!dashboardProcessing && (
<div className="row row-cards">
{dashboard.statsHistory &&
<div className="col-lg-12">
<Statistics
history={dashboard.statsHistory}
refreshButton={refreshButton}
dnsQueries={dashboard.stats.dns_queries}
blockedFiltering={dashboard.stats.blocked_filtering}
replacedSafebrowsing={dashboard.stats.replaced_safebrowsing}
replacedParental={dashboard.stats.replaced_parental}
/>
</div>
}
<div className="col-lg-6">
{dashboard.stats &&
<Counters
refreshButton={refreshButton}
dnsQueries={dashboard.stats.dns_queries}
blockedFiltering={dashboard.stats.blocked_filtering}
replacedSafebrowsing={dashboard.stats.replaced_safebrowsing}
replacedParental={dashboard.stats.replaced_parental}
replacedSafesearch={dashboard.stats.replaced_safesearch}
avgProcessingTime={dashboard.stats.avg_processing_time}
/>
}
<div className="col-lg-12">
<Statistics
interval={stats.interval}
dnsQueries={stats.dnsQueries}
blockedFiltering={stats.blockedFiltering}
replacedSafebrowsing={stats.replacedSafebrowsing}
replacedParental={stats.replacedParental}
numDnsQueries={stats.numDnsQueries}
numBlockedFiltering={stats.numBlockedFiltering}
numReplacedSafebrowsing={stats.numReplacedSafebrowsing}
numReplacedParental={stats.numReplacedParental}
refreshButton={refreshButton}
/>
</div>
<div className="col-lg-6">
<Counters
subtitle={subtitle}
interval={stats.interval}
dnsQueries={stats.numDnsQueries}
blockedFiltering={stats.numBlockedFiltering}
replacedSafebrowsing={stats.numReplacedSafebrowsing}
replacedParental={stats.numReplacedParental}
replacedSafesearch={stats.numReplacedSafesearch}
avgProcessingTime={stats.avgProcessingTime}
refreshButton={refreshButton}
/>
</div>
<div className="col-lg-6">
<Clients
subtitle={subtitle}
dnsQueries={stats.numDnsQueries}
topClients={stats.topClients}
clients={dashboard.clients}
autoClients={dashboard.autoClients}
refreshButton={refreshButton}
/>
</div>
<div className="col-lg-6">
<QueriedDomains
subtitle={subtitle}
dnsQueries={stats.numDnsQueries}
topQueriedDomains={stats.topQueriedDomains}
refreshButton={refreshButton}
/>
</div>
<div className="col-lg-6">
<BlockedDomains
subtitle={subtitle}
topBlockedDomains={stats.topBlockedDomains}
blockedFiltering={stats.numBlockedFiltering}
replacedSafebrowsing={stats.numReplacedSafebrowsing}
replacedParental={stats.numReplacedParental}
refreshButton={refreshButton}
/>
</div>
{dashboard.topStats &&
<Fragment>
<div className="col-lg-6">
<Clients
dnsQueries={dashboard.stats.dns_queries}
refreshButton={refreshButton}
topClients={dashboard.topStats.top_clients}
clients={dashboard.clients}
autoClients={dashboard.autoClients}
/>
</div>
<div className="col-lg-6">
<QueriedDomains
dnsQueries={dashboard.stats.dns_queries}
refreshButton={refreshButton}
topQueriedDomains={dashboard.topStats.top_queried_domains}
/>
</div>
<div className="col-lg-6">
<BlockedDomains
refreshButton={refreshButton}
topBlockedDomains={dashboard.topStats.top_blocked_domains}
blockedFiltering={dashboard.stats.blocked_filtering}
replacedSafebrowsing={dashboard.stats.replaced_safebrowsing}
replacedParental={dashboard.stats.replaced_parental}
/>
</div>
</Fragment>
}
</div>
}
)}
</Fragment>
);
}
}
Dashboard.propTypes = {
getStats: PropTypes.func,
getStatsHistory: PropTypes.func,
getTopStats: PropTypes.func,
dashboard: PropTypes.object,
isCoreRunning: PropTypes.bool,
getFiltering: PropTypes.func,
toggleProtection: PropTypes.func,
getClients: PropTypes.func,
processingProtection: PropTypes.bool,
t: PropTypes.func,
dashboard: PropTypes.object.isRequired,
stats: PropTypes.object.isRequired,
getStats: PropTypes.func.isRequired,
getStatsConfig: PropTypes.func.isRequired,
toggleProtection: PropTypes.func.isRequired,
getClients: PropTypes.func.isRequired,
t: PropTypes.func.isRequired,
};
export default withNamespaces()(Dashboard);

View File

@@ -27,8 +27,9 @@ class AutoClients extends Component {
};
getStats = (ip, stats) => {
if (stats && stats.top_clients) {
return stats.top_clients[ip];
if (stats) {
const statsForCurrentIP = stats.find(item => item.name === ip);
return statsForCurrentIP && statsForCurrentIP.count;
}
return '';
@@ -59,11 +60,11 @@ class AutoClients extends Component {
Cell: this.cellWrap,
},
{
Header: this.props.t('table_statistics'),
Header: this.props.t('requests_count'),
accessor: 'statistics',
Cell: (row) => {
const clientIP = row.original.ip;
const clientStats = clientIP && this.getStats(clientIP, this.props.topStats);
const clientStats = clientIP && this.getStats(clientIP, this.props.topClients);
if (clientStats) {
return (
@@ -112,7 +113,7 @@ class AutoClients extends Component {
AutoClients.propTypes = {
t: PropTypes.func.isRequired,
autoClients: PropTypes.array.isRequired,
topStats: PropTypes.object.isRequired,
topClients: PropTypes.array.isRequired,
};
export default withNamespaces()(AutoClients);

View File

@@ -63,8 +63,9 @@ class ClientsTable extends Component {
};
getStats = (ip, stats) => {
if (stats && stats.top_clients) {
return stats.top_clients[ip];
if (stats) {
const statsForCurrentIP = stats.find(item => item.name === ip);
return statsForCurrentIP && statsForCurrentIP.count;
}
return '';
@@ -149,11 +150,11 @@ class ClientsTable extends Component {
},
},
{
Header: this.props.t('table_statistics'),
Header: this.props.t('requests_count'),
accessor: 'statistics',
Cell: (row) => {
const clientIP = row.original.ip;
const clientStats = clientIP && this.getStats(clientIP, this.props.topStats);
const clientStats = clientIP && this.getStats(clientIP, this.props.topClients);
if (clientStats) {
return (
@@ -276,7 +277,7 @@ class ClientsTable extends Component {
ClientsTable.propTypes = {
t: PropTypes.func.isRequired,
clients: PropTypes.array.isRequired,
topStats: PropTypes.object.isRequired,
topClients: PropTypes.array.isRequired,
toggleClientModal: PropTypes.func.isRequired,
deleteClient: PropTypes.func.isRequired,
addClient: PropTypes.func.isRequired,

View File

@@ -10,13 +10,14 @@ import Loading from '../../ui/Loading';
class Clients extends Component {
componentDidMount() {
this.props.getClients();
this.props.getTopStats();
this.props.getStats();
}
render() {
const {
t,
dashboard,
stats,
clients,
addClient,
updateClient,
@@ -27,12 +28,12 @@ class Clients extends Component {
return (
<Fragment>
<PageTitle title={t('client_settings')} />
{(dashboard.processingTopStats || dashboard.processingClients) && <Loading />}
{!dashboard.processingTopStats && !dashboard.processingClients && (
{(stats.processingStats || dashboard.processingClients) && <Loading />}
{!stats.processingStats && !dashboard.processingClients && (
<Fragment>
<ClientsTable
clients={dashboard.clients}
topStats={dashboard.topStats}
topClients={stats.topClients}
isModalOpen={clients.isModalOpen}
modalClientName={clients.modalClientName}
modalType={clients.modalType}
@@ -46,7 +47,7 @@ class Clients extends Component {
/>
<AutoClients
autoClients={dashboard.autoClients}
topStats={dashboard.topStats}
topClients={stats.topClients}
/>
</Fragment>
)}
@@ -58,14 +59,14 @@ class Clients extends Component {
Clients.propTypes = {
t: PropTypes.func.isRequired,
dashboard: PropTypes.object.isRequired,
stats: PropTypes.object.isRequired,
clients: PropTypes.object.isRequired,
toggleClientModal: PropTypes.func.isRequired,
deleteClient: PropTypes.func.isRequired,
addClient: PropTypes.func.isRequired,
updateClient: PropTypes.func.isRequired,
getClients: PropTypes.func.isRequired,
getTopStats: PropTypes.func.isRequired,
topStats: PropTypes.object,
getStats: PropTypes.func.isRequired,
};
export default withNamespaces()(Clients);

View File

@@ -88,7 +88,7 @@ class Settings extends Component {
<div className="col-md-12">
<StatsConfig
interval={stats.interval}
processing={stats.setConfigProcessing}
processing={stats.processingSetConfig}
setStatsConfig={setStatsConfig}
/>
</div>

View File

@@ -4,33 +4,27 @@ import { ResponsiveLine } from '@nivo/line';
import './Line.css';
const Line = props => (
props.data &&
const Line = ({ data, color }) => (
data &&
<ResponsiveLine
data={props.data}
data={data}
margin={{
top: 15,
right: 0,
bottom: 1,
left: 0,
left: 20,
}}
minY="auto"
stacked={false}
curve='linear'
axisBottom={{
tickSize: 0,
tickPadding: 10,
}}
axisLeft={{
tickSize: 0,
tickPadding: 10,
}}
axisBottom={null}
axisLeft={null}
enableGridX={false}
enableGridY={false}
enableDots={false}
enableArea={true}
animate={false}
colorBy={() => (props.color)}
colorBy={() => (color)}
tooltip={slice => (
<div>
{slice.data.map(d => (