diff --git a/client/src/components/geneExpression/gene.js b/client/src/components/geneExpression/gene.js
index 5912e912..7d0834eb 100644
--- a/client/src/components/geneExpression/gene.js
+++ b/client/src/components/geneExpression/gene.js
@@ -64,6 +64,8 @@ class Gene extends React.Component {
isColorAccessor,
isScatterplotXXaccessor,
isScatterplotYYaccessor,
+ quickGene,
+ removeGene,
} = this.props;
const { geneIsExpanded } = this.state;
const geneSymbolWidth = 60 + (geneIsExpanded ? MINI_HISTOGRAM_WIDTH : 0);
@@ -94,16 +96,18 @@ class Gene extends React.Component {
}}
>
-
+ {!quickGene && (
+
+ )}
@@ -132,7 +136,9 @@ class Gene extends React.Component {
minimal
small
data-testid={`delete-from-geneset-${gene}`}
- onClick={this.handleDeleteGeneFromSet}
+ onClick={
+ quickGene ? removeGene(gene) : this.handleDeleteGeneFromSet
+ }
intent="none"
style={{ fontWeight: 700, marginRight: 2 }}
icon={}
diff --git a/client/src/components/geneExpression/index.js b/client/src/components/geneExpression/index.js
index b7990627..0670e751 100644
--- a/client/src/components/geneExpression/index.js
+++ b/client/src/components/geneExpression/index.js
@@ -1,8 +1,10 @@
import React from "react";
import { connect } from "react-redux";
-import { Button } from "@blueprintjs/core";
-import GeneSet from "./geneSet";
+import { Button, H4, Icon } from "@blueprintjs/core";
+import { IconNames } from "@blueprintjs/icons";
+import GeneSet from "./geneSet";
+import QuickGene from "./quickGene";
import CreateGenesetDialogue from "./menus/createGenesetDialogue";
@connect((state) => {
@@ -11,6 +13,11 @@ import CreateGenesetDialogue from "./menus/createGenesetDialogue";
};
})
class GeneExpression extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = { geneSetsExpanded: true };
+ }
+
renderGeneSets = () => {
const sets = [];
const { genesets } = this.props;
@@ -31,25 +38,66 @@ class GeneExpression extends React.Component {
handleActivateCreateGenesetMode = () => {
const { dispatch } = this.props;
+ const { geneSetsExpanded } = this.state;
dispatch({ type: "geneset: activate add new geneset mode" });
+ if (!geneSetsExpanded) {
+ this.setState((state) => {
+ return { ...state, geneSetsExpanded: true };
+ });
+ }
+ };
+
+ handleExpandGeneSets = () => {
+ this.setState((state) => {
+ return { ...state, geneSetsExpanded: !state.geneSetsExpanded };
+ });
};
render() {
+ const { geneSetsExpanded } = this.state;
return (
+
-
-
+ Gene Sets{" "}
+ {geneSetsExpanded ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
-
{this.renderGeneSets()}
+
+ {geneSetsExpanded &&
{this.renderGeneSets()}
}
);
}
diff --git a/client/src/components/geneExpression/quickGene.js b/client/src/components/geneExpression/quickGene.js
new file mode 100644
index 00000000..219345f1
--- /dev/null
+++ b/client/src/components/geneExpression/quickGene.js
@@ -0,0 +1,176 @@
+import { H4, Icon, MenuItem } from "@blueprintjs/core";
+import { IconNames } from "@blueprintjs/icons";
+import React, { useState, useEffect, useRef, useMemo } from "react";
+import fuzzysort from "fuzzysort";
+import { Suggest } from "@blueprintjs/select";
+import { useSelector, useDispatch } from "react-redux";
+
+import Gene from "./gene";
+
+import { postUserErrorToast } from "../framework/toasters";
+import actions from "../../actions";
+
+const usePrevious = (value) => {
+ const ref = useRef();
+ useEffect(() => {
+ ref.current = value;
+ });
+ return ref.current;
+};
+
+function QuickGene() {
+ const dispatch = useDispatch();
+
+ const [isExpanded, setIsExpanded] = useState(true);
+ const [geneNames, setGeneNames] = useState([]);
+ const [, setStatus] = useState("pending");
+
+ const { annoMatrix, userDefinedGenes, userDefinedGenesLoading } = useSelector(
+ (state) => {
+ return {
+ annoMatrix: state.annoMatrix,
+ userDefinedGenes: state.controls.userDefinedGenes,
+ userDefinedGenesLoading: state.controls.userDefinedGenesLoading,
+ };
+ }
+ );
+
+ const prevProps = usePrevious({ annoMatrix });
+
+ useEffect(async () => {
+ if (!annoMatrix) return;
+ if (annoMatrix !== prevProps?.annoMatrix) {
+ const { schema } = annoMatrix;
+ const varIndex = schema.annotations.var.index;
+
+ setStatus("pending");
+ try {
+ const df = await annoMatrix.fetch("var", varIndex);
+ setStatus("success");
+ setGeneNames(df.col(varIndex).asArray());
+ } catch (error) {
+ setStatus("error");
+ throw error;
+ }
+ }
+ }, [annoMatrix, prevProps]);
+
+ const handleExpand = () => setIsExpanded(!isExpanded);
+
+ const renderGene = (fuzzySortResult, { handleClick, modifiers }) => {
+ if (!modifiers.matchesPredicate) {
+ return null;
+ }
+ /* the fuzzysort wraps the object with other properties, like a score */
+ const geneName = fuzzySortResult.target;
+
+ return (
+