From 2ef549cf5ae3d7818d333337fdd095405631cb00 Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Mon, 20 Apr 2020 10:18:32 +0300 Subject: [PATCH] Fix xo issues Signed-off-by: XhmikosR --- scripts/make-fake-data.js | 19 +++--- src/components/common/EnableDisable.tsx | 10 ++- src/components/common/Header.tsx | 2 +- src/components/common/NavButton.tsx | 2 +- src/components/common/NavDropdown.tsx | 3 +- src/components/common/Sidebar.tsx | 16 ++--- src/components/common/StatusBadge.tsx | 2 +- src/components/common/WithAPIData.tsx | 18 +++--- .../common/__tests__/EnableDisable.test.tsx | 4 +- .../__tests__/FooterUpdateStatus.test.tsx | 2 +- .../common/__tests__/NavDropdown.test.tsx | 4 +- .../common/__tests__/Sidebar.test.tsx | 2 +- .../common/__tests__/WithAPIData.test.tsx | 10 +-- .../common/context/__tests__/index.test.tsx | 2 +- src/components/dashboard/ChartTooltip.tsx | 1 + src/components/dashboard/ClientsGraph.tsx | 25 ++++---- .../dashboard/GenericDoughnutChart.tsx | 21 +++---- src/components/dashboard/QueriesGraph.tsx | 27 ++++---- src/components/dashboard/QueryTypesChart.tsx | 2 +- src/components/dashboard/SummaryStats.tsx | 8 +-- .../dashboard/TimeRangeSelector.tsx | 18 +++--- .../dashboard/TopBlockedClients.tsx | 2 +- .../dashboard/TopBlockedDomains.tsx | 2 +- src/components/dashboard/TopClients.tsx | 2 +- src/components/dashboard/TopDomains.tsx | 2 +- src/components/dashboard/TopTable.tsx | 8 +-- .../dashboard/__tests__/ClientsGraph.test.tsx | 2 +- .../__tests__/GenericDoughnutChart.test.tsx | 8 +-- .../dashboard/__tests__/SummaryStats.test.tsx | 2 +- .../dashboard/__tests__/TopTable.test.tsx | 2 +- src/components/list/DomainInput.tsx | 6 +- src/components/list/ListPage.tsx | 4 +- .../list/__tests__/ListPage.test.tsx | 3 +- src/components/log/QueryLog.tsx | 61 ++++++++++--------- .../login/__tests__/ForgotPassword.test.tsx | 4 +- .../ConditionalForwardingSettings.tsx | 12 ++-- src/components/settings/DHCPInfo.tsx | 12 ++-- src/components/settings/DNSInfo.tsx | 8 +-- src/components/settings/DnsList.tsx | 8 +-- src/components/settings/DnsListNewItem.tsx | 14 ++--- src/components/settings/DnsOptionSettings.tsx | 6 +- .../settings/PreferenceSettings.tsx | 14 ++--- src/components/settings/VersionInfo.tsx | 2 +- .../settings/__tests__/DHCPInfo.test.tsx | 2 +- .../settings/preconfiguredUpstreams.tsx | 4 +- src/config.development.tsx | 2 +- src/containers/Full.tsx | 2 +- src/index.tsx | 4 +- src/redux/actions/index.tsx | 2 +- src/redux/sagas/applyLanguage.tsx | 2 +- src/redux/sagas/autoLogin.tsx | 6 +- src/redux/state/preferences.tsx | 2 +- src/routes.tsx | 4 +- src/setupTests.tsx | 4 +- src/types/api.d.ts | 18 +++--- src/util/CancelablePromise.tsx | 1 + src/util/__tests__/basePath.test.tsx | 4 +- src/util/api.tsx | 26 ++++---- src/util/basePath.ts | 5 +- src/util/http.tsx | 2 +- src/util/result.ts | 8 +-- src/util/validate.tsx | 15 ++--- src/views/Dashboard.tsx | 6 +- src/views/ExactBlacklist.tsx | 4 +- src/views/ExactWhitelist.tsx | 4 +- src/views/Login.tsx | 14 ++--- src/views/RegexBlacklist.tsx | 4 +- src/views/RegexWhitelist.tsx | 4 +- 68 files changed, 263 insertions(+), 268 deletions(-) diff --git a/scripts/make-fake-data.js b/scripts/make-fake-data.js index 0495a87..26383d2 100644 --- a/scripts/make-fake-data.js +++ b/scripts/make-fake-data.js @@ -162,10 +162,11 @@ function topDomainList(length, max) { const numbers = []; const domains = unique(faker.internet.domainName, length); - for (let i = 0; i < length; i++) - numbers.push(faker.random.number({ max: max })); + for (let i = 0; i < length; i++) numbers.push(faker.random.number({ max })); - numbers.sort((a, b) => (parseInt(a, 10) > parseInt(b, 10) ? -1 : 1)); + numbers.sort((a, b) => + Number.parseInt(a, 10) > Number.parseInt(b, 10) ? -1 : 1 + ); for (let i = 0; i < length; i++) { result.push({ @@ -203,7 +204,9 @@ function topClientList(length, totalQueries) { for (let i = 0; i < length; i++) numbers.push(faker.random.number({ max: totalQueries })); - numbers.sort((a, b) => (parseInt(a, 10) > parseInt(b, 10) ? -1 : 1)); + numbers.sort((a, b) => + Number.parseInt(a, 10) > Number.parseInt(b, 10) ? -1 : 1 + ); for (let i = 0; i < length; i++) { top_clients.push({ @@ -251,7 +254,7 @@ function clientsOverTime(range, size) { return { over_time: graph, - clients: clients + clients }; } @@ -305,7 +308,7 @@ function getVersionInfo() { "beta", "test" ]), - hash: faker.internet.color().substring(1) + faker.random.number(9), + hash: faker.internet.color().slice(1) + faker.random.number(9), tag: "vDev" }, ftl: { @@ -316,7 +319,7 @@ function getVersionInfo() { "beta", "test" ]), - hash: faker.internet.color().substring(1) + faker.random.number(9), + hash: faker.internet.color().slice(1) + faker.random.number(9), tag: "vDev" }, web: { @@ -327,7 +330,7 @@ function getVersionInfo() { "beta", "test" ]), - hash: faker.internet.color().substring(1) + faker.random.number(9), + hash: faker.internet.color().slice(1) + faker.random.number(9), tag: "vDev" } }; diff --git a/src/components/common/EnableDisable.tsx b/src/components/common/EnableDisable.tsx index c790758..eeae104 100644 --- a/src/components/common/EnableDisable.tsx +++ b/src/components/common/EnableDisable.tsx @@ -8,8 +8,6 @@ * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ -/* eslint-disable jsx-a11y/anchor-is-valid */ - import React, { Component, FormEvent } from "react"; import { WithTranslation, withTranslation } from "react-i18next"; import NavButton from "./NavButton"; @@ -100,9 +98,9 @@ export class EnableDisable extends Component< ) // Allow new status changes when finished .then(this.toggleProcessing) - .catch(e => { + .catch(error => { // Ignore canceled requests - if (e.isCanceled) { + if (error.isCanceled) { return; } @@ -173,7 +171,7 @@ export class EnableDisable extends Component< type="number" value={this.state.customTime} onChange={e => - this.setState({ customTime: parseInt(e.target.value) }) + this.setState({ customTime: Number.parseInt(e.target.value) }) } /> @@ -182,7 +180,7 @@ export class EnableDisable extends Component< value={this.state.customMultiplier} onChange={e => this.setState({ - customMultiplier: parseInt(e.target.value) + customMultiplier: Number.parseInt(e.target.value) }) } > diff --git a/src/components/common/Header.tsx b/src/components/common/Header.tsx index 356bb59..83a8472 100644 --- a/src/components/common/Header.tsx +++ b/src/components/common/Header.tsx @@ -41,8 +41,8 @@ export default () => (
diff --git a/src/components/common/NavButton.tsx b/src/components/common/NavButton.tsx index d1e5489..b200e14 100644 --- a/src/components/common/NavButton.tsx +++ b/src/components/common/NavButton.tsx @@ -22,11 +22,11 @@ const NavButton = ({ name, icon, onClick }: NavButtonProps) => (
  • { e.preventDefault(); onClick(e); }} - className="nav-link" > {name} diff --git a/src/components/common/NavDropdown.tsx b/src/components/common/NavDropdown.tsx index f88bf00..0f25b89 100644 --- a/src/components/common/NavDropdown.tsx +++ b/src/components/common/NavDropdown.tsx @@ -8,8 +8,6 @@ * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ -/* eslint-disable jsx-a11y/anchor-is-valid */ - import React, { MouseEvent, ReactNode } from "react"; export interface NavDropdownProps { @@ -23,6 +21,7 @@ export default ({ name, icon, isOpen, children }: NavDropdownProps) => (
  • @@ -134,10 +134,10 @@ export const TimeRangeSelectorContainer = ({ size }: { size?: string }) => ( {context => ( )} diff --git a/src/components/dashboard/TopBlockedClients.tsx b/src/components/dashboard/TopBlockedClients.tsx index 39c2cd5..550e6e3 100644 --- a/src/components/dashboard/TopBlockedClients.tsx +++ b/src/components/dashboard/TopBlockedClients.tsx @@ -17,7 +17,7 @@ import { TimeRangeContext } from "../common/context/TimeRangeContext"; export interface TopBlockedClientsData { blockedQueries: number; - topClients: Array; + topClients: ApiClientData[]; } /** diff --git a/src/components/dashboard/TopBlockedDomains.tsx b/src/components/dashboard/TopBlockedDomains.tsx index 67bdbdc..8aa8023 100644 --- a/src/components/dashboard/TopBlockedDomains.tsx +++ b/src/components/dashboard/TopBlockedDomains.tsx @@ -17,7 +17,7 @@ import { TimeRangeContext } from "../common/context/TimeRangeContext"; export interface TopBlockedDomainsData { totalBlocked: number; - topBlocked: Array; + topBlocked: ApiTopDomainItem[]; } /** diff --git a/src/components/dashboard/TopClients.tsx b/src/components/dashboard/TopClients.tsx index fb10915..96cd578 100644 --- a/src/components/dashboard/TopClients.tsx +++ b/src/components/dashboard/TopClients.tsx @@ -17,7 +17,7 @@ import { TimeRangeContext } from "../common/context/TimeRangeContext"; export interface TopClientsData { totalQueries: number; - topClients: Array; + topClients: ApiClientData[]; } /** diff --git a/src/components/dashboard/TopDomains.tsx b/src/components/dashboard/TopDomains.tsx index 0768cbb..aa67437 100644 --- a/src/components/dashboard/TopDomains.tsx +++ b/src/components/dashboard/TopDomains.tsx @@ -17,7 +17,7 @@ import { TimeRangeContext } from "../common/context/TimeRangeContext"; export interface TopDomainsData { totalQueries: number; - topDomains: Array; + topDomains: ApiTopDomainItem[]; } /** diff --git a/src/components/dashboard/TopTable.tsx b/src/components/dashboard/TopTable.tsx index 50546e6..df3fb8f 100644 --- a/src/components/dashboard/TopTable.tsx +++ b/src/components/dashboard/TopTable.tsx @@ -15,13 +15,13 @@ export interface TopTableInnerProps { loading: boolean; title: string; data: T; - headers: Array; + headers: string[]; emptyMessage: string; isEmpty: (data: T) => boolean; generateRows: (data: T) => ReactNode; } -export class TopTable extends Component, {}> { +export class TopTable extends Component> { static defaultProps = { loading: true, title: "", @@ -112,13 +112,13 @@ export default function ({ }} renderInitial={() => ( )} @@ -136,13 +136,13 @@ export default function ({ )} renderErr={() => ( )} diff --git a/src/components/dashboard/__tests__/ClientsGraph.test.tsx b/src/components/dashboard/__tests__/ClientsGraph.test.tsx index 281e3b0..ce85103 100644 --- a/src/components/dashboard/__tests__/ClientsGraph.test.tsx +++ b/src/components/dashboard/__tests__/ClientsGraph.test.tsx @@ -49,7 +49,7 @@ const fakeData: ApiClientsGraph = { ] }; -const tick = global.tick; +const { tick } = global; it("shows loading indicator correctly", () => { const wrapper = shallow().dive(); diff --git a/src/components/dashboard/__tests__/GenericDoughnutChart.test.tsx b/src/components/dashboard/__tests__/GenericDoughnutChart.test.tsx index 5b6161c..457d5f9 100644 --- a/src/components/dashboard/__tests__/GenericDoughnutChart.test.tsx +++ b/src/components/dashboard/__tests__/GenericDoughnutChart.test.tsx @@ -17,23 +17,21 @@ import { transformData } from "../GenericDoughnutChart"; -const fakeData: Array = [ +const fakeData: ChartItem[] = [ { name: "roberta.net", ip: "8.239.48.32", percent: 0.38411761010240625 }, { name: "", ip: "89.60.252.186", percent: 0.2830935477791041 }, { name: "christop.net", ip: "181.219.42.222", percent: 0.6249293208519193 } ]; it("shows loading indicator correctly", () => { - const wrapper = shallow( - - ); + const wrapper = shallow(); expect(wrapper.children(".card-img-overlay")).toExist(); }); it("hides loading indicator correctly", async () => { const wrapper = shallow( - + ); expect(wrapper.children(".card-img-overlay")).not.toExist(); diff --git a/src/components/dashboard/__tests__/SummaryStats.test.tsx b/src/components/dashboard/__tests__/SummaryStats.test.tsx index 0bc6474..9497c5a 100644 --- a/src/components/dashboard/__tests__/SummaryStats.test.tsx +++ b/src/components/dashboard/__tests__/SummaryStats.test.tsx @@ -16,7 +16,7 @@ import { TranslatedSummaryStats } from "../SummaryStats"; -const tick = global.tick; +const { tick } = global; const fakeData: ApiSummary = { active_clients: 2, diff --git a/src/components/dashboard/__tests__/TopTable.test.tsx b/src/components/dashboard/__tests__/TopTable.test.tsx index bd5c3ea..c3fb53b 100644 --- a/src/components/dashboard/__tests__/TopTable.test.tsx +++ b/src/components/dashboard/__tests__/TopTable.test.tsx @@ -13,7 +13,7 @@ import { shallow } from "enzyme"; import { TopTable } from "../TopTable"; it("shows loading indicator correctly", () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.children().last()).toHaveClassName("card-img-overlay"); }); diff --git a/src/components/list/DomainInput.tsx b/src/components/list/DomainInput.tsx index ee817c2..77fd7b7 100644 --- a/src/components/list/DomainInput.tsx +++ b/src/components/list/DomainInput.tsx @@ -45,7 +45,7 @@ export class DomainInput extends Component< handleSubmit = (e: FormEvent) => { e.preventDefault(); - const domain = this.state.domain; + const { domain } = this.state; // Don't do anything for empty inputs if (domain.length === 0) { @@ -73,8 +73,8 @@ export class DomainInput extends Component< className={`form-control ${this.state.isValid ? "" : "is-invalid"}`} placeholder={placeholder} value={this.state.domain} - onChange={this.handleChange} disabled={!api.loggedIn} + onChange={this.handleChange} /> {api.loggedIn ? ( @@ -83,9 +83,9 @@ export class DomainInput extends Component< ) : null} diff --git a/src/components/list/ListPage.tsx b/src/components/list/ListPage.tsx index 0a4347b..27bb8c1 100644 --- a/src/components/list/ListPage.tsx +++ b/src/components/list/ListPage.tsx @@ -21,7 +21,7 @@ import { export interface ListPageProps { title: string; - note?: {} | string; + note?: Record | string; placeholder: string; onAdd: (domain: string) => Promise; onRefresh: () => Promise; @@ -162,9 +162,9 @@ export class ListPage extends Component<
    {this.props.note} diff --git a/src/components/list/__tests__/ListPage.test.tsx b/src/components/list/__tests__/ListPage.test.tsx index 63f9778..21e40b6 100644 --- a/src/components/list/__tests__/ListPage.test.tsx +++ b/src/components/list/__tests__/ListPage.test.tsx @@ -19,8 +19,7 @@ import Alert from "../../common/Alert"; import { DomainInputContainer } from "../DomainInput"; import DomainList from "../DomainList"; -const ignoreAPI = global.ignoreAPI; -const tick = global.tick; +const { ignoreAPI, tick } = global; type ListPageWrapper = ShallowWrapper< ListPageProps, diff --git a/src/components/log/QueryLog.tsx b/src/components/log/QueryLog.tsx index 88f0053..9d4934a 100644 --- a/src/components/log/QueryLog.tsx +++ b/src/components/log/QueryLog.tsx @@ -8,7 +8,7 @@ * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ -import React, { Component, Fragment } from "react"; +import React, { Component } from "react"; import ReactTable, { Filter, ReactTableFunction, @@ -34,12 +34,12 @@ import { } from "../../util/CancelablePromise"; export interface QueryLogState { - history: Array; + history: ApiQuery[]; cursor: null | string; loading: boolean; atEnd: boolean; filtersChanged: boolean; - filters: Array; + filters: Filter[]; } /** @@ -107,10 +107,10 @@ class QueryLog extends Component { color: [1, 4, 5, 6].includes(rowInfo.row.status) ? "red" : "green" } }; - } else { - // Unknown queries do not get colored - return {}; } + + // Unknown queries do not get colored + return {}; }; /** @@ -119,8 +119,8 @@ class QueryLog extends Component { * @param tableFilters the filters requested by the table * @return the filters converted for use by the API */ - parseFilters = (tableFilters: Array) => { - let filters: any = {}; + parseFilters = (tableFilters: Filter[]) => { + const filters: any = {}; for (const filter of tableFilters) { switch (filter.id) { @@ -134,7 +134,7 @@ class QueryLog extends Component { break; } - filters.query_type = parseInt(filter.value); + filters.query_type = Number.parseInt(filter.value); break; case "domain": if (filter.value.length === 0) { @@ -167,6 +167,7 @@ class QueryLog extends Component { filters.status = filter.value; break; } + break; case "dnssec": if (filter.value === "all") { @@ -243,14 +244,30 @@ class QueryLog extends Component { return ( ( + +   +
    +   +
    + )} onFetchData={state => { if (isEqual(state.filtered, this.state.filters)) { // If the filters have not changed, do not debounce the fetch. @@ -277,22 +294,6 @@ class QueryLog extends Component { history: [] }); }, 300)} - defaultFiltered={[ - { - id: "time", - value: getDefaultRange(t) - } - ]} - getTrProps={this.getRowProps} - ofText={this.state.atEnd ? "of" : "of at least"} - // Pad empty rows to have the same height as filled rows - PadRowComponent={() => ( - -   -
    -   -
    - )} /> ); } @@ -376,9 +377,9 @@ const selectionFilter = ( onChange: ReactTableFunction; }) => ( onUpdate({ ...settings, ip: e.target.value })} invalid={!isRouterIpValid} + onChange={e => onUpdate({ ...settings, ip: e.target.value })} /> @@ -72,7 +72,7 @@ const ConditionalForwardingSettings = ({ value={settings.cidr === -1 ? "" : settings.cidr} invalid={!isCidrValid} onChange={e => { - let cidr = parseInt(e.target.value); + let cidr = Number.parseInt(e.target.value); if (e.target.value.length === 0) { // Use -1 as an internal representation of the empty string. @@ -97,12 +97,12 @@ const ConditionalForwardingSettings = ({ id="localDomain" disabled={!settings.enabled} value={settings.domain} - onChange={e => onUpdate({ ...settings, domain: e.target.value })} invalid={!isDomainValid} + onChange={e => onUpdate({ ...settings, domain: e.target.value })} /> - + ); export default ConditionalForwardingSettings; diff --git a/src/components/settings/DHCPInfo.tsx b/src/components/settings/DHCPInfo.tsx index e9673b4..ead1eb3 100644 --- a/src/components/settings/DHCPInfo.tsx +++ b/src/components/settings/DHCPInfo.tsx @@ -221,8 +221,8 @@ class DHCPInfo extends Component { id="startIP" disabled={!this.state.settings.active} value={this.state.settings.ip_start} - onChange={this.onChange("ip_start", "value")} invalid={!isIpStartValid} + onChange={this.onChange("ip_start", "value")} /> @@ -235,8 +235,8 @@ class DHCPInfo extends Component { id="endIP" disabled={!this.state.settings.active} value={this.state.settings.ip_end} - onChange={this.onChange("ip_end", "value")} invalid={!isIpEndValid} + onChange={this.onChange("ip_end", "value")} /> @@ -249,8 +249,8 @@ class DHCPInfo extends Component { id="routerIP" disabled={!this.state.settings.active} value={this.state.settings.router_ip} - onChange={this.onChange("router_ip", "value")} invalid={!isRouterIpValid} + onChange={this.onChange("router_ip", "value")} /> @@ -264,15 +264,15 @@ class DHCPInfo extends Component { id="leaseTime" disabled={!this.state.settings.active} value={this.state.settings.lease_time} + invalid={!isLeaseTimeValid} onChange={(e: ChangeEvent) => this.setState(oldState => ({ settings: { ...oldState.settings, - lease_time: parseInt(e.target.value) + lease_time: Number.parseInt(e.target.value) } })) } - invalid={!isLeaseTimeValid} /> Hours @@ -287,8 +287,8 @@ class DHCPInfo extends Component { id="domain" disabled={!this.state.settings.active} value={this.state.settings.domain} - onChange={this.onChange("domain", "value")} invalid={!isDomainValid} + onChange={this.onChange("domain", "value")} /> diff --git a/src/components/settings/DNSInfo.tsx b/src/components/settings/DNSInfo.tsx index 2e06da2..16121c5 100644 --- a/src/components/settings/DNSInfo.tsx +++ b/src/components/settings/DNSInfo.tsx @@ -36,7 +36,7 @@ export interface DNSInfoState { alertType: AlertType; showAlert: boolean; processing: boolean; - upstreamDns: Array; + upstreamDns: string[]; conditionalForwarding: ConditionalForwardingObject; options: DnsOptionsObject; } @@ -226,26 +226,26 @@ class DNSInfo extends Component {

    {t("Upstream DNS Servers")}

    {t("Conditional Forwarding")}

    {t("DNS Options")}

    diff --git a/src/components/settings/DnsList.tsx b/src/components/settings/DnsList.tsx index 1c696ef..1a32ad3 100644 --- a/src/components/settings/DnsList.tsx +++ b/src/components/settings/DnsList.tsx @@ -18,7 +18,7 @@ import { } from "../../util/validate"; export interface DnsListProps { - upstreams: Array; + upstreams: string[]; onAdd: (upstream: string) => void; onRemove: (upstream: string) => void; } @@ -32,7 +32,7 @@ export interface DnsListProps { */ export const isAddressValid = ( address: string, - upstreams: Array + upstreams: string[] ): boolean => { return ( !upstreams.includes(address) && @@ -45,14 +45,14 @@ const DnsList = ({ upstreams, onAdd, onRemove }: DnsListProps) => ( {upstreams.map(upstream => ( onRemove(upstream)} address={upstream} + onRemove={() => onRemove(upstream)} /> ))} isAddressValid(address, upstreams)} upstreams={upstreams} + onAdd={onAdd} /> ); diff --git a/src/components/settings/DnsListNewItem.tsx b/src/components/settings/DnsListNewItem.tsx index 3343947..e8c35e5 100644 --- a/src/components/settings/DnsListNewItem.tsx +++ b/src/components/settings/DnsListNewItem.tsx @@ -20,12 +20,12 @@ import { export interface DnsListNewItemProps { onAdd: (address: string) => void; isValid: (address: string) => boolean; - upstreams: Array; + upstreams: string[]; } export interface DnsListNewItemState { address: string; - selected: Array; + selected: PreconfiguredUpstreamOption[]; } /** @@ -70,22 +70,23 @@ class DnsListNewItem extends Component< this.setState({ address })} - onChange={selected => this.setState({ selected })} options={preconfiguredUpstreamOptions.filter( upstream => !this.props.upstreams.includes(upstream.address) )} selected={this.state.selected} emptyLabel={t("Detected custom upstream server")} - positionFixed - ref={this.typeahead} + onInputChange={address => this.setState({ address })} + onChange={selected => this.setState({ selected })} /> diff --git a/src/components/settings/DnsOptionSettings.tsx b/src/components/settings/DnsOptionSettings.tsx index 688cf4b..e9f90c1 100644 --- a/src/components/settings/DnsOptionSettings.tsx +++ b/src/components/settings/DnsOptionSettings.tsx @@ -8,7 +8,7 @@ * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ -import React, { Fragment } from "react"; +import React from "react"; import { Col, FormGroup, Input, Label } from "reactstrap"; import { TFunction } from "i18next"; @@ -30,7 +30,7 @@ const DnsOptionSettings = ({ onUpdate, t }: DnsOptionSettingsProps) => ( - + <> - + ); export default DnsOptionSettings; diff --git a/src/components/settings/PreferenceSettings.tsx b/src/components/settings/PreferenceSettings.tsx index aa57a8d..f20fd49 100644 --- a/src/components/settings/PreferenceSettings.tsx +++ b/src/components/settings/PreferenceSettings.tsx @@ -157,14 +157,14 @@ class PreferenceSettings extends Component< return t(this.state.alertMessage, { error: t(this.state.error.key, this.state.error.data) }); - } else { - // Check if the message should be translated - if (this.state.translateMessage) { - return t(this.state.alertMessage); - } else { - return this.state.alertMessage; - } } + + // Check if the message should be translated + if (this.state.translateMessage) { + return t(this.state.alertMessage); + } + + return this.state.alertMessage; }; render() { diff --git a/src/components/settings/VersionInfo.tsx b/src/components/settings/VersionInfo.tsx index 3df81b0..841e232 100644 --- a/src/components/settings/VersionInfo.tsx +++ b/src/components/settings/VersionInfo.tsx @@ -14,7 +14,7 @@ import api from "../../util/api"; import VersionCard from "./VersionCard"; import { WithAPIData } from "../common/WithAPIData"; -class VersionInfo extends Component { +class VersionInfo extends Component { render() { const { t } = this.props; diff --git a/src/components/settings/__tests__/DHCPInfo.test.tsx b/src/components/settings/__tests__/DHCPInfo.test.tsx index 7caa311..cf9e1d6 100644 --- a/src/components/settings/__tests__/DHCPInfo.test.tsx +++ b/src/components/settings/__tests__/DHCPInfo.test.tsx @@ -14,7 +14,7 @@ import DHCPInfo, { DHCPInfoState } from "../DHCPInfo"; import fetchMock from "fetch-mock"; import { WithTranslation } from "react-i18next"; -const tick = global.tick; +const { tick } = global; const endpoint = "/api/settings/dhcp"; const fakeData = { diff --git a/src/components/settings/preconfiguredUpstreams.tsx b/src/components/settings/preconfiguredUpstreams.tsx index 7f12e35..b1c07ee 100644 --- a/src/components/settings/preconfiguredUpstreams.tsx +++ b/src/components/settings/preconfiguredUpstreams.tsx @@ -20,7 +20,7 @@ export interface PreconfiguredUpstream { * A list of preconfigured upstream DNS servers. Each item has primary and * secondary IPv4 and IPv6 server entries. Some addresses may be empty. */ -export const preconfiguredUpstreams: Array = [ +export const preconfiguredUpstreams: PreconfiguredUpstream[] = [ { name: "OpenDNS (ECS)", primaryIpv4: "208.67.222.222", @@ -103,7 +103,7 @@ export const preconfiguredUpstreamOptions = preconfiguredUpstreams.flatMap( address }); - let parsedUpstreams: Array = []; + const parsedUpstreams: PreconfiguredUpstreamOption[] = []; if (upstream.primaryIpv4.length > 0) { parsedUpstreams.push( diff --git a/src/config.development.tsx b/src/config.development.tsx index 61b835e..0266a6f 100644 --- a/src/config.development.tsx +++ b/src/config.development.tsx @@ -11,7 +11,7 @@ import { Config } from "./config"; const apiUrlBase = - process.env.REACT_APP_CUSTOM_API_URL || process.env.PUBLIC_URL; + process.env.REACT_APP_CUSTOM_API_URL ?? process.env.PUBLIC_URL; export default { developmentMode: true, diff --git a/src/containers/Full.tsx b/src/containers/Full.tsx index 0e71a3e..2cdff1e 100644 --- a/src/containers/Full.tsx +++ b/src/containers/Full.tsx @@ -60,7 +60,7 @@ const createRoute = (routeData: RouteData): ReactNode => { return (routeData as RouteGroup).children.map(createRoute); } - let navItem: RouteItem = routeData as RouteItem; + const navItem: RouteItem = routeData as RouteItem; return navItem.auth ? ( ("PREFERENCES_REQUEST"); +export const preferencesRequest = createAction("PREFERENCES_REQUEST"); export const preferencesSuccess = createAction( "PREFERENCES_SUCCESS" ); diff --git a/src/redux/sagas/applyLanguage.tsx b/src/redux/sagas/applyLanguage.tsx index 39e5755..0e43c69 100644 --- a/src/redux/sagas/applyLanguage.tsx +++ b/src/redux/sagas/applyLanguage.tsx @@ -18,7 +18,7 @@ import i18n from "i18next"; * @param action The action with the language to apply */ export function* applyLanguage(action: PayloadAction) { - const language = action.payload.language; + const { language } = action.payload; // Only change the language if it's different if (i18n.language !== language) { diff --git a/src/redux/sagas/autoLogin.tsx b/src/redux/sagas/autoLogin.tsx index 8a8b592..9ddd6be 100644 --- a/src/redux/sagas/autoLogin.tsx +++ b/src/redux/sagas/autoLogin.tsx @@ -28,14 +28,14 @@ export function* autoLogin() { try { // Check if we are logged in yield call(api.checkAuthStatus); - } catch (e) { - if (e.key === "unauthorized") { + } catch (error) { + if (error.key === "unauthorized") { // The API requires authentication and we are not already logged in return; } // An unexpected error occurred while checking our logged in state - throw e; + throw error; } if (!api.loggedIn) { diff --git a/src/redux/state/preferences.tsx b/src/redux/state/preferences.tsx index 943e5c1..715e534 100644 --- a/src/redux/state/preferences.tsx +++ b/src/redux/state/preferences.tsx @@ -38,7 +38,7 @@ export const loadInitialPreferences = (): ApiPreferences => { try { return JSON.parse(cachedPreferencesString); - } catch (e) { + } catch (_) { return defaultPreferences; } }; diff --git a/src/routes.tsx b/src/routes.tsx index c285c87..2fe9ee8 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -59,12 +59,12 @@ export interface RouteGroup { icon: string; auth: boolean; authStrict?: boolean; - children: Array; + children: RouteData[]; } export type RouteData = RouteItem | RouteGroup | RouteCustomItem; -export const nav: Array = [ +export const nav: RouteData[] = [ { name: "Dashboard", url: "/dashboard", diff --git a/src/setupTests.tsx b/src/setupTests.tsx index d75e8b1..90dddbb 100644 --- a/src/setupTests.tsx +++ b/src/setupTests.tsx @@ -11,10 +11,10 @@ import React from "react"; import { configure } from "enzyme"; import Adapter from "enzyme-adapter-react-16"; -import "jest-enzyme"; +import "jest-enzyme"; // eslint-disable-line import/no-unassigned-import import api from "./util/api"; import fetchMock from "fetch-mock"; -import "jest-localstorage-mock"; +import "jest-localstorage-mock"; // eslint-disable-line import/no-unassigned-import import { TFunction } from "i18next"; import config from "./config"; diff --git a/src/types/api.d.ts b/src/types/api.d.ts index e897347..1d92440 100644 --- a/src/types/api.d.ts +++ b/src/types/api.d.ts @@ -21,7 +21,7 @@ interface ApiQuery { interface ApiHistoryResponse { cursor: null | string; - history: Array; + history: ApiQuery[]; } interface ApiNetworkSettings { @@ -44,7 +44,7 @@ interface ApiVersions { } interface ApiDnsSettings { - upstream_dns: Array; + upstream_dns: string[]; options: { fqdn_required: boolean; bogus_priv: boolean; @@ -113,13 +113,13 @@ interface ApiStatus { } interface ApiClientsGraph { - over_time: Array; - clients: Array; + over_time: ApiClientOverTime[]; + clients: ApiClientGraphInfo[]; } interface ApiClientOverTime { timestamp: number; - data: Array; + data: number[]; } interface ApiClientGraphInfo { @@ -185,22 +185,22 @@ interface ApiTopDomainItem { } interface ApiTopBlockedDomains { - top_domains: Array; + top_domains: ApiTopDomainItem[]; blocked_queries: number; } interface ApiTopDomains { - top_domains: Array; + top_domains: ApiTopDomainItem[]; total_queries: number; } interface ApiTopClients { - top_clients: Array; + top_clients: ApiClientData[]; total_queries: number; } interface ApiTopBlockedClients { - top_clients: Array; + top_clients: ApiClient[]; blocked_queries: number; } diff --git a/src/util/CancelablePromise.tsx b/src/util/CancelablePromise.tsx index 2bda5bf..6f349ef 100644 --- a/src/util/CancelablePromise.tsx +++ b/src/util/CancelablePromise.tsx @@ -87,6 +87,7 @@ export function makeCancelable( if (repeatId !== null) { clearTimeout(repeatId); } + hasCanceled = true; } }; diff --git a/src/util/__tests__/basePath.test.tsx b/src/util/__tests__/basePath.test.tsx index 5ec92be..f86c6ee 100644 --- a/src/util/__tests__/basePath.test.tsx +++ b/src/util/__tests__/basePath.test.tsx @@ -22,10 +22,10 @@ it("should return the path from the base element when it exists", () => { const expectedBasePath = "/admin"; const baseElement = document.createElement("base"); baseElement.href = expectedBasePath; - document.head.appendChild(baseElement); + document.head.append(baseElement); const actualBasePath = getBasePath(); - document.head.removeChild(baseElement); + baseElement.remove(); expect(actualBasePath).toEqual(expectedBasePath); }); diff --git a/src/util/api.tsx b/src/util/api.tsx index 593579d..040f45a 100644 --- a/src/util/api.tsx +++ b/src/util/api.tsx @@ -15,7 +15,7 @@ import { TimeRange } from "../components/common/context/TimeRangeContext"; export class ApiClient { public loggedIn = false; - constructor(private http: HttpClient) {} + constructor(private readonly http: HttpClient) {} authenticate = (key: string): Promise => { return this.http.get("auth", { @@ -39,14 +39,14 @@ export class ApiClient { return this.http.get("stats/database/summary?" + timeRangeToParams(range)); }; - getHistoryGraph = (): Promise> => { + getHistoryGraph = (): Promise => { return this.http.get("stats/overTime/history"); }; getHistoryGraphDb = ( range: TimeRange, interval: number - ): Promise> => { + ): Promise => { return this.http.get( "stats/database/overTime/history?interval=" + interval + @@ -71,11 +71,11 @@ export class ApiClient { ); }; - getQueryTypes = (): Promise> => { + getQueryTypes = (): Promise => { return this.http.get("stats/query_types"); }; - getQueryTypesDb = (range: TimeRange): Promise> => { + getQueryTypesDb = (range: TimeRange): Promise => { return this.http.get( "stats/database/query_types?" + timeRangeToParams(range) ); @@ -161,36 +161,36 @@ export class ApiClient { return this.http.get("stats/history?" + paramsToString(params)); }; - getExactWhitelist = (): Promise> => { + getExactWhitelist = (): Promise => { return this.http.get("dns/whitelist/exact"); }; - getExactBlacklist = (): Promise> => { + getExactBlacklist = (): Promise => { return this.http.get("dns/blacklist/exact"); }; - getRegexWhitelist = (): Promise> => { + getRegexWhitelist = (): Promise => { return this.http.get("dns/whitelist/regex"); }; - getRegexBlacklist = (): Promise> => { + getRegexBlacklist = (): Promise => { return this.http.get("dns/blacklist/regex"); }; addExactWhitelist = (domain: string): Promise => { - return this.http.post("dns/whitelist/exact", { domain: domain }); + return this.http.post("dns/whitelist/exact", { domain }); }; addExactBlacklist = (domain: string): Promise => { - return this.http.post("dns/blacklist/exact", { domain: domain }); + return this.http.post("dns/blacklist/exact", { domain }); }; addRegexWhitelist = (domain: string): Promise => { - return this.http.post("dns/whitelist/regex", { domain: domain }); + return this.http.post("dns/whitelist/regex", { domain }); }; addRegexBlacklist = (domain: string): Promise => { - return this.http.post("dns/blacklist/regex", { domain: domain }); + return this.http.post("dns/blacklist/regex", { domain }); }; removeExactWhitelist = (domain: string): Promise => { diff --git a/src/util/basePath.ts b/src/util/basePath.ts index 8caa571..3fbaa07 100644 --- a/src/util/basePath.ts +++ b/src/util/basePath.ts @@ -20,7 +20,8 @@ export const getBasePath = (): string => { if (baseElement) { return new URL(baseElement.href).pathname; - } else { - return process.env.PUBLIC_URL; } + + // PUBLIC_URL is supplied by CRA, and will never be undefined + return process.env.PUBLIC_URL; }; diff --git a/src/util/http.tsx b/src/util/http.tsx index 7765d3b..a1b00f8 100644 --- a/src/util/http.tsx +++ b/src/util/http.tsx @@ -180,7 +180,7 @@ export const paramsToString = (params: { [key: string]: string | number; }): string => { return Object.keys(params) - .map(key => key + "=" + params[key]) + .map(key => `${key}=${params[key]}`) .join("&"); }; diff --git a/src/util/result.ts b/src/util/result.ts index edbf048..e0182a0 100644 --- a/src/util/result.ts +++ b/src/util/result.ts @@ -19,7 +19,7 @@ export interface Result { } export class Ok implements Result { - constructor(private value: T) {} + constructor(private readonly value: T) {} isErr(): boolean { return false; @@ -34,12 +34,12 @@ export class Ok implements Result { } unwrapErr(): E { - throw Error("unwrapErr on a Result.Ok"); + throw new Error("unwrapErr on a Result.Ok"); } } export class Err implements Result { - constructor(private err: E) {} + constructor(private readonly err: E) {} isErr(): boolean { return true; @@ -50,7 +50,7 @@ export class Err implements Result { } unwrap(): T { - throw Error("unwrap on a Result.Err"); + throw new Error("unwrap on a Result.Err"); } unwrapErr(): E { diff --git a/src/util/validate.tsx b/src/util/validate.tsx index 712258d..0847375 100644 --- a/src/util/validate.tsx +++ b/src/util/validate.tsx @@ -23,7 +23,7 @@ export function isValidHostname(hostname: string): boolean { // If the hostname without periods make a number, deny if (isPositiveNumber(joined)) return false; - return /^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*)+(\.([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*))*$/.test( + return /^([a-zA-Z\d]+(-[a-zA-Z\d]+)*)+(\.([a-zA-Z\d]+(-[a-zA-Z\d]+)*))*$/.test( hostname ); } @@ -39,15 +39,16 @@ export function isValidDomain(domain: string): boolean { export function isPositiveNumber(input: string): boolean { // Because parseInt has limitations, e.g. parseInt("15ex") is parsed to 15 // Caution, does not work with negative numbers, replace with /^(\-|\+)?([0-9])$/ if needed - return /^[0-9]+$/.test(input); + return /^\d+$/.test(input); } export function isValidRegex(regex: string): boolean { try { new RegExp(regex); - } catch (e) { + } catch (_) { return false; } + return true; } @@ -67,7 +68,7 @@ export function isValidIpv4(address: string): boolean { // All segments must be numbers (positive) return segments.every( - segment => isPositiveNumber(segment) && parseInt(segment) < 256 + segment => isPositiveNumber(segment) && Number.parseInt(segment) < 256 ); } @@ -111,7 +112,7 @@ export function isValidIpv4Cidr(cidr: string): boolean { * @param address */ export function isValidIpv6(address: string): boolean { - return /^[a-fA-F0-9:]+$/.test(address); + return /^[a-fA-F\d:]+$/.test(address); } /** @@ -125,7 +126,7 @@ export function isValidIpv6(address: string): boolean { * @param address The IPv6 address */ export function isValidIpv6OptionalPort(address: string): boolean { - return /^(\[[a-fA-F0-9:]+]:\d+|[a-fA-F0-9:]+)$/.test(address); + return /^(\[[a-fA-F\d:]+]:\d+|[a-fA-F\d:]+)$/.test(address); } /** @@ -134,7 +135,7 @@ export function isValidIpv6OptionalPort(address: string): boolean { * @param cidr The string to check */ export function isValidIpv6Cidr(cidr: string): boolean { - const cidrNum = parseInt(cidr); + const cidrNum = Number.parseInt(cidr); return !isNaN(cidrNum) && cidrNum > 0 && cidrNum <= 128 && cidrNum % 4 === 0; } diff --git a/src/views/Dashboard.tsx b/src/views/Dashboard.tsx index 8bc45db..36cc58e 100644 --- a/src/views/Dashboard.tsx +++ b/src/views/Dashboard.tsx @@ -8,7 +8,7 @@ * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ -import React, { Fragment } from "react"; +import React from "react"; import SummaryStats from "../components/dashboard/SummaryStats"; import QueriesGraph from "../components/dashboard/QueriesGraph"; import { ClientsGraphContainer } from "../components/dashboard/ClientsGraph"; @@ -37,7 +37,7 @@ export default () => ( {api.loggedIn ? ( - + <>
    @@ -67,7 +67,7 @@ export default () => (
    -
    + ) : null} ); diff --git a/src/views/ExactBlacklist.tsx b/src/views/ExactBlacklist.tsx index 9b542c2..9a21958 100644 --- a/src/views/ExactBlacklist.tsx +++ b/src/views/ExactBlacklist.tsx @@ -21,11 +21,11 @@ const Blacklist: FunctionComponent = props => { ); diff --git a/src/views/ExactWhitelist.tsx b/src/views/ExactWhitelist.tsx index 89827b8..a41eb24 100644 --- a/src/views/ExactWhitelist.tsx +++ b/src/views/ExactWhitelist.tsx @@ -21,11 +21,11 @@ const Whitelist: FunctionComponent = props => { ); diff --git a/src/views/Login.tsx b/src/views/Login.tsx index e460380..db0e6bb 100644 --- a/src/views/Login.tsx +++ b/src/views/Login.tsx @@ -8,7 +8,7 @@ * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ -import React, { ChangeEvent, Component, FormEvent, Fragment } from "react"; +import React, { ChangeEvent, Component, FormEvent } from "react"; import { Redirect } from "react-router-dom"; import sha from "sha.js"; import api from "../util/api"; @@ -56,7 +56,7 @@ class Login extends Component { */ authenticate = (e?: FormEvent) => { // Prevent the page from reloading when the user gets redirected - e && e.preventDefault(); + e?.preventDefault(); // Hash the password twice before sending to the API let hashedPassword = sha("sha256") @@ -79,7 +79,7 @@ class Login extends Component { } // Redirect to the page the user was originally going to, or if that doesn't exist, go to home - const locationState = this.props.location.state || { + const locationState = this.props.location.state ?? { from: { pathname: "/" } }; this.props.history.push(locationState.from.pathname); @@ -116,12 +116,12 @@ class Login extends Component { // tell them they will be redirected once login is successful this.props.location.state && this.props.location.state.from.pathname in routes(t) ? ( - + <>
    {t('You will be transferred to the "{{page}}" page', { page: routes(t)[this.props.location.state.from.pathname] })} -
    + ) : null } { @@ -152,12 +152,12 @@ class Login extends Component { } >
    diff --git a/src/views/RegexBlacklist.tsx b/src/views/RegexBlacklist.tsx index e31af49..288d090 100644 --- a/src/views/RegexBlacklist.tsx +++ b/src/views/RegexBlacklist.tsx @@ -21,11 +21,11 @@ const RegexBlacklist: FunctionComponent = props => { ); diff --git a/src/views/RegexWhitelist.tsx b/src/views/RegexWhitelist.tsx index 34e6627..090067a 100644 --- a/src/views/RegexWhitelist.tsx +++ b/src/views/RegexWhitelist.tsx @@ -21,11 +21,11 @@ const RegexWhitelist: FunctionComponent = props => { );