auspice
Version:
Web app for visualizing pathogen evolution
126 lines (119 loc) • 3.81 kB
JavaScript
import React from "react";
import { connect } from "react-redux";
import Awesomplete from 'awesomplete'; /* https://leaverou.github.io/awesomplete/ */
import styled from 'styled-components';
import { updateVisibleTipsAndBranchThicknesses, updateTipRadii } from "../../actions/tree";
import { NODE_VISIBLE } from "../../util/globals";
import { SidebarSubtitle } from "./styles";
import "../../css/awesomplete.css";
const Cross = ({onClick, show}) => {
if (!show) return null;
return (
<div
className="boxed-item-icon"
style={{
float: "right",
height: "23px",
width: "23px",
borderTopRightRadius: "2px",
borderBottomRightRadius: "2px",
borderRightWidth: "1px",
fontSize: 18
}}
onClick={onClick}
>
{'\xD7'}
</div>
);
};
const Container = styled.div`
font-family: ${(props) => props.theme["font-family"]};
font-size: 14px;
display: inline-block;
color: ${(props) => props.theme.color};
`;
const InputContainer = styled.div`
width: 80%;
display: inline-block;
`;
const Input = styled.input`
fontFamily: inherit;
color: inherit;
fontSize: inherit;
width: 100%;
height: 23px;
padding-left: 7px;
border-radius: 4px;
border: 1px solid #ccc;
`;
class SearchStrains extends React.Component {
constructor() {
super();
this.state = {awesomplete: undefined, show: false};
this.removeSelection = () => {
this.ref.value = null;
this.props.dispatch(updateVisibleTipsAndBranchThicknesses({tipSelected: {clear: true}}));
this.props.dispatch(updateTipRadii());
this.setState({show: false});
};
}
componentDidMount() {
const awesomplete = new Awesomplete(this.ref, {
maxItems: 1000
});
this.ref.addEventListener('awesomplete-selectcomplete', (e) => {
const strain = e.text.value;
for (let i = 0; i < this.props.nodes.length; i++) {
if (this.props.nodes[i].name === strain) {
this.props.dispatch(updateVisibleTipsAndBranchThicknesses({
tipSelected: {treeIdx: this.props.nodes[i].arrayIdx}
}));
/* ^^^ also sets reduxState.tree.selectedStrain */
this.props.dispatch(updateTipRadii({
tipSelectedIdx: this.props.nodes[i].arrayIdx
}));
break;
}
}
this.setState({show: true});
});
this.setState({awesomplete});
}
componentWillReceiveProps(nextProps) {
if (this.props.selectedStrain && !nextProps.selectedStrain) {
this.ref.value = null;
this.setState({show: false});
}
}
// partialSelection() {
// /* this allows dispatches based on the the list of matches, before one is actually chosen */
// /* put his in the <input> onChange={() => this.partialSelection()} */
// console.log("partialSelection", this.state.awesomplete.suggestions.map((s) => s.value));
// }
updateVisibleStrains() {
/* this tells the serch box which strains are visible
and therefore are eligible to be searched */
this.state.awesomplete.list = this.props.nodes
.filter((n) => !n.hasChildren && this.props.visibility[n.arrayIdx] === NODE_VISIBLE)
.map((n) => n.name);
this.state.awesomplete.evaluate();
}
render() {
return (
<Container>
<SidebarSubtitle spaceAbove>Search Strains</SidebarSubtitle>
<InputContainer>
<Input ref={(r) => {this.ref = r;}} onFocus={() => this.updateVisibleStrains()}/>
</InputContainer>
<Cross show={this.state.show} onClick={this.removeSelection}/>
</Container>
);
}
}
export default SearchStrains;