mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-27 00:08:12 +08:00
categorical metadata performance work (#356)
* do not create unecessary option state for categories we will not display * performance improvements for categorical metadata handling
This commit is contained in:
@@ -23,11 +23,16 @@ const truncateCategories = options => {
|
||||
};
|
||||
|
||||
@connect(state => ({
|
||||
ranges: _.get(state.controls.world, "summary.obs", null)
|
||||
ranges: _.get(state.controls.world, "summary.obs", null),
|
||||
categorySelectionLimit: _.get(
|
||||
state.config,
|
||||
"parameters.category-selection-limit",
|
||||
globals.configDefaults.parameters["category-selection-limit"]
|
||||
)
|
||||
}))
|
||||
class Categories extends React.Component {
|
||||
render() {
|
||||
const { ranges } = this.props;
|
||||
const { ranges, categorySelectionLimit } = this.props;
|
||||
if (!ranges) return null;
|
||||
|
||||
return (
|
||||
@@ -42,7 +47,13 @@ class Categories extends React.Component {
|
||||
<p> Categorical Metadata </p>
|
||||
{_.map(ranges, (value, key) => {
|
||||
const isColorField = key.includes("color") || key.includes("Color");
|
||||
if (value.options && !isColorField && key !== "name") {
|
||||
const isSelectableCategory =
|
||||
value.options &&
|
||||
!isColorField &&
|
||||
key !== "name" &&
|
||||
value.numOptions < categorySelectionLimit;
|
||||
|
||||
if (isSelectableCategory) {
|
||||
const categoryOptions = truncateCategories(value.options);
|
||||
return (
|
||||
<Category
|
||||
|
||||
@@ -2,11 +2,25 @@ import React from "react";
|
||||
import _ from "lodash";
|
||||
import { connect } from "react-redux";
|
||||
import { FaChevronRight, FaChevronDown, FaPaintBrush } from "react-icons/fa";
|
||||
import memoize from "memoize-one";
|
||||
|
||||
import * as globals from "../../globals";
|
||||
import Value from "./value";
|
||||
import alphabeticallySortedValues from "./util";
|
||||
|
||||
const countCategories = (values, optsAsBools) =>
|
||||
_.reduce(
|
||||
values,
|
||||
(r, v, k) => {
|
||||
r.total += 1;
|
||||
if (optsAsBools[k]) {
|
||||
r.on += 1;
|
||||
}
|
||||
return r;
|
||||
},
|
||||
{ total: 0, on: 0 }
|
||||
);
|
||||
|
||||
@connect(state => ({
|
||||
colorAccessor: state.controls.colorAccessor,
|
||||
categoricalAsBooleansMap: state.controls.categoricalAsBooleansMap
|
||||
@@ -18,22 +32,24 @@ class Category extends React.Component {
|
||||
isChecked: true,
|
||||
isExpanded: false
|
||||
};
|
||||
this.countCategories = memoize((values, optsAsBools) =>
|
||||
countCategories(values, optsAsBools)
|
||||
);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const { categoricalAsBooleansMap, metadataField } = this.props;
|
||||
|
||||
const valuesAsBool = _.values(categoricalAsBooleansMap[metadataField]);
|
||||
/* count categories toggled on by counting true values */
|
||||
const categoriesToggledOn = _.values(valuesAsBool).filter(v => v).length;
|
||||
|
||||
if (categoriesToggledOn === valuesAsBool.length) {
|
||||
const { categoricalAsBooleansMap, metadataField, values } = this.props;
|
||||
const categoryCount = this.countCategories(
|
||||
values,
|
||||
categoricalAsBooleansMap[metadataField]
|
||||
);
|
||||
if (categoryCount.on === categoryCount.total) {
|
||||
/* everything is on, so not indeterminate */
|
||||
this.checkbox.indeterminate = false;
|
||||
} else if (categoriesToggledOn === 0) {
|
||||
} else if (categoryCount.on === 0) {
|
||||
/* nothing is on, so no */
|
||||
this.checkbox.indeterminate = false;
|
||||
} else if (categoriesToggledOn < valuesAsBool.length) {
|
||||
} else if (categoryCount.on < categoryCount.total) {
|
||||
/* to be explicit... */
|
||||
this.checkbox.indeterminate = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user