From b0a377f80c00a0efddb898656efd8497536fbf35 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Fri, 30 Nov 2018 17:36:45 -0500 Subject: [PATCH] Implement DnsList components These components will display an editable list of upstream DNS servers. Signed-off-by: Mcat12 --- src/components/settings/DnsList.js | 50 +++++++++++++++++++ src/components/settings/DnsListItem.js | 29 +++++++++++ src/components/settings/DnsListNewItem.js | 60 +++++++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 src/components/settings/DnsList.js create mode 100644 src/components/settings/DnsListItem.js create mode 100644 src/components/settings/DnsListNewItem.js diff --git a/src/components/settings/DnsList.js b/src/components/settings/DnsList.js new file mode 100644 index 0000000..5ac16a3 --- /dev/null +++ b/src/components/settings/DnsList.js @@ -0,0 +1,50 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2017 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* Web Interface +* An Editable List of Upstream DNS Servers +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +import React from "react"; +import PropTypes from "prop-types"; +import { ListGroup } from "reactstrap"; +import DnsListItem from "./DnsListItem"; +import DnsListNewItem from "./DnsListNewItem"; +import { isValidIpv4OptionalPort } from "../../validate"; + +/** + * Check if an upstream address is unique and valid + * + * @param address the address to check + * @param upstreams the list of current upstreams + * @returns {boolean} if the upstream address is unique and valid + */ +export const isAddressValid = (address, upstreams) => + !upstreams.includes(address) && isValidIpv4OptionalPort(address); + +const DnsList = ({ upstreams, onAdd, onRemove }) => ( + + {upstreams.map(upstream => ( + onRemove(upstream)} + address={upstream} + /> + ))} + isAddressValid(address, upstreams)} + /> + +); + +DnsList.propTypes = { + upstreams: PropTypes.arrayOf(PropTypes.string).isRequired, + onAdd: PropTypes.func.isRequired, + onRemove: PropTypes.func.isRequired +}; + +export default DnsList; diff --git a/src/components/settings/DnsListItem.js b/src/components/settings/DnsListItem.js new file mode 100644 index 0000000..276c50c --- /dev/null +++ b/src/components/settings/DnsListItem.js @@ -0,0 +1,29 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2017 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* Web Interface +* A Upstream DNS List Item +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +import React from "react"; +import PropTypes from "prop-types"; +import { Button, ListGroupItem } from "reactstrap"; + +const DnsListItem = ({ address, onRemove }) => ( + + {address} + + +); + +DnsListItem.propTypes = { + address: PropTypes.string.isRequired, + onRemove: PropTypes.func.isRequired +}; + +export default DnsListItem; diff --git a/src/components/settings/DnsListNewItem.js b/src/components/settings/DnsListNewItem.js new file mode 100644 index 0000000..173545b --- /dev/null +++ b/src/components/settings/DnsListNewItem.js @@ -0,0 +1,60 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2017 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* Web Interface +* Input For New DNS List Items +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ + +import React, { Component } from "react"; +import PropTypes from "prop-types"; +import { + Button, + Input, + InputGroup, + InputGroupAddon, + ListGroupItem +} from "reactstrap"; + +export default class DnsListNewItem extends Component { + static propTypes = { + onAdd: PropTypes.func.isRequired, + isValid: PropTypes.func.isRequired + }; + + state = { + address: "" + }; + + render() { + const isAddressValid = this.props.isValid(this.state.address); + + return ( + + + this.setState({ address: e.target.value })} + /> + + + + + + ); + } +}