diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json
index 95f80e68..119c1828 100644
--- a/client/src/__locales/en.json
+++ b/client/src/__locales/en.json
@@ -369,9 +369,13 @@
"interval_24_hour": "24 hours",
"interval_days": "{{count}} day",
"interval_days_plural": "{{count}} days",
- "time_period": "Time period",
- "time_period_desc": "If you decrease the interval value, some data will be lost",
"domain": "Domain",
"answer": "Answer",
- "filter_added_successfully": "The filter has been successfully added"
+ "filter_added_successfully": "The filter has been successfully added",
+ "statistics_logs": "Statistics and logs",
+ "statistics_retention": "Statistics retention",
+ "statistics_retention_desc": "If you decrease the interval value, some data will be lost",
+ "statistics_clear": " Clear statistics",
+ "statistics_clear_confirm": "Are you sure you want to clear statistics?",
+ "statistics_cleared": "Statistics successfully cleared"
}
diff --git a/client/src/actions/stats.js b/client/src/actions/stats.js
index a6eb0f13..65902e15 100644
--- a/client/src/actions/stats.js
+++ b/client/src/actions/stats.js
@@ -59,3 +59,19 @@ export const getStats = () => async (dispatch) => {
dispatch(getStatsFailure());
}
};
+
+export const resetStatsRequest = createAction('RESET_STATS_REQUEST');
+export const resetStatsFailure = createAction('RESET_STATS_FAILURE');
+export const resetStatsSuccess = createAction('RESET_STATS_SUCCESS');
+
+export const resetStats = () => async (dispatch) => {
+ dispatch(getStatsRequest());
+ try {
+ await apiClient.resetStats();
+ dispatch(addSuccessToast('statistics_cleared'));
+ dispatch(resetStatsSuccess());
+ } catch (error) {
+ dispatch(addErrorToast({ error }));
+ dispatch(resetStatsFailure());
+ }
+};
diff --git a/client/src/api/Api.js b/client/src/api/Api.js
index de068563..0f63f2ea 100644
--- a/client/src/api/Api.js
+++ b/client/src/api/Api.js
@@ -496,6 +496,7 @@ export default class Api {
GET_STATS = { path: 'stats', method: 'GET' };
STATS_INFO = { path: 'stats_info', method: 'GET' };
STATS_CONFIG = { path: 'stats_config', method: 'POST' };
+ STATS_RESET = { path: 'stats_reset', method: 'POST' };
getStats() {
const { path, method } = this.GET_STATS;
@@ -515,4 +516,9 @@ export default class Api {
};
return this.makeRequest(path, method, config);
}
+
+ resetStats() {
+ const { path, method } = this.STATS_RESET;
+ return this.makeRequest(path, method);
+ }
}
diff --git a/client/src/components/Settings/StatsConfig/Form.js b/client/src/components/Settings/StatsConfig/Form.js
index 828ffa15..463476c9 100644
--- a/client/src/components/Settings/StatsConfig/Form.js
+++ b/client/src/components/Settings/StatsConfig/Form.js
@@ -38,10 +38,10 @@ const Form = (props) => {
- time_period_desc
+ statistics_retention_desc
diff --git a/client/src/components/Settings/StatsConfig/index.js b/client/src/components/Settings/StatsConfig/index.js
index 5513e7d6..b649c6c9 100644
--- a/client/src/components/Settings/StatsConfig/index.js
+++ b/client/src/components/Settings/StatsConfig/index.js
@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
-import { withNamespaces } from 'react-i18next';
+import { withNamespaces, Trans } from 'react-i18next';
import debounce from 'lodash/debounce';
import { DEBOUNCE_TIMEOUT } from '../../../helpers/constants';
@@ -12,18 +12,21 @@ class StatsConfig extends Component {
this.props.setStatsConfig(values);
}, DEBOUNCE_TIMEOUT);
+ handleReset = () => {
+ const { t, resetStats } = this.props;
+ // eslint-disable-next-line no-alert
+ if (window.confirm(t('statistics_clear_confirm'))) {
+ resetStats();
+ }
+ };
+
render() {
const {
- t,
- interval,
- processing,
+ t, interval, processing, processingReset,
} = this.props;
return (
-
+
+
+
);
@@ -42,7 +54,9 @@ class StatsConfig extends Component {
StatsConfig.propTypes = {
interval: PropTypes.number.isRequired,
processing: PropTypes.bool.isRequired,
+ processingReset: PropTypes.bool.isRequired,
setStatsConfig: PropTypes.func.isRequired,
+ resetStats: PropTypes.func.isRequired,
t: PropTypes.func.isRequired,
};
diff --git a/client/src/components/Settings/index.js b/client/src/components/Settings/index.js
index c928d393..5f7f2fd6 100644
--- a/client/src/components/Settings/index.js
+++ b/client/src/components/Settings/index.js
@@ -68,6 +68,7 @@ class Settings extends Component {
services,
setBlockedServices,
setStatsConfig,
+ resetStats,
stats,
t,
} = this.props;
@@ -89,7 +90,9 @@ class Settings extends Component {
@@ -107,13 +110,13 @@ class Settings extends Component {
}
Settings.propTypes = {
- initSettings: PropTypes.func,
- settings: PropTypes.object,
- settingsList: PropTypes.object,
- toggleSetting: PropTypes.func,
- getStatsConfig: PropTypes.func,
- setStatsConfig: PropTypes.func,
- t: PropTypes.func,
+ initSettings: PropTypes.func.isRequired,
+ settings: PropTypes.object.isRequired,
+ toggleSetting: PropTypes.func.isRequired,
+ getStatsConfig: PropTypes.func.isRequired,
+ setStatsConfig: PropTypes.func.isRequired,
+ resetStats: PropTypes.func.isRequired,
+ t: PropTypes.func.isRequired,
};
export default withNamespaces()(Settings);
diff --git a/client/src/containers/Settings.js b/client/src/containers/Settings.js
index d13048ae..14f08cfc 100644
--- a/client/src/containers/Settings.js
+++ b/client/src/containers/Settings.js
@@ -1,7 +1,7 @@
import { connect } from 'react-redux';
import { initSettings, toggleSetting } from '../actions';
import { getBlockedServices, setBlockedServices } from '../actions/services';
-import { getStatsConfig, setStatsConfig } from '../actions/stats';
+import { getStatsConfig, setStatsConfig, resetStats } from '../actions/stats';
import Settings from '../components/Settings';
const mapStateToProps = (state) => {
@@ -21,6 +21,7 @@ const mapDispatchToProps = {
setBlockedServices,
getStatsConfig,
setStatsConfig,
+ resetStats,
};
export default connect(
diff --git a/client/src/reducers/stats.js b/client/src/reducers/stats.js
index 3bae662d..88c33a12 100644
--- a/client/src/reducers/stats.js
+++ b/client/src/reducers/stats.js
@@ -2,6 +2,22 @@ import { handleActions } from 'redux-actions';
import * as actions from '../actions/stats';
+const defaultStats = {
+ dnsQueries: [],
+ blockedFiltering: [],
+ replacedParental: [],
+ replacedSafebrowsing: [],
+ topBlockedDomains: [],
+ topClients: [],
+ topQueriedDomains: [],
+ numBlockedFiltering: 0,
+ numDnsQueries: 0,
+ numReplacedParental: 0,
+ numReplacedSafebrowsing: 0,
+ numReplacedSafesearch: 0,
+ avgProcessingTime: 0,
+};
+
const stats = handleActions(
{
[actions.getStatsConfigRequest]: state => ({ ...state, processingGetConfig: true }),
@@ -59,25 +75,22 @@ const stats = handleActions(
return newState;
},
+
+ [actions.resetStatsRequest]: state => ({ ...state, processingReset: true }),
+ [actions.resetStatsFailure]: state => ({ ...state, processingReset: false }),
+ [actions.resetStatsSuccess]: state => ({
+ ...state,
+ ...defaultStats,
+ processingReset: false,
+ }),
},
{
processingGetConfig: false,
processingSetConfig: false,
processingStats: true,
+ processingReset: false,
interval: 1,
- dnsQueries: [],
- blockedFiltering: [],
- replacedParental: [],
- replacedSafebrowsing: [],
- topBlockedDomains: [],
- topClients: [],
- topQueriedDomains: [],
- numBlockedFiltering: 0,
- numDnsQueries: 0,
- numReplacedParental: 0,
- numReplacedSafebrowsing: 0,
- numReplacedSafesearch: 0,
- avgProcessingTime: 0,
+ ...defaultStats,
},
);