auspice
Version:
Web app for visualizing pathogen evolution
111 lines (106 loc) • 4.42 kB
JavaScript
import React from "react";
import { connect } from "react-redux";
import styled from 'styled-components';
import Slider from "./slider";
import { controlsWidth, minDistanceDateSlider } from "../../util/globals";
import { numericToCalendar } from "../../util/dateHelpers";
import { changeDateFilter } from "../../actions/tree";
import { MAP_ANIMATION_PLAY_PAUSE_BUTTON } from "../../actions/types";
const DateLabel = styled.div`
font-family: ${(props) => props.theme["font-family"]};
margin-bottom: 5px;
font-size: 12px;
font-weight: 400;
color: ${(props) => props.theme.color};
float: ${(props) => props.right ? "right" : "left"};
`;
class DateRangeInputs extends React.Component {
constructor(props) {
super(props);
this.state = {
lastSliderUpdateTime: Date.now()
};
}
maybeClearMapAnimationInterval() {
if (window.NEXTSTRAIN && window.NEXTSTRAIN.animationTickReference) {
clearInterval(window.NEXTSTRAIN.animationTickReference);
window.NEXTSTRAIN.animationTickReference = null;
this.props.dispatch({
type: MAP_ANIMATION_PLAY_PAUSE_BUTTON,
data: "Play"
});
}
}
updateFromSlider(debounce, numDateValues) {
/* debounce: boolean. TRUE: both debounce and quickdraw. */
this.maybeClearMapAnimationInterval();
if (debounce) {
// simple debounce @ 100ms
const currentTime = Date.now();
if (currentTime < this.state.lastSliderUpdateTime + 100) {
return null;
}
// console.log("UPDATING", currentTime, this.state.lastSliderUpdateTime)
this.setState({lastSliderUpdateTime: currentTime});
}
// {numDateValues} is an array of numDates received from Slider
// [numDateStart, numDateEnd]
const newRange = {min: numericToCalendar(numDateValues[0]),
max: numericToCalendar(numDateValues[1])};
if (this.props.dateMin !== newRange.min && this.props.dateMax === newRange.max) { // update min
this.props.dispatch(changeDateFilter({newMin: newRange.min, quickdraw: debounce}));
} else if (this.props.dateMin === newRange.min &&
this.props.dateMax !== newRange.max) { // update max
this.props.dispatch(changeDateFilter({newMax: newRange.max, quickdraw: debounce}));
} else if (this.props.dateMin !== newRange.min &&
this.props.dateMax !== newRange.max) { // update both
this.props.dispatch(changeDateFilter({newMin: newRange.min, newMax: newRange.max, quickdraw: debounce}));
} else if (debounce === false) {
/* this occurs when no dates have actually changed BUT we need to redraw (e.g. quickdraw has come off) */
this.props.dispatch(changeDateFilter({quickdraw: debounce}));
}
return null;
}
render() {
if (this.props.branchLengthsToDisplay === "divOnly") {
return null;
}
return (
<div>
<div style={{width: controlsWidth}}>
<Slider // numDates are handed to Slider
min={this.props.absoluteDateMinNumeric}
max={this.props.absoluteDateMaxNumeric}
defaultValue={[this.props.absoluteDateMinNumeric, this.props.absoluteDateMaxNumeric]}
value={[this.props.dateMinNumeric, this.props.dateMaxNumeric]}
/* debounce the onChange event, but ensure the final one goes through */
onChange={this.updateFromSlider.bind(this, true)}
onAfterChange={this.updateFromSlider.bind(this, false)}
minDistance={minDistanceDateSlider * (this.props.absoluteDateMaxNumeric - this.props.absoluteDateMinNumeric)}
pearling
withBars
/>
</div>
<div style={{height: 5}}/>
<div style={{width: controlsWidth}}>
<DateLabel>{this.props.dateMin}</DateLabel>
<DateLabel right>{this.props.dateMax}</DateLabel>
</div>
</div>
);
}
}
export default DateRangeInputs;