mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-16 21:37:59 +08:00
[WIP] JS lint and dead code removal (#1053)
* lint and dead code removal * fix regressions
This commit is contained in:
@@ -44,7 +44,7 @@ class HistogramBrush extends React.PureComponent {
|
||||
return varData.col(field);
|
||||
}
|
||||
|
||||
calcHistogramCache = memoize((col, field) => {
|
||||
calcHistogramCache = memoize(col => {
|
||||
/*
|
||||
recalculate expensive stuff, notably bins, summaries, etc.
|
||||
*/
|
||||
@@ -240,15 +240,23 @@ class HistogramBrush extends React.PureComponent {
|
||||
};
|
||||
}
|
||||
|
||||
drawHistogram(svgRef) {
|
||||
const { field, world } = this.props;
|
||||
const col = HistogramBrush.getColumn(world, field);
|
||||
const histogramCache = this.calcHistogramCache(col, field);
|
||||
const { x, y, bins } = histogramCache;
|
||||
this._histogram = { x, y, bins, svgRef };
|
||||
}
|
||||
handleSetGeneAsScatterplotX = () => {
|
||||
const { dispatch, field } = this.props;
|
||||
dispatch({
|
||||
type: "set scatterplot x",
|
||||
data: field
|
||||
});
|
||||
};
|
||||
|
||||
handleColorAction() {
|
||||
handleSetGeneAsScatterplotY = () => {
|
||||
const { dispatch, field } = this.props;
|
||||
dispatch({
|
||||
type: "set scatterplot y",
|
||||
data: field
|
||||
});
|
||||
};
|
||||
|
||||
handleColorAction = () => {
|
||||
const { dispatch, field, world, ranges } = this.props;
|
||||
|
||||
if (world.obsAnnotations.hasCol(field)) {
|
||||
@@ -260,9 +268,9 @@ class HistogramBrush extends React.PureComponent {
|
||||
} else if (world.varData.hasCol(field)) {
|
||||
dispatch(actions.requestSingleGeneExpressionCountsForColoringPOST(field));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
removeHistogram() {
|
||||
removeHistogram = () => {
|
||||
const {
|
||||
dispatch,
|
||||
field,
|
||||
@@ -291,26 +299,14 @@ class HistogramBrush extends React.PureComponent {
|
||||
data: null
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handleSetGeneAsScatterplotX() {
|
||||
return () => {
|
||||
const { dispatch, field } = this.props;
|
||||
dispatch({
|
||||
type: "set scatterplot x",
|
||||
data: field
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
handleSetGeneAsScatterplotY() {
|
||||
return () => {
|
||||
const { dispatch, field } = this.props;
|
||||
dispatch({
|
||||
type: "set scatterplot y",
|
||||
data: field
|
||||
});
|
||||
};
|
||||
drawHistogram(svgRef) {
|
||||
const { field, world } = this.props;
|
||||
const col = HistogramBrush.getColumn(world, field);
|
||||
const histogramCache = this.calcHistogramCache(col);
|
||||
const { x, y, bins } = histogramCache;
|
||||
this._histogram = { x, y, bins, svgRef };
|
||||
}
|
||||
|
||||
renderAxesBrushBins(x, y, bins, svgRef, field) {
|
||||
@@ -439,7 +435,7 @@ class HistogramBrush extends React.PureComponent {
|
||||
<ButtonGroup style={{ marginRight: 7 }}>
|
||||
<Button
|
||||
data-testid={`plot-x-${field}`}
|
||||
onClick={this.handleSetGeneAsScatterplotX(field).bind(this)}
|
||||
onClick={this.handleSetGeneAsScatterplotX}
|
||||
active={scatterplotXXaccessor === field}
|
||||
intent={scatterplotXXaccessor === field ? "primary" : "none"}
|
||||
>
|
||||
@@ -447,7 +443,7 @@ class HistogramBrush extends React.PureComponent {
|
||||
</Button>
|
||||
<Button
|
||||
data-testid={`plot-y-${field}`}
|
||||
onClick={this.handleSetGeneAsScatterplotY(field).bind(this)}
|
||||
onClick={this.handleSetGeneAsScatterplotY}
|
||||
active={scatterplotYYaccessor === field}
|
||||
intent={scatterplotYYaccessor === field ? "primary" : "none"}
|
||||
>
|
||||
@@ -459,7 +455,7 @@ class HistogramBrush extends React.PureComponent {
|
||||
{isUserDefined ? (
|
||||
<Button
|
||||
minimal
|
||||
onClick={this.removeHistogram.bind(this)}
|
||||
onClick={this.removeHistogram}
|
||||
style={{
|
||||
color: globals.blue,
|
||||
cursor: "pointer",
|
||||
@@ -475,7 +471,7 @@ class HistogramBrush extends React.PureComponent {
|
||||
hoverOpenDelay={globals.tooltipHoverOpenDelay}
|
||||
>
|
||||
<Button
|
||||
onClick={this.handleColorAction.bind(this)}
|
||||
onClick={this.handleColorAction}
|
||||
active={colorAccessor === field}
|
||||
intent={colorAccessor === field ? "primary" : "none"}
|
||||
data-testclass="colorby"
|
||||
|
||||
@@ -83,7 +83,7 @@ class Categories extends React.Component {
|
||||
|
||||
categoryNameErrorMessage = name => {
|
||||
const err = this.categoryNameError(name);
|
||||
if (err == "duplicate") {
|
||||
if (err === "duplicate") {
|
||||
return (
|
||||
<span>
|
||||
<span style={{ fontStyle: "italic" }}>{name}</span> already exists -
|
||||
@@ -91,7 +91,7 @@ class Categories extends React.Component {
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (err == "characters") {
|
||||
if (err === "characters") {
|
||||
return (
|
||||
<span>
|
||||
<span style={{ fontStyle: "italic" }}>{name}</span> contains illegal
|
||||
|
||||
@@ -149,7 +149,7 @@ class Category extends React.Component {
|
||||
or return an error type.
|
||||
*/
|
||||
const { metadataField, universe } = this.props;
|
||||
const obsByName = universe.schema.annotations.obsByName;
|
||||
const { obsByName } = universe.schema.annotations;
|
||||
|
||||
if (obsByName[metadataField].categories.indexOf(name) !== -1) {
|
||||
return "duplicate";
|
||||
@@ -165,7 +165,7 @@ class Category extends React.Component {
|
||||
labelNameErrorMessage = name => {
|
||||
const { metadataField } = this.props;
|
||||
const err = this.labelNameError(name);
|
||||
if (err == "duplicate") {
|
||||
if (err === "duplicate") {
|
||||
return (
|
||||
<span>
|
||||
<span style={{ fontStyle: "italic" }}>{name}</span> already exists
|
||||
@@ -174,7 +174,7 @@ class Category extends React.Component {
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (err == "characters") {
|
||||
if (err === "characters") {
|
||||
return (
|
||||
<span>
|
||||
<span style={{ fontStyle: "italic" }}>{name}</span> contains illegal
|
||||
@@ -242,8 +242,7 @@ class Category extends React.Component {
|
||||
colorAccessor,
|
||||
categoricalSelection,
|
||||
isUserAnno,
|
||||
annotations,
|
||||
universe
|
||||
annotations
|
||||
} = this.props;
|
||||
const { isTruncated } = categoricalSelection[metadataField];
|
||||
|
||||
@@ -288,7 +287,6 @@ class Category extends React.Component {
|
||||
type="checkbox"
|
||||
/>
|
||||
<span className="bp3-control-indicator" />
|
||||
{""}
|
||||
</label>
|
||||
<span
|
||||
data-testid={`category-expand-${metadataField}`}
|
||||
|
||||
@@ -144,7 +144,9 @@ class Occupancy extends React.Component {
|
||||
categoryIndex
|
||||
} = this.props;
|
||||
|
||||
this.canvas?.getContext("2d").clearRect(0, 0, this._WIDTH, this._HEIGHT);
|
||||
const { canvas } = this;
|
||||
if (canvas)
|
||||
canvas.getContext("2d").clearRect(0, 0, this._WIDTH, this._HEIGHT);
|
||||
|
||||
const colorByIsCatagoricalData = !!categoricalSelection[colorAccessor];
|
||||
|
||||
|
||||
@@ -9,13 +9,12 @@ import {
|
||||
MenuItem,
|
||||
Popover,
|
||||
Position,
|
||||
Icon,
|
||||
PopoverInteractionKind
|
||||
PopoverInteractionKind,
|
||||
Tooltip
|
||||
} from "@blueprintjs/core";
|
||||
import Occupancy from "./occupancy";
|
||||
import * as globals from "../../globals";
|
||||
import styles from "./categorical.css";
|
||||
import { Tooltip } from "@blueprintjs/core";
|
||||
|
||||
import { AnnotationsHelpers } from "../../util/stateManager";
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class Continuous extends React.Component {
|
||||
|
||||
componentDidUpdate() {}
|
||||
|
||||
handleColorAction(key) {
|
||||
handleColorAction = key => {
|
||||
return () => {
|
||||
const { dispatch, obsAnnotations } = this.props;
|
||||
const summary = obsAnnotations.col(key).summarize();
|
||||
@@ -35,7 +35,7 @@ class Continuous extends React.Component {
|
||||
rangeForColorAccessor: summary
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { obsAnnotations, schema } = this.props;
|
||||
@@ -54,10 +54,11 @@ class Continuous extends React.Component {
|
||||
<div>
|
||||
{this.hasContinuous ? (
|
||||
<p
|
||||
style={Object.assign({}, globals.leftSidebarSectionHeading, {
|
||||
style={{
|
||||
...globals.leftSidebarSectionHeading,
|
||||
marginTop: 40,
|
||||
paddingLeft: globals.leftSidebarSectionPadding
|
||||
})}
|
||||
}}
|
||||
>
|
||||
Continuous metadata
|
||||
</p>
|
||||
@@ -84,7 +85,7 @@ class Continuous extends React.Component {
|
||||
isObs
|
||||
zebra={zebra % 2 === 0}
|
||||
ranges={summary}
|
||||
handleColorAction={this.handleColorAction(key).bind(this)}
|
||||
handleColorAction={this.handleColorAction(key)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
/* https://github.com/palantir/blueprint/issues/2348 */
|
||||
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g clip-path="url(#clip0)">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
<path d="M1.33415 8.75877C0.939491 8.36411 0.727699 7.82249 0.749957 7.2648L0.926361 2.84501C0.967947 1.80308 1.80308 0.967947 2.84501 0.926361L7.2648 0.749958C7.82249 0.727699 8.36411 0.939492 8.75877 1.33415L14.3595 6.93485C15.1405 7.7159 15.1405 8.98223 14.3595 9.76328L9.76328 14.3595C8.98223 15.1405 7.7159 15.1405 6.93485 14.3595L1.33415 8.75877Z" fill="black"/>
|
||||
<circle cx="4.5" cy="4.5" r="1.5" fill="white"/>
|
||||
<circle cx="4.5" cy="11.5" r="3.75" stroke="white" stroke-width="0.5"/>
|
||||
<circle cx="4.5" cy="11.5" r="3.5" fill="black"/>
|
||||
<line x1="4.5" y1="10" x2="4.5" y2="13" stroke="white"/>
|
||||
<line x1="3" y1="11.5" x2="6" y2="11.5" stroke="white"/>
|
||||
</g>
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
|
||||
import { memoize } from "../../util/dataframe/util";
|
||||
|
||||
const renderGene = (fuzzySortResult, { handleClick, modifiers, query }) => {
|
||||
const renderGene = (fuzzySortResult, { handleClick, modifiers }) => {
|
||||
if (!modifiers.matchesPredicate) {
|
||||
return null;
|
||||
}
|
||||
@@ -89,6 +89,59 @@ class GeneExpression extends React.Component {
|
||||
// eslint-disable-next-line react/sort-comp
|
||||
_memoGenesToUpper = memoize(this._genesToUpper, arr => arr);
|
||||
|
||||
handleBulkAddClick = () => {
|
||||
const { world, dispatch, userDefinedGenes } = this.props;
|
||||
const varIndexName = world.schema.annotations.var.index;
|
||||
const { bulkAdd } = this.state;
|
||||
|
||||
/*
|
||||
test:
|
||||
Apod,,, Cd74,, ,,, Foo, Bar-2,,
|
||||
*/
|
||||
if (bulkAdd !== "") {
|
||||
const genes = _.pull(_.uniq(bulkAdd.split(/[ ,]+/)), "");
|
||||
if (genes.length === 0) {
|
||||
return keepAroundErrorToast("Must enter a gene name.");
|
||||
}
|
||||
const worldGenes = world.varAnnotations.col(varIndexName).asArray();
|
||||
|
||||
// These gene lists are unique enough where memoization is useless
|
||||
const upperGenes = this._genesToUpper(genes);
|
||||
const upperUserDefinedGenes = this._genesToUpper(userDefinedGenes);
|
||||
|
||||
const upperWorldGenes = this._memoGenesToUpper(worldGenes);
|
||||
|
||||
dispatch({ type: "bulk user defined gene start" });
|
||||
|
||||
Promise.all(
|
||||
[...upperGenes.keys()].map(upperGene => {
|
||||
if (upperUserDefinedGenes.get(upperGene) !== undefined) {
|
||||
return keepAroundErrorToast("That gene already exists");
|
||||
}
|
||||
|
||||
const indexOfGene = upperWorldGenes.get(upperGene);
|
||||
|
||||
if (indexOfGene === undefined) {
|
||||
return keepAroundErrorToast(
|
||||
`${
|
||||
genes[upperGenes.get(upperGene)]
|
||||
} doesn't appear to be a valid gene name.`
|
||||
);
|
||||
}
|
||||
return dispatch(
|
||||
actions.requestUserDefinedGene(worldGenes[indexOfGene])
|
||||
);
|
||||
})
|
||||
).then(
|
||||
() => dispatch({ type: "bulk user defined gene complete" }),
|
||||
() => dispatch({ type: "bulk user defined gene error" })
|
||||
);
|
||||
}
|
||||
|
||||
this.setState({ bulkAdd: "" });
|
||||
return undefined;
|
||||
};
|
||||
|
||||
placeholderGeneNames() {
|
||||
/*
|
||||
return a string containing gene name suggestions for use as a user hint.
|
||||
@@ -145,58 +198,6 @@ class GeneExpression extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleBulkAddClick() {
|
||||
const { world, dispatch, userDefinedGenes } = this.props;
|
||||
const varIndexName = world.schema.annotations.var.index;
|
||||
const { bulkAdd } = this.state;
|
||||
|
||||
/*
|
||||
test:
|
||||
Apod,,, Cd74,, ,,, Foo, Bar-2,,
|
||||
*/
|
||||
if (bulkAdd !== "") {
|
||||
const genes = _.pull(_.uniq(bulkAdd.split(/[ ,]+/)), "");
|
||||
if (genes.length === 0) {
|
||||
return keepAroundErrorToast("Must enter a gene name.");
|
||||
}
|
||||
const worldGenes = world.varAnnotations.col(varIndexName).asArray();
|
||||
|
||||
// These gene lists are unique enough where memoization is useless
|
||||
const upperGenes = this._genesToUpper(genes);
|
||||
const upperUserDefinedGenes = this._genesToUpper(userDefinedGenes);
|
||||
|
||||
const upperWorldGenes = this._memoGenesToUpper(worldGenes);
|
||||
|
||||
dispatch({ type: "bulk user defined gene start" });
|
||||
|
||||
Promise.all(
|
||||
[...upperGenes.keys()].map(upperGene => {
|
||||
if (upperUserDefinedGenes.get(upperGene) !== undefined) {
|
||||
return keepAroundErrorToast("That gene already exists");
|
||||
}
|
||||
|
||||
const indexOfGene = upperWorldGenes.get(upperGene);
|
||||
|
||||
if (indexOfGene === undefined) {
|
||||
return keepAroundErrorToast(
|
||||
`${
|
||||
genes[upperGenes.get(upperGene)]
|
||||
} doesn't appear to be a valid gene name.`
|
||||
);
|
||||
}
|
||||
return dispatch(
|
||||
actions.requestUserDefinedGene(worldGenes[indexOfGene])
|
||||
);
|
||||
})
|
||||
).then(
|
||||
() => dispatch({ type: "bulk user defined gene complete" }),
|
||||
() => dispatch({ type: "bulk user defined gene error" })
|
||||
);
|
||||
}
|
||||
|
||||
this.setState({ bulkAdd: "" });
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
world,
|
||||
@@ -261,7 +262,7 @@ class GeneExpression extends React.Component {
|
||||
}}
|
||||
initialContent={<MenuItem disabled text="Enter a gene…" />}
|
||||
inputProps={{ "data-testid": "gene-search" }}
|
||||
inputValueRenderer={g => {
|
||||
inputValueRenderer={() => {
|
||||
return "";
|
||||
}}
|
||||
itemListPredicate={filterGenes}
|
||||
@@ -276,7 +277,7 @@ class GeneExpression extends React.Component {
|
||||
/>
|
||||
<Button
|
||||
className="bp3-button bp3-intent-primary"
|
||||
data-testid={"add-gene"}
|
||||
data-testid="add-gene"
|
||||
loading={userDefinedGenesLoading}
|
||||
onClick={() => this.handleClick(activeItem)}
|
||||
>
|
||||
@@ -308,7 +309,7 @@ class GeneExpression extends React.Component {
|
||||
/>
|
||||
<Button
|
||||
intent="primary"
|
||||
onClick={this.handleBulkAddClick.bind(this)}
|
||||
onClick={this.handleBulkAddClick}
|
||||
loading={userDefinedGenesLoading}
|
||||
>
|
||||
Add genes
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import Categorical from "../categorical/categorical";
|
||||
import Continuous from "../continuous/continuous";
|
||||
import GeneExpression from "../geneExpression";
|
||||
import * as globals from "../../globals";
|
||||
import DynamicScatterplot from "../scatterplot/scatterplot";
|
||||
import TopLeftLogoAndTitle from "./topLeftLogoAndTitle";
|
||||
|
||||
@@ -266,11 +266,10 @@ class MenuBar extends React.Component {
|
||||
const haveBothCellSets =
|
||||
!!differential.celllist1 && !!differential.celllist2;
|
||||
|
||||
const tipMessage =
|
||||
"See top 10 differentially expressed genes" +
|
||||
(diffexpMayBeSlow
|
||||
? " (CAUTION: large dataset - may take longer or fail)"
|
||||
: "");
|
||||
const slowMsg = diffexpMayBeSlow
|
||||
? " (CAUTION: large dataset - may take longer or fail)"
|
||||
: "";
|
||||
const tipMessage = `See top 10 differentially expressed genes${slowMsg}`;
|
||||
|
||||
return (
|
||||
<div className="bp3-button-group" style={{ marginRight: 10 }}>
|
||||
@@ -318,7 +317,6 @@ class MenuBar extends React.Component {
|
||||
render() {
|
||||
const {
|
||||
dispatch,
|
||||
differential,
|
||||
crossfilter,
|
||||
resettingInterface,
|
||||
libraryVersions,
|
||||
|
||||
@@ -12,17 +12,7 @@ import * as globals from "../../globals";
|
||||
}))
|
||||
class RightSidebar extends React.Component {
|
||||
render() {
|
||||
const {
|
||||
responsive,
|
||||
scatterplotXXaccessor,
|
||||
scatterplotYYaccessor
|
||||
} = this.props;
|
||||
|
||||
/*
|
||||
this magic number should be made less fragile,
|
||||
if cellxgene logo or tabs change, this must as well
|
||||
*/
|
||||
const logoRelatedPadding = 50;
|
||||
const { responsive } = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import calcCentroid from "../util/centroid";
|
||||
|
||||
const initialState = {
|
||||
metadataField: "",
|
||||
categoryIndex: -1,
|
||||
@@ -8,7 +6,7 @@ const initialState = {
|
||||
};
|
||||
|
||||
const CentroidLabel = (state = initialState, action, sharedNextState) => {
|
||||
const { categoricalSelection, world, layoutChoice } = sharedNextState;
|
||||
const { categoricalSelection } = sharedNextState;
|
||||
const { metadataField, categoryIndex } = action;
|
||||
const categoryField =
|
||||
categoricalSelection?.[metadataField]?.categoryValues[categoryIndex];
|
||||
@@ -19,12 +17,7 @@ const CentroidLabel = (state = initialState, action, sharedNextState) => {
|
||||
metadataField,
|
||||
categoryIndex,
|
||||
categoryField,
|
||||
centroidXY: null /* calcCentroid( This function call is computationally heavy and also leading to large GC. Before reimplementation, look into optimization and memoization
|
||||
world,
|
||||
metadataField,
|
||||
categoryField,
|
||||
layoutChoice.currentDimNames
|
||||
) */
|
||||
centroidXY: null
|
||||
};
|
||||
|
||||
case "category value mouse hover end":
|
||||
|
||||
@@ -55,7 +55,7 @@ const ColorsReducer = (
|
||||
|
||||
case "annotation: delete category": {
|
||||
const { colorAccessor } = state;
|
||||
if (action.metadataField != colorAccessor) {
|
||||
if (action.metadataField !== colorAccessor) {
|
||||
return state;
|
||||
}
|
||||
/* else reset */
|
||||
|
||||
@@ -3,6 +3,8 @@ import quantile from "./quantile";
|
||||
/*
|
||||
Centroid coordinate calculation
|
||||
*/
|
||||
|
||||
/* Unused - please cleanup
|
||||
const calcMeanCentroid = (world, annoName, annoValue, layoutDimNames) => {
|
||||
const centroid = { x: 0, y: 0, size: 0 };
|
||||
const annoArray = world.obsAnnotations.col(annoName).asArray();
|
||||
@@ -24,6 +26,7 @@ const calcMeanCentroid = (world, annoName, annoValue, layoutDimNames) => {
|
||||
|
||||
return [centroid.x, centroid.y];
|
||||
};
|
||||
*/
|
||||
|
||||
const calcMedianCentroid = (world, annoName, annoValue, layoutDimNames) => {
|
||||
const centroidX = [];
|
||||
|
||||
@@ -138,7 +138,7 @@ export function allHaveLabelByMask(df, colName, label, mask) {
|
||||
const col = df.col(colName);
|
||||
if (!col) return false;
|
||||
if (df.length !== mask.length)
|
||||
throw new InternalError("mismatch on mask length");
|
||||
throw new RangeError("mismatch on mask length");
|
||||
|
||||
for (let i = 0; i < df.length; i += 1) {
|
||||
if (mask[i]) {
|
||||
|
||||
@@ -108,7 +108,7 @@ export default class ImmutableTypedCrossfilter {
|
||||
};
|
||||
|
||||
return new ImmutableTypedCrossfilter(data, dimensions, {
|
||||
bitArray: bitArray
|
||||
bitArray
|
||||
});
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ export default class ImmutableTypedCrossfilter {
|
||||
}
|
||||
|
||||
return new ImmutableTypedCrossfilter(data, dimensions, {
|
||||
bitArray: bitArray
|
||||
bitArray
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user