diff --git a/client/src/components/categorical/categorical.js b/client/src/components/categorical/categorical.js index 05f034d6..1c73162b 100644 --- a/client/src/components/categorical/categorical.js +++ b/client/src/components/categorical/categorical.js @@ -11,12 +11,10 @@ import * as globals from "../../globals"; import Value from "./value"; import { alphabeticallySortedValues } from "./util"; -@connect(state => { - return { - colorAccessor: state.controls.colorAccessor, - categoricalAsBooleansMap: state.controls.categoricalAsBooleansMap - }; -}) +@connect(state => ({ + colorAccessor: state.controls.colorAccessor, + categoricalAsBooleansMap: state.controls.categoricalAsBooleansMap +})) class Category extends React.Component { constructor(props) { super(props); @@ -27,9 +25,9 @@ class Category extends React.Component { } componentDidUpdate() { - const valuesAsBool = _.values( - this.props.categoricalAsBooleansMap[this.props.metadataField] - ); + 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; @@ -46,55 +44,60 @@ class Category extends React.Component { } handleColorChange() { - this.props.dispatch({ + const { dispatch, metadataField } = this.props; + dispatch({ type: "color by categorical metadata", - colorAccessor: this.props.metadataField + colorAccessor: metadataField }); } toggleAll() { - this.props.dispatch({ + const { dispatch, metadataField } = this.props; + dispatch({ type: "categorical metadata filter all of these", - metadataField: this.props.metadataField + metadataField }); this.setState({ isChecked: true }); } toggleNone() { - this.props.dispatch({ + const { dispatch, metadataField, value } = this.props; + dispatch({ type: "categorical metadata filter none of these", - metadataField: this.props.metadataField, - value: this.props.value + metadataField, + value }); this.setState({ isChecked: false }); } - renderCategoryItems() { - return _.map(alphabeticallySortedValues(this.props.values), (v, i) => { - return ( - - ); - }); - } - handleToggleAllClick() { + const { isChecked } = this.state; // || this.checkbox.indeterminate === false - if (this.state.isChecked) { + if (isChecked) { console.log("checked, firing toggle none"); this.toggleNone(); - } else if (!this.state.isChecked) { + } else if (!isChecked) { console.log("!checked, firing toggle all"); this.toggleAll(); } } + renderCategoryItems() { + const { values, metadataField } = this.props; + return _.map(alphabeticallySortedValues(values), (v, i) => ( + + )); + } + render() { + const { isExpanded, isChecked } = this.state; + const { metadataField, colorAccessor } = this.props; return (
{ - this.setState({ isExpanded: !this.state.isExpanded }); + this.setState({ isExpanded: !isExpanded }); }} > - {this.state.isExpanded ? : } + {isExpanded ? : } - {this.props.metadataField} + {metadataField} (this.checkbox = el)} - checked={this.state.isChecked} + checked={isChecked} type="checkbox" />

-
{this.state.isExpanded ? this.renderCategoryItems() : null}
+
{isExpanded ? this.renderCategoryItems() : null}
); } @@ -181,7 +184,8 @@ class Categories extends React.Component { } render() { - if (!this.props.ranges) return null; + const { ranges } = this.props; + if (!ranges) return null; return (
- {_.map(this.props.ranges, (value, key) => { + {_.map(ranges, (value, key) => { const isColorField = key.includes("color") || key.includes("Color"); if (value.options && !isColorField && key !== "name") { return ( @@ -208,27 +212,3 @@ class Categories extends React.Component { } export default Categories; - -/* - - [on off] toggle hide deselected filters (shows a menu vs shows what you ordered in compact/narrative form. fold out animation.) - -

Sort by: Alphabetical / Count || Show counts: true / false || Collapse: all / none

- - -

-

-

-

- - might be interesting to show them as an 👁 icon, or with a slash through it, to allow for visible or hidden state - -*/ - -/* - - Each category has a color associated with it - ie., color by location should show up on these buttons, - Does colorby live here? Like a global, with the category labels at the top? If not, we have to - duplicate the category names somewhere else - but then, not all (like Cluster_2d_color) won't be listed here. - -*/ diff --git a/client/src/components/categorical/util.js b/client/src/components/categorical/util.js index 32398200..d55795ca 100644 --- a/client/src/components/categorical/util.js +++ b/client/src/components/categorical/util.js @@ -1,8 +1,7 @@ // jshint esversion: 6 -export const alphabeticallySortedValues = values => { - return Object.keys(values).sort((a, b) => { - var textA = a.toUpperCase(); - var textB = b.toUpperCase(); +export const alphabeticallySortedValues = values => + Object.keys(values).sort((a, b) => { + const textA = a.toUpperCase(); + const textB = b.toUpperCase(); return textA < textB ? -1 : textA > textB ? 1 : 0; }); -}; diff --git a/client/src/components/categorical/value.js b/client/src/components/categorical/value.js index 10be1611..0e3f555c 100644 --- a/client/src/components/categorical/value.js +++ b/client/src/components/categorical/value.js @@ -1,47 +1,51 @@ // jshint esversion: 6 import { connect } from "react-redux"; import React from "react"; -import * as globals from "../../globals"; -import actions from "../../actions"; -@connect(state => { - return { - categoricalAsBooleansMap: state.controls.categoricalAsBooleansMap, - colorScale: state.controls.colorScale, - colorAccessor: state.controls.colorAccessor - }; -}) +@connect(state => ({ + categoricalAsBooleansMap: state.controls.categoricalAsBooleansMap, + colorScale: state.controls.colorScale, + colorAccessor: state.controls.colorAccessor +})) class CategoryValue extends React.Component { toggleOff() { - this.props.dispatch({ + const { dispatch, metadataField, value } = this.props; + dispatch({ type: "categorical metadata filter deselect", - metadataField: this.props.metadataField, - value: this.props.value + metadataField, + value }); } toggleOn() { - this.props.dispatch({ + const { dispatch, metadataField, value } = this.props; + dispatch({ type: "categorical metadata filter select", - metadataField: this.props.metadataField, - value: this.props.value + metadataField, + value }); } render() { - if (!this.props.categoricalAsBooleansMap) return null; + const { + categoricalAsBooleansMap, + metadataField, + count, + value, + colorAccessor, + colorScale, + i + } = this.props; - const selected = this.props.categoricalAsBooleansMap[ - this.props.metadataField - ][this.props.value]; - const c = - this.props.metadataField === - this.props - .colorAccessor; /* this is the color scale, so add swatches below */ + if (!categoricalAsBooleansMap) return null; + + const selected = categoricalAsBooleansMap[metadataField][value]; + /* this is the color scale, so add swatches below */ + const c = metadataField === colorAccessor; return (
- {this.props.value} + {value}

- {this.props.count} + {count}

); @@ -89,38 +91,3 @@ class CategoryValue extends React.Component { } export default CategoryValue; - -// toggleOnlyThis() { -// this.props.dispatch({ -// type: "categorical metadata filter none of these", -// metadataField: this.props.metadataField, -// value: this.props.value -// }) -// } -// -// {"only"} -// - -// onClick={selected ? this.toggleOff.bind(this) : this.toggleOn.bind(this)} -// toggleOn() { -// this.props.dispatch( -// actions.attemptCategoricalMetadataSelection( -// this.props.metadataField, -// this.props.value -// )) -// } -// toggleOff() { -// this.props.dispatch( -// actions.attemptCategoricalMetadataDeselection( -// this.props.metadataField, -// this.props.value -// )) -// }