Merge: fix #822 - Whitelist filter rules

Squashed commit of the following:

commit 350c6d5fadd77145b801df8887284bf4d64fbd19
Author: Ildar Kamalov <i.kamalov@adguard.com>
Date:   Wed Feb 26 15:43:29 2020 +0300

    * client: update translations

commit a884dffcd59f2259e2eee2c1e5a3270819bf8962
Author: Ildar Kamalov <i.kamalov@adguard.com>
Date:   Mon Feb 17 17:32:10 2020 +0300

    + client: handle whitelist filters

commit a586ec5bc614ffb0e01584a1fbdc7292b4865e68
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Wed Jan 29 18:16:59 2020 +0300

    + client: add whitelist

commit a52c3de62cf2fa34be6394771fb8bb56b4ee81e3
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Thu Feb 20 17:50:44 2020 +0300

    * change /filtering/refresh

commit 7f8f2ecccb9f7fa65318c1717dc6a7bd61afccf4
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Thu Feb 20 16:17:07 2020 +0300

    * fix race-detector issue

commit ac4b64c4a52c5b364a4b154bf18dea0fdf45647f
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Mon Jan 20 20:08:21 2020 +0300

    + whitelist filters
This commit is contained in:
Andrey Meshkov
2020-02-26 19:58:25 +03:00
parent 82aa38fce3
commit d839136fee
70 changed files with 1821 additions and 1132 deletions

View File

@@ -1,108 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Field, reduxForm } from 'redux-form';
import { Trans, withNamespaces } from 'react-i18next';
import flow from 'lodash/flow';
import { renderInputField, required, domain, answer } from '../../../../helpers/form';
const Form = (props) => {
const {
t,
handleSubmit,
reset,
pristine,
submitting,
toggleRewritesModal,
processingAdd,
} = props;
return (
<form onSubmit={handleSubmit}>
<div className="modal-body">
<div className="form__desc form__desc--top">
<Trans>domain_desc</Trans>
</div>
<div className="form__group">
<Field
id="domain"
name="domain"
component={renderInputField}
type="text"
className="form-control"
placeholder={t('form_domain')}
validate={[required, domain]}
/>
</div>
<Trans>examples_title</Trans>:
<ol className="leading-loose">
<li>
<code>example.org</code> <Trans>example_rewrite_domain</Trans>
</li>
<li>
<code>*.example.org</code> &nbsp;
<span>
<Trans components={[<code key="0">text</code>]}>
example_rewrite_wildcard
</Trans>
</span>
</li>
</ol>
<div className="form__group">
<Field
id="answer"
name="answer"
component={renderInputField}
type="text"
className="form-control"
placeholder={t('form_answer')}
validate={[required, answer]}
/>
</div>
</div>
<div className="modal-footer">
<div className="btn-list">
<button
type="button"
className="btn btn-secondary btn-standard"
disabled={submitting || processingAdd}
onClick={() => {
reset();
toggleRewritesModal();
}}
>
<Trans>cancel_btn</Trans>
</button>
<button
type="submit"
className="btn btn-success btn-standard"
disabled={submitting || pristine || processingAdd}
>
<Trans>save_btn</Trans>
</button>
</div>
</div>
</form>
);
};
Form.propTypes = {
pristine: PropTypes.bool.isRequired,
handleSubmit: PropTypes.func.isRequired,
reset: PropTypes.func.isRequired,
toggleRewritesModal: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired,
processingAdd: PropTypes.bool.isRequired,
t: PropTypes.func.isRequired,
};
export default flow([
withNamespaces(),
reduxForm({
form: 'rewritesForm',
enableReinitialize: true,
}),
])(Form);

View File

@@ -1,52 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Trans, withNamespaces } from 'react-i18next';
import ReactModal from 'react-modal';
import Form from './Form';
const Modal = (props) => {
const {
isModalOpen,
handleSubmit,
toggleRewritesModal,
processingAdd,
processingDelete,
} = props;
return (
<ReactModal
className="Modal__Bootstrap modal-dialog modal-dialog-centered"
closeTimeoutMS={0}
isOpen={isModalOpen}
onRequestClose={() => toggleRewritesModal()}
>
<div className="modal-content">
<div className="modal-header">
<h4 className="modal-title">
<Trans>rewrite_add</Trans>
</h4>
<button type="button" className="close" onClick={() => toggleRewritesModal()}>
<span className="sr-only">Close</span>
</button>
</div>
<Form
onSubmit={handleSubmit}
toggleRewritesModal={toggleRewritesModal}
processingAdd={processingAdd}
processingDelete={processingDelete}
/>
</div>
</ReactModal>
);
};
Modal.propTypes = {
isModalOpen: PropTypes.bool.isRequired,
handleSubmit: PropTypes.func.isRequired,
toggleRewritesModal: PropTypes.func.isRequired,
processingAdd: PropTypes.bool.isRequired,
processingDelete: PropTypes.bool.isRequired,
};
export default withNamespaces()(Modal);

View File

@@ -1,87 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ReactTable from 'react-table';
import { withNamespaces } from 'react-i18next';
class Table extends Component {
cellWrap = ({ value }) => (
<div className="logs__row logs__row--overflow">
<span className="logs__text" title={value}>
{value}
</span>
</div>
);
columns = [
{
Header: this.props.t('domain'),
accessor: 'domain',
Cell: this.cellWrap,
},
{
Header: this.props.t('answer'),
accessor: 'answer',
Cell: this.cellWrap,
},
{
Header: this.props.t('actions_table_header'),
accessor: 'actions',
maxWidth: 100,
Cell: value => (
<div className="logs__row logs__row--center">
<button
type="button"
className="btn btn-icon btn-outline-secondary btn-sm"
onClick={() =>
this.props.handleDelete({
answer: value.row.answer,
domain: value.row.domain,
})
}
title={this.props.t('delete_table_action')}
>
<svg className="icons">
<use xlinkHref="#delete" />
</svg>
</button>
</div>
),
},
];
render() {
const {
t, list, processing, processingAdd, processingDelete,
} = this.props;
return (
<ReactTable
data={list || []}
columns={this.columns}
loading={processing || processingAdd || processingDelete}
className="-striped -highlight card-table-overflow"
showPagination={true}
defaultPageSize={10}
minRows={5}
previousText={t('previous_btn')}
nextText={t('next_btn')}
loadingText={t('loading_table_status')}
pageText={t('page_table_footer_text')}
ofText="/"
rowsText={t('rows_table_footer_text')}
noDataText={t('rewrite_not_found')}
/>
);
}
}
Table.propTypes = {
t: PropTypes.func.isRequired,
list: PropTypes.array.isRequired,
processing: PropTypes.bool.isRequired,
processingAdd: PropTypes.bool.isRequired,
processingDelete: PropTypes.bool.isRequired,
handleDelete: PropTypes.func.isRequired,
};
export default withNamespaces()(Table);

View File

@@ -1,83 +0,0 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { Trans, withNamespaces } from 'react-i18next';
import Table from './Table';
import Modal from './Modal';
import Card from '../../../ui/Card';
class Rewrites extends Component {
handleSubmit = (values) => {
this.props.addRewrite(values);
};
handleDelete = (values) => {
// eslint-disable-next-line no-alert
if (window.confirm(this.props.t('rewrite_confirm_delete', { key: values.domain }))) {
this.props.deleteRewrite(values);
}
};
render() {
const {
t,
rewrites,
toggleRewritesModal,
} = this.props;
const {
list,
isModalOpen,
processing,
processingAdd,
processingDelete,
} = rewrites;
return (
<Card
id="rewrites"
title={t('dns_rewrites')}
subtitle={t('rewrite_desc')}
bodyType="card-body box-body--settings"
>
<Fragment>
<Table
list={list}
processing={processing}
processingAdd={processingAdd}
processingDelete={processingDelete}
handleDelete={this.handleDelete}
/>
<button
type="button"
className="btn btn-success btn-standard mt-3"
onClick={() => toggleRewritesModal()}
disabled={processingAdd}
>
<Trans>rewrite_add</Trans>
</button>
<Modal
isModalOpen={isModalOpen}
toggleRewritesModal={toggleRewritesModal}
handleSubmit={this.handleSubmit}
processingAdd={processingAdd}
processingDelete={processingDelete}
/>
</Fragment>
</Card>
);
}
}
Rewrites.propTypes = {
t: PropTypes.func.isRequired,
getRewritesList: PropTypes.func.isRequired,
toggleRewritesModal: PropTypes.func.isRequired,
addRewrite: PropTypes.func.isRequired,
deleteRewrite: PropTypes.func.isRequired,
rewrites: PropTypes.object.isRequired,
};
export default withNamespaces()(Rewrites);

View File

@@ -4,7 +4,6 @@ import { withNamespaces } from 'react-i18next';
import Upstream from './Upstream';
import Access from './Access';
import Rewrites from './Rewrites';
import Config from './Config';
import PageTitle from '../../ui/PageTitle';
import Loading from '../../ui/Loading';
@@ -13,7 +12,6 @@ class Dns extends Component {
componentDidMount() {
this.props.getDnsSettings();
this.props.getAccessList();
this.props.getRewritesList();
this.props.getDnsConfig();
}
@@ -23,25 +21,18 @@ class Dns extends Component {
dashboard,
settings,
access,
rewrites,
setAccessList,
testUpstream,
setUpstream,
getRewritesList,
addRewrite,
deleteRewrite,
toggleRewritesModal,
dnsConfig,
setDnsConfig,
} = this.props;
const isDataLoading = dashboard.processingDnsSettings
|| access.processing
|| rewrites.processing
|| dnsConfig.processingGetConfig;
const isDataReady = !dashboard.processingDnsSettings
&& !access.processing
&& !rewrites.processing
&& !dnsConfig.processingGetConfig;
return (
@@ -64,13 +55,6 @@ class Dns extends Component {
testUpstream={testUpstream}
/>
<Access access={access} setAccessList={setAccessList} />
<Rewrites
rewrites={rewrites}
getRewritesList={getRewritesList}
addRewrite={addRewrite}
deleteRewrite={deleteRewrite}
toggleRewritesModal={toggleRewritesModal}
/>
</Fragment>
)}
</Fragment>
@@ -86,11 +70,6 @@ Dns.propTypes = {
getAccessList: PropTypes.func.isRequired,
setAccessList: PropTypes.func.isRequired,
access: PropTypes.object.isRequired,
rewrites: PropTypes.object.isRequired,
getRewritesList: PropTypes.func.isRequired,
addRewrite: PropTypes.func.isRequired,
deleteRewrite: PropTypes.func.isRequired,
toggleRewritesModal: PropTypes.func.isRequired,
getDnsSettings: PropTypes.func.isRequired,
dnsConfig: PropTypes.object.isRequired,
setDnsConfig: PropTypes.func.isRequired,