From c34a68304ec1c59d8adb55ff12403a020c1bf8d3 Mon Sep 17 00:00:00 2001 From: Severiano Badajoz Date: Tue, 19 May 2020 12:38:29 -0700 Subject: [PATCH] remove all linting errors on client/src (#1463) * run eslint --fix * camelcase * camelCase config part 1 * part 2 * part 3 - removing subscripts * fix "class-methods-use-this" * fix "class-methods-use-this" * fix eslint ignores * add eslint ignore for set state in update * reformat comments to appease eslint * add a11y features * sort-comp fix * a11y fix * add ignore for set state in update * add a11y htmlFor * remove unused toast * remove unnecessary bind * add ignore for set state in update * add rel="noopener noreferrer" Using target="_blank" without rel="noopener noreferrer" is a security risk: see https://mathiasbynens.github.io/rel-noopener * use arrow function to bind * remove unused definitions/declarations * prettier * remove unused state * add comments to empty catch blocks remove curly brackets * escape ' * use eqeqeq * switch from default export * remove ignore log * remove static * fix import * revert subscripting config * clean-up * remove unnecessary subscript * fix new errors from master * change category click handler to a class property * fix camelcase changes that slipped by * unused import * Fix newly introduced ESLint errors from addGenes --- client/__tests__/e2e/config.js | 6 +- client/__tests__/e2e/e2e.test.js | 13 +- client/__tests__/e2e/e2eAnnotations.test.js | 5 +- client/__tests__/e2e/feature.test.js | 8 +- client/__tests__/util/promiseLimit.test.js | 2 +- client/configuration/webpack/cspHashPlugin.js | 2 +- client/src/actions/index.js | 2 +- .../src/components/autosave/filenameDialog.js | 2 +- client/src/components/autosave/index.js | 3 +- .../components/categorical/category/index.js | 57 ++++--- client/src/components/categorical/index.js | 2 +- .../src/components/categorical/labelInput.js | 6 +- .../src/components/categorical/value/index.js | 11 +- client/src/components/framework/toasters.js | 5 - .../src/components/geneExpression/addGenes.js | 2 +- client/src/components/graph/graph.js | 53 +++--- .../graph/overlays/centroidLabels.js | 7 +- .../graph/overlays/graphOverlayLayer.js | 6 +- .../leftSidebar/topLeftLogoAndTitle.js | 4 +- .../src/components/menubar/cellSetButtons.js | 4 +- .../src/components/menubar/diffexpButtons.js | 27 +-- client/src/components/menubar/embedding.js | 4 +- client/src/components/menubar/index.js | 155 +++++++++--------- .../src/components/scatterplot/scatterplot.js | 28 ++-- client/src/components/termsPrompt/index.js | 29 ++-- client/src/index.js | 1 - client/src/reducers/colors.js | 2 +- client/src/reducers/layoutChoice.js | 2 +- client/src/reducers/ontology.js | 9 +- client/src/reducers/world.js | 6 +- client/src/util/dataframe/labelIndex.js | 10 +- client/src/util/promiseLimit.js | 2 +- client/src/util/significantDigits.js | 2 +- .../src/util/typedCrossfilter/crossfilter.js | 9 +- 34 files changed, 248 insertions(+), 238 deletions(-) diff --git a/client/__tests__/e2e/config.js b/client/__tests__/e2e/config.js index d4748edd..80078f8b 100644 --- a/client/__tests__/e2e/config.js +++ b/client/__tests__/e2e/config.js @@ -1,9 +1,9 @@ -export const jest_env = process.env.JEST_ENV; +export const jestEnv = process.env.JEST_ENV; export const appPort = process.env.CXG_SERVER_PORT; export const appUrlBase = process.env.CXG_URL_BASE || `http://localhost:${appPort}`; -export const DEV = jest_env === "dev"; -export const DEBUG = jest_env === "debug"; +export const DEV = jestEnv === "dev"; +export const DEBUG = jestEnv === "debug"; export const DATASET = "pbmc3k"; if (DEBUG) jest.setTimeout(100000); diff --git a/client/__tests__/e2e/e2e.test.js b/client/__tests__/e2e/e2e.test.js index 226d37f1..76e1b4d0 100644 --- a/client/__tests__/e2e/e2e.test.js +++ b/client/__tests__/e2e/e2e.test.js @@ -7,7 +7,10 @@ import { appUrlBase, DATASET } from "./config"; import { setupTestBrowser } from "./testBrowser"; import { datasets } from "./data"; -let browser, page, utils, cxgActions; +let browser; +let page; +let utils; +let cxgActions; const data = datasets[DATASET]; beforeAll(async () => { @@ -34,9 +37,9 @@ describe("did launch", () => { try { await utils.clickOn("tos-cookies-accept", { timeout: 500 }); } catch { - console.warn("No terms of service footer detected.") + console.warn("No terms of service footer detected."); } - page.waitFor(50); // give the footer a chance to disappear + page.waitFor(50); // give the footer a chance to disappear const result = await page.$("[data-testid='tos-cookies-accept']"); expect(result).toBeNull(); }); @@ -130,7 +133,7 @@ describe("gene entry", () => { testGenes ); expect(allHistograms).toEqual(expect.arrayContaining(testGenes)); - expect(allHistograms.length).toEqual(testGenes.length); + expect(allHistograms).toHaveLength(testGenes.length); }); }); @@ -144,7 +147,7 @@ describe("differential expression", () => { expect(allHistograms).toEqual( expect.arrayContaining(data.diffexp["gene-results"]) ); - expect(allHistograms.length).toEqual(data.diffexp["gene-results"].length); + expect(allHistograms).toHaveLength(data.diffexp["gene-results"].length); }); }); diff --git a/client/__tests__/e2e/e2eAnnotations.test.js b/client/__tests__/e2e/e2eAnnotations.test.js index 6da0c42e..f0041529 100644 --- a/client/__tests__/e2e/e2eAnnotations.test.js +++ b/client/__tests__/e2e/e2eAnnotations.test.js @@ -5,7 +5,10 @@ import { appUrlBase, DATASET } from "./config"; import { setupTestBrowser } from "./testBrowser"; import { datasets } from "./data"; -let browser, page, utils, actions; +let browser; +let page; +let utils; +let actions; const data = datasets[DATASET]; beforeAll(async () => { diff --git a/client/__tests__/e2e/feature.test.js b/client/__tests__/e2e/feature.test.js index 0fed000a..9e7adc11 100644 --- a/client/__tests__/e2e/feature.test.js +++ b/client/__tests__/e2e/feature.test.js @@ -12,9 +12,13 @@ import { appUrlBase, DEBUG, DEV, DATASET } from "./config"; import { puppeteerUtils, cellxgeneActions } from "./puppeteerUtils"; import { datasets } from "./data"; -let browser, page, utils, cxgActions, spy; +let browser; +let page; +let utils; +let cxgActions; +let spy; const browserViewport = { width: 1280, height: 960 }; -let data = datasets[DATASET].features; +const data = datasets[DATASET].features; if (DEBUG) jest.setTimeout(100000); if (DEV) jest.setTimeout(10000); diff --git a/client/__tests__/util/promiseLimit.test.js b/client/__tests__/util/promiseLimit.test.js index fc6832f6..659e2f23 100644 --- a/client/__tests__/util/promiseLimit.test.js +++ b/client/__tests__/util/promiseLimit.test.js @@ -1,4 +1,4 @@ -import { PromiseLimit } from "../../src/util/promiseLimit"; +import PromiseLimit from "../../src/util/promiseLimit"; import { range } from "../../src/util/range"; const delay = (t) => new Promise((resolve, reject) => setTimeout(resolve, t)); diff --git a/client/configuration/webpack/cspHashPlugin.js b/client/configuration/webpack/cspHashPlugin.js index d56d2b32..99afd46f 100644 --- a/client/configuration/webpack/cspHashPlugin.js +++ b/client/configuration/webpack/cspHashPlugin.js @@ -54,7 +54,7 @@ class CspHashPlugin { .createHash("sha256") .update(str, "utf8") .digest("base64"); - return "sha256-" + hash; + return `sha256-${hash}`; } } diff --git a/client/src/actions/index.js b/client/src/actions/index.js index 19ff498d..0bfffd51 100644 --- a/client/src/actions/index.js +++ b/client/src/actions/index.js @@ -7,7 +7,7 @@ import { doBinaryRequest, dispatchNetworkErrorMessageToUser, } from "../util/actionHelpers"; -import { PromiseLimit } from "../util/promiseLimit"; +import PromiseLimit from "../util/promiseLimit"; import { requestReembed, reembedResetWorldToUniverse } from "./reembed"; import { loadUserColorConfig } from "../util/stateManager/colorHelpers"; diff --git a/client/src/components/autosave/filenameDialog.js b/client/src/components/autosave/filenameDialog.js index e25792d1..c2f02e64 100644 --- a/client/src/components/autosave/filenameDialog.js +++ b/client/src/components/autosave/filenameDialog.js @@ -18,7 +18,7 @@ import { saveInProgress: state.autosave?.saveInProgress ?? false, lastSavedObsAnnotations: state.autosave?.lastSavedObsAnnotations, error: state.autosave?.error, - writableCategoriesEnabled: state.config?.parameters?.["annotations"] ?? false, + writableCategoriesEnabled: state.config?.parameters?.annotations ?? false, })) class FilenameDialog extends React.Component { constructor(props) { diff --git a/client/src/components/autosave/index.js b/client/src/components/autosave/index.js index bffd1740..d77dcc65 100644 --- a/client/src/components/autosave/index.js +++ b/client/src/components/autosave/index.js @@ -1,6 +1,5 @@ import React from "react"; import { connect } from "react-redux"; -import * as globals from "../../globals"; import actions from "../../actions"; import FilenameDialog from "./filenameDialog"; @@ -11,7 +10,7 @@ import FilenameDialog from "./filenameDialog"; saveInProgress: state.autosave?.saveInProgress ?? false, lastSavedObsAnnotations: state.autosave?.lastSavedObsAnnotations, error: state.autosave?.error, - writableCategoriesEnabled: state.config?.parameters?.["annotations"] ?? false, + writableCategoriesEnabled: state.config?.parameters?.annotations ?? false, initialDataLoadComplete: state.autosave?.initialDataLoadComplete, })) class Autosave extends React.Component { diff --git a/client/src/components/categorical/category/index.js b/client/src/components/categorical/category/index.js index e3c6b239..dfd5e296 100644 --- a/client/src/components/categorical/category/index.js +++ b/client/src/components/categorical/category/index.js @@ -64,7 +64,7 @@ class Category extends React.Component { } else if (categoryCount.selectedCatCount < categoryCount.totalCatCount) { /* to be explicit... */ this.checkbox.indeterminate = true; - this.setState({ isChecked: false }); + this.setState({ isChecked: false }); // eslint-disable-line react/no-did-update-set-state } } } @@ -77,14 +77,15 @@ class Category extends React.Component { }); }; - toggleAll() { - const { dispatch, metadataField } = this.props; - dispatch({ - type: "categorical metadata filter all of these", - metadataField, - }); - this.setState({ isChecked: true }); - } + handleCategoryClick = () => { + const { annotations, metadataField, onExpansionChange } = this.props; + const editingCategory = + annotations.isEditingCategoryName && + annotations.categoryBeingEdited === metadataField; + if (!editingCategory) { + onExpansionChange(metadataField); + } + }; toggleNone() { const { dispatch, metadataField } = this.props; @@ -95,6 +96,15 @@ class Category extends React.Component { this.setState({ isChecked: false }); } + toggleAll() { + const { dispatch, metadataField } = this.props; + dispatch({ + type: "categorical metadata filter all of these", + metadataField, + }); + this.setState({ isChecked: true }); + } + handleToggleAllClick() { const { isChecked } = this.state; // || this.checkbox.indeterminate === false @@ -115,6 +125,8 @@ class Category extends React.Component { globals.categoryDisplayStringMaxLength ); + const checkboxID = `category-select-${metadataField}`; + return (
-
diff --git a/client/src/index.js b/client/src/index.js index b4655afa..7f2de221 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -1,5 +1,4 @@ // jshint esversion: 6 -/* eslint-disable no-console */ import React from "react"; import ReactDOM from "react-dom"; import { Provider } from "react-redux"; diff --git a/client/src/reducers/colors.js b/client/src/reducers/colors.js index aa10d077..a7c566fe 100644 --- a/client/src/reducers/colors.js +++ b/client/src/reducers/colors.js @@ -150,7 +150,7 @@ const ColorsReducer = ( case "annotation: delete label": { const { world } = nextSharedState; const { colorMode, colorAccessor } = state; - const { metadataField, colors } = action; + const { metadataField } = action; if ( colorMode !== "color by categorical metadata" || colorAccessor !== metadataField diff --git a/client/src/reducers/layoutChoice.js b/client/src/reducers/layoutChoice.js index 12486bc0..fa04f6f7 100644 --- a/client/src/reducers/layoutChoice.js +++ b/client/src/reducers/layoutChoice.js @@ -49,7 +49,7 @@ const LayoutChoice = ( } case "reembed: add reembedding": { - const name = action.schema.name; + const { name } = action.schema; const available = Array.from(new Set(state.available).add(name)); return { ...state, diff --git a/client/src/reducers/ontology.js b/client/src/reducers/ontology.js index 504d26ff..828bc88a 100644 --- a/client/src/reducers/ontology.js +++ b/client/src/reducers/ontology.js @@ -9,11 +9,12 @@ const Ontology = ( ) => { switch (action.type) { case "configuration load complete": { - /* eslint-disable camelcase */ const enabled = - action.config?.parameters?.annotations_cell_ontology_enabled ?? false; - const terms = action.config?.parameters?.annotations_cell_ontology_terms; - /* eslint-enable camelcase */ + action.config?.parameters?.["annotations_cell_ontology_enabled"] ?? + false; + const terms = + action.config?.parameters?.["annotations_cell_ontology_terms"]; + const termSet = new Set(terms); return { ...state, diff --git a/client/src/reducers/world.js b/client/src/reducers/world.js index 0e9685ad..6a62df26 100644 --- a/client/src/reducers/world.js +++ b/client/src/reducers/world.js @@ -41,8 +41,8 @@ const WorldReducer = ( const { dim } = action; // we don't clip anything except for varData and obsAnnotations - let unclipped = state.unclipped; - if (dim == "varData" || dim == "obsAnnotations") { + let { unclipped } = state; + if (dim === "varData" || dim === "obsAnnotations") { unclipped = { ...unclipped, [dim]: universe[dim].clone(), @@ -298,7 +298,7 @@ const WorldReducer = ( const { obsLayout: origObsLayout, schema: origSchema } = state; const { embedding, schema: embeddingSchema } = action; - const { dims, name } = embeddingSchema; + const { dims } = embeddingSchema; let obsLayout = origObsLayout; let schema = origSchema; diff --git a/client/src/util/dataframe/labelIndex.js b/client/src/util/dataframe/labelIndex.js index 0b01adda..79f69802 100644 --- a/client/src/util/dataframe/labelIndex.js +++ b/client/src/util/dataframe/labelIndex.js @@ -1,3 +1,4 @@ +/* eslint-disable max-classes-per-file */ /** Label indexing - map a label to & from an integer offset. See Dataframe for how this is used. @@ -23,7 +24,6 @@ function extent(tarr) { return [min, max]; } -/* eslint-disable class-methods-use-this */ class IdentityInt32Index { /* identity/noop index, with small assumptions that labels are int32 @@ -41,11 +41,13 @@ class IdentityInt32Index { return k; } + // eslint-disable-next-line class-methods-use-this getOffset(i) { // label to offset return i; } + // eslint-disable-next-line class-methods-use-this getLabel(i) { // offset to label return i; @@ -93,9 +95,6 @@ class IdentityInt32Index { return this.__promote(labelArray); } } -/* eslint-enable class-methods-use-this */ - -/* eslint-disable class-methods-use-this */ class DenseInt32Index { /* DenseInt32Index indexes integer labels, and uses Int32Array typed arrays @@ -177,9 +176,7 @@ class DenseInt32Index { return this.__promote(labelArray); } } -/* eslint-enable class-methods-use-this */ -/* eslint-disable class-methods-use-this */ class KeyIndex { /* KeyIndex indexes arbitrary JS primitive types, and uses a Map() @@ -223,6 +220,7 @@ class KeyIndex { return this.rindex.length; } + // eslint-disable-next-line class-methods-use-this subsetLabels(labelArray) { return new KeyIndex(labelArray); } diff --git a/client/src/util/promiseLimit.js b/client/src/util/promiseLimit.js index ad502fbc..1b1731b3 100644 --- a/client/src/util/promiseLimit.js +++ b/client/src/util/promiseLimit.js @@ -13,7 +13,7 @@ return Promise.all([ plimit.add(() => fetch('/baz')) ]) */ -export class PromiseLimit { +export default class PromiseLimit { constructor(maxConcurrency) { this.queue = new Set(); this.maxConcurrency = maxConcurrency; diff --git a/client/src/util/significantDigits.js b/client/src/util/significantDigits.js index 6d3e005e..21fbf83f 100644 --- a/client/src/util/significantDigits.js +++ b/client/src/util/significantDigits.js @@ -5,6 +5,6 @@ export default (n) => { return n .toExponential() - .replace(/e[\+\-0-9]*$/, "") + .replace(/e[+\-0-9]*$/, "") .replace(/^0\.?0*|\./, "").length; }; diff --git a/client/src/util/typedCrossfilter/crossfilter.js b/client/src/util/typedCrossfilter/crossfilter.js index f328d3a8..3ee99386 100644 --- a/client/src/util/typedCrossfilter/crossfilter.js +++ b/client/src/util/typedCrossfilter/crossfilter.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line max-classes-per-file import PositiveIntervals from "./positiveIntervals"; import BitArray from "./bitArray"; import { @@ -409,7 +410,7 @@ class ImmutableScalarDimension extends _ImmutableBaseDimension { this.index = makeSortIndex(array); } - /* eslint-disable class-methods-use-this */ + // eslint-disable-next-line class-methods-use-this _createValueArray(data, mapf, array) { // create dimension value array const len = data.length; @@ -419,7 +420,6 @@ class ImmutableScalarDimension extends _ImmutableBaseDimension { } return larray; } - /* eslint-enable class-methods-use-this */ select(spec) { const { mode } = spec; @@ -466,7 +466,7 @@ class ImmutableScalarDimension extends _ImmutableBaseDimension { const ranges = []; const r = [ lowerBoundIndirect(value, index, lo, 0, value.length), - !!inclusive + inclusive ? upperBoundIndirect(value, index, hi, 0, value.length) : lowerBoundIndirect(value, index, hi, 0, value.length), ]; @@ -514,11 +514,10 @@ class ImmutableEnumDimension extends ImmutableScalarDimension { }); } - /* eslint-disable class-methods-use-this */ + // eslint-disable-next-line class-methods-use-this selectRange() { throw new Error("range selection unsupported on Enumerated dimension"); } - /* eslint-enable class-methods-use-this */ } class ImmutableSpatialDimension extends _ImmutableBaseDimension {