+ client: added name for client

This commit is contained in:
Ildar Kamalov 2019-03-20 17:04:32 +03:00 committed by Simon Zolin
parent 5210d214ec
commit bc0b0af06b
8 changed files with 86 additions and 8 deletions

View File

@ -665,3 +665,18 @@ export const toggleDhcp = config => async (dispatch) => {
} }
} }
}; };
export const getClientsRequest = createAction('GET_CLIENTS_REQUEST');
export const getClientsFailure = createAction('GET_CLIENTS_FAILURE');
export const getClientsSuccess = createAction('GET_CLIENTS_SUCCESS');
export const getClients = () => async (dispatch) => {
dispatch(getClientsRequest());
try {
const clients = await apiClient.getGlobalClients();
dispatch(getClientsSuccess(clients));
} catch (error) {
dispatch(addErrorToast({ error }));
dispatch(getClientsFailure());
}
};

View File

@ -39,6 +39,7 @@ export default class Api {
GLOBAL_VERSION = { path: 'version.json', method: 'GET' }; GLOBAL_VERSION = { path: 'version.json', method: 'GET' };
GLOBAL_ENABLE_PROTECTION = { path: 'enable_protection', method: 'POST' }; GLOBAL_ENABLE_PROTECTION = { path: 'enable_protection', method: 'POST' };
GLOBAL_DISABLE_PROTECTION = { path: 'disable_protection', method: 'POST' }; GLOBAL_DISABLE_PROTECTION = { path: 'disable_protection', method: 'POST' };
GLOBAL_CLIENTS = { path: 'clients', method: 'GET' }
restartGlobalFiltering() { restartGlobalFiltering() {
const { path, method } = this.GLOBAL_RESTART; const { path, method } = this.GLOBAL_RESTART;
@ -139,6 +140,11 @@ export default class Api {
return this.makeRequest(path, method); return this.makeRequest(path, method);
} }
getGlobalClients() {
const { path, method } = this.GLOBAL_CLIENTS;
return this.makeRequest(path, method);
}
// Filtering // Filtering
FILTERING_STATUS = { path: 'filtering/status', method: 'GET' }; FILTERING_STATUS = { path: 'filtering/status', method: 'GET' };
FILTERING_ENABLE = { path: 'filtering/enable', method: 'POST' }; FILTERING_ENABLE = { path: 'filtering/enable', method: 'POST' };

View File

@ -26,6 +26,7 @@ class App extends Component {
componentDidMount() { componentDidMount() {
this.props.getDnsStatus(); this.props.getDnsStatus();
this.props.getVersion(); this.props.getVersion();
this.props.getClients();
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
@ -108,6 +109,7 @@ App.propTypes = {
getVersion: PropTypes.func, getVersion: PropTypes.func,
changeLanguage: PropTypes.func, changeLanguage: PropTypes.func,
encryption: PropTypes.object, encryption: PropTypes.object,
getClients: PropTypes.func,
}; };
export default withNamespaces()(App); export default withNamespaces()(App);

View File

@ -7,7 +7,7 @@ import { Trans, withNamespaces } from 'react-i18next';
import Card from '../ui/Card'; import Card from '../ui/Card';
import Cell from '../ui/Cell'; import Cell from '../ui/Cell';
import { getPercent } 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 { class Clients extends Component {
@ -23,7 +23,24 @@ class Clients extends Component {
columns = [{ columns = [{
Header: 'IP', Header: 'IP',
accessor: 'ip', accessor: 'ip',
Cell: ({ value }) => (<div className="logs__row logs__row--overflow"><span className="logs__text" title={value}>{value}</span></div>), Cell: ({ value }) => {
const clientName = getClientName(this.props.clients, 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), sortMethod: (a, b) => parseInt(a.replace(/\./g, ''), 10) - parseInt(b.replace(/\./g, ''), 10),
}, { }, {
Header: <Trans>requests_count</Trans>, Header: <Trans>requests_count</Trans>,
@ -61,6 +78,7 @@ Clients.propTypes = {
topClients: PropTypes.object.isRequired, topClients: PropTypes.object.isRequired,
dnsQueries: PropTypes.number.isRequired, dnsQueries: PropTypes.number.isRequired,
refreshButton: PropTypes.node.isRequired, refreshButton: PropTypes.node.isRequired,
clients: PropTypes.array.isRequired,
t: PropTypes.func, t: PropTypes.func,
}; };

View File

@ -46,6 +46,7 @@ class Dashboard extends Component {
dashboard.processing || dashboard.processing ||
dashboard.processingStats || dashboard.processingStats ||
dashboard.processingStatsHistory || dashboard.processingStatsHistory ||
dashboard.processingClients ||
dashboard.processingTopStats; dashboard.processingTopStats;
const refreshFullButton = <button type="button" className="btn btn-outline-primary btn-sm" onClick={() => this.getAllStats()}><Trans>refresh_statics</Trans></button>; const refreshFullButton = <button type="button" className="btn btn-outline-primary btn-sm" onClick={() => this.getAllStats()}><Trans>refresh_statics</Trans></button>;
@ -94,6 +95,7 @@ class Dashboard extends Component {
dnsQueries={dashboard.stats.dns_queries} dnsQueries={dashboard.stats.dns_queries}
refreshButton={refreshButton} refreshButton={refreshButton}
topClients={dashboard.topStats.top_clients} topClients={dashboard.topStats.top_clients}
clients={dashboard.clients}
/> />
</div> </div>
<div className="col-lg-6"> <div className="col-lg-6">

View File

@ -6,7 +6,7 @@ import escapeRegExp from 'lodash/escapeRegExp';
import endsWith from 'lodash/endsWith'; import endsWith from 'lodash/endsWith';
import { Trans, withNamespaces } from 'react-i18next'; import { Trans, withNamespaces } from 'react-i18next';
import { formatTime } from '../../helpers/helpers'; import { formatTime, getClientName } from '../../helpers/helpers';
import { getTrackerData } from '../../helpers/trackers/trackers'; import { getTrackerData } from '../../helpers/trackers/trackers';
import PageTitle from '../ui/PageTitle'; import PageTitle from '../ui/PageTitle';
import Card from '../ui/Card'; import Card from '../ui/Card';
@ -86,7 +86,7 @@ class Logs extends Component {
} }
renderLogs(logs) { renderLogs(logs) {
const { t } = this.props; const { t, dashboard } = this.props;
const columns = [{ const columns = [{
Header: t('time_table_header'), Header: t('time_table_header'),
accessor: 'time', accessor: 'time',
@ -196,11 +196,19 @@ class Logs extends Component {
Cell: (row) => { Cell: (row) => {
const { reason } = row.original; const { reason } = row.original;
const isFiltered = row ? reason.indexOf('Filtered') === 0 : false; const isFiltered = row ? reason.indexOf('Filtered') === 0 : false;
const clientName = getClientName(dashboard.clients, row.value);
let client;
if (clientName) {
client = <span>{clientName} <small>({row.value})</small></span>;
} else {
client = row.value;
}
return ( return (
<Fragment> <Fragment>
<div className="logs__row"> <div className="logs__row">
{row.value} {client}
</div> </div>
{this.renderBlockingButton(isFiltered, row.original.domain)} {this.renderBlockingButton(isFiltered, row.original.domain)}
</Fragment> </Fragment>
@ -315,9 +323,18 @@ class Logs extends Component {
</div> </div>
</PageTitle> </PageTitle>
<Card> <Card>
{queryLogEnabled && queryLogs.getLogsProcessing && <Loading />} {
{queryLogEnabled && !queryLogs.getLogsProcessing && queryLogEnabled
this.renderLogs(queryLogs.logs)} && queryLogs.getLogsProcessing
&& dashboard.processingClients
&& <Loading />
}
{
queryLogEnabled
&& !queryLogs.getLogsProcessing
&& !dashboard.processingClients
&& this.renderLogs(queryLogs.logs)
}
</Card> </Card>
</Fragment> </Fragment>
); );

View File

@ -203,3 +203,8 @@ export const redirectToCurrentProtocol = (values, httpPort = 80) => {
}; };
export const normalizeTextarea = text => text && text.replace(/[;, ]/g, '\n').split('\n').filter(n => n); export const normalizeTextarea = text => text && text.replace(/[;, ]/g, '\n').split('\n').filter(n => n);
export const getClientName = (clients, ip) => {
const client = clients.find(item => ip === item.ip);
return (client && client.name) || '';
};

View File

@ -167,6 +167,17 @@ const dashboard = handleActions({
const newState = { ...state, language: payload }; const newState = { ...state, language: payload };
return newState; return newState;
}, },
[actions.getClientsRequest]: state => ({ ...state, processingClients: true }),
[actions.getClientsFailure]: state => ({ ...state, processingClients: false }),
[actions.getClientsSuccess]: (state, { payload }) => {
const newState = {
...state,
clients: payload,
processingClients: false,
};
return newState;
},
}, { }, {
processing: true, processing: true,
isCoreRunning: false, isCoreRunning: false,
@ -175,6 +186,7 @@ const dashboard = handleActions({
logStatusProcessing: false, logStatusProcessing: false,
processingVersion: true, processingVersion: true,
processingFiltering: true, processingFiltering: true,
processingClients: true,
upstreamDns: '', upstreamDns: '',
bootstrapDns: '', bootstrapDns: '',
allServers: false, allServers: false,
@ -184,6 +196,7 @@ const dashboard = handleActions({
dnsPort: 53, dnsPort: 53,
dnsAddresses: [], dnsAddresses: [],
dnsVersion: '', dnsVersion: '',
clients: [],
}); });
const queryLogs = handleActions({ const queryLogs = handleActions({