diff --git a/CHANGELOG.md b/CHANGELOG.md index b3f10636..d7904040 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ NOTE: Add new changes BELOW THIS COMMENT. configuration file ([#951]). The UI changes are coming in the upcoming releases. - The ability to edit rewrite rules via `PUT /control/rewrite/update` HTTP API - ([#1577]). + and the Web UI ([#1577]). ### Changed diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index a2633ad8..644f466d 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -478,7 +478,9 @@ "setup_dns_notice": "In order to use <1>DNS-over-HTTPS or <1>DNS-over-TLS, you need to <0>configure Encryption in AdGuard Home settings.", "rewrite_added": "DNS rewrite for \"{{key}}\" successfully added", "rewrite_deleted": "DNS rewrite for \"{{key}}\" successfully deleted", + "rewrite_updated": "DNS rewrite successfully updated", "rewrite_add": "Add DNS rewrite", + "rewrite_edit": "Edit DNS rewrite", "rewrite_not_found": "No DNS rewrites found", "rewrite_confirm_delete": "Are you sure you want to delete DNS rewrite for \"{{key}}\"?", "rewrite_desc": "Allows to easily configure custom DNS response for a specific domain name.", diff --git a/client/src/actions/rewrites.js b/client/src/actions/rewrites.js index 638f8ab6..1fd72b5a 100644 --- a/client/src/actions/rewrites.js +++ b/client/src/actions/rewrites.js @@ -38,6 +38,29 @@ export const addRewrite = (config) => async (dispatch) => { } }; +export const updateRewriteRequest = createAction('UPDATE_REWRITE_REQUEST'); +export const updateRewriteFailure = createAction('UPDATE_REWRITE_FAILURE'); +export const updateRewriteSuccess = createAction('UPDATE_REWRITE_SUCCESS'); + +/** + * @param {Object} config + * @param {string} config.target - current DNS rewrite value + * @param {string} config.update - updated DNS rewrite value + */ +export const updateRewrite = (config) => async (dispatch) => { + dispatch(updateRewriteRequest()); + try { + await apiClient.updateRewrite(config); + dispatch(updateRewriteSuccess()); + dispatch(toggleRewritesModal()); + dispatch(getRewritesList()); + dispatch(addSuccessToast(i18next.t('rewrite_updated', { key: config.domain }))); + } catch (error) { + dispatch(addErrorToast({ error })); + dispatch(updateRewriteFailure()); + } +}; + export const deleteRewriteRequest = createAction('DELETE_REWRITE_REQUEST'); export const deleteRewriteFailure = createAction('DELETE_REWRITE_FAILURE'); export const deleteRewriteSuccess = createAction('DELETE_REWRITE_SUCCESS'); diff --git a/client/src/api/Api.js b/client/src/api/Api.js index 30c2db1d..a01c9d04 100644 --- a/client/src/api/Api.js +++ b/client/src/api/Api.js @@ -455,6 +455,8 @@ class Api { REWRITE_ADD = { path: 'rewrite/add', method: 'POST' }; + REWRITE_UPDATE = { path: 'rewrite/update', method: 'PUT' }; + REWRITE_DELETE = { path: 'rewrite/delete', method: 'POST' }; getRewritesList() { @@ -470,6 +472,14 @@ class Api { return this.makeRequest(path, method, parameters); } + updateRewrite(config) { + const { path, method } = this.REWRITE_UPDATE; + const parameters = { + data: config, + }; + return this.makeRequest(path, method, parameters); + } + deleteRewrite(config) { const { path, method } = this.REWRITE_DELETE; const parameters = { diff --git a/client/src/components/Filters/Rewrites/Form.js b/client/src/components/Filters/Rewrites/Form.js index 6ea545a0..395c0501 100644 --- a/client/src/components/Filters/Rewrites/Form.js +++ b/client/src/components/Filters/Rewrites/Form.js @@ -105,6 +105,7 @@ Form.propTypes = { submitting: PropTypes.bool.isRequired, processingAdd: PropTypes.bool.isRequired, t: PropTypes.func.isRequired, + initialValues: PropTypes.object, }; export default flow([ diff --git a/client/src/components/Filters/Rewrites/Modal.js b/client/src/components/Filters/Rewrites/Modal.js index c7f10de5..4afc138f 100644 --- a/client/src/components/Filters/Rewrites/Modal.js +++ b/client/src/components/Filters/Rewrites/Modal.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { Trans, withTranslation } from 'react-i18next'; import ReactModal from 'react-modal'; +import { MODAL_TYPE } from '../../../helpers/constants'; import Form from './Form'; const Modal = (props) => { @@ -12,6 +13,8 @@ const Modal = (props) => { toggleRewritesModal, processingAdd, processingDelete, + modalType, + currentRewrite, } = props; return ( @@ -24,13 +27,18 @@ const Modal = (props) => {

- rewrite_add + {modalType === MODAL_TYPE.EDIT_REWRITE ? ( + rewrite_edit + ) : ( + rewrite_add + )}

( @@ -31,24 +32,44 @@ class Table extends Component { maxWidth: 100, sortable: false, resizable: false, - Cell: (value) => ( -
- -
- ), + Cell: (value) => { + const currentRewrite = { + answer: value.row.answer, + domain: value.row.domain, + }; + + return ( +
+ + + +
+ ); + }, }, ]; @@ -84,7 +105,9 @@ Table.propTypes = { processing: PropTypes.bool.isRequired, processingAdd: PropTypes.bool.isRequired, processingDelete: PropTypes.bool.isRequired, + processingUpdate: PropTypes.bool.isRequired, handleDelete: PropTypes.func.isRequired, + toggleRewritesModal: PropTypes.func.isRequired, }; export default withTranslation()(Table); diff --git a/client/src/components/Filters/Rewrites/index.js b/client/src/components/Filters/Rewrites/index.js index b94e20da..3d47821b 100644 --- a/client/src/components/Filters/Rewrites/index.js +++ b/client/src/components/Filters/Rewrites/index.js @@ -6,16 +6,13 @@ import Table from './Table'; import Modal from './Modal'; import Card from '../../ui/Card'; import PageTitle from '../../ui/PageTitle'; +import { MODAL_TYPE } from '../../../helpers/constants'; class Rewrites extends Component { componentDidMount() { this.props.getRewritesList(); } - 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 }))) { @@ -23,6 +20,19 @@ class Rewrites extends Component { } }; + handleSubmit = (values) => { + const { modalType, currentRewrite } = this.props.rewrites; + + if (modalType === MODAL_TYPE.EDIT_REWRITE && currentRewrite) { + this.props.updateRewrite({ + target: currentRewrite, + update: values, + }); + } else { + this.props.addRewrite(values); + } + }; + render() { const { t, @@ -36,6 +46,9 @@ class Rewrites extends Component { processing, processingAdd, processingDelete, + processingUpdate, + modalType, + currentRewrite, } = rewrites; return ( @@ -54,13 +67,15 @@ class Rewrites extends Component { processing={processing} processingAdd={processingAdd} processingDelete={processingDelete} + processingUpdate={processingUpdate} handleDelete={this.handleDelete} + toggleRewritesModal={toggleRewritesModal} />