Commit 53278b34 authored by Jed Simson's avatar Jed Simson

Add Date Range Picker option

parent d4882e3f
......@@ -15,8 +15,12 @@
"tests"
],
"dependencies": {
"bootstrap": "^3.3.6",
"bootstrap": "v4.0.0-alpha.2",
"react": "^15.1.0",
"jquery": "^3.0.0"
"jquery": "<3.0.0",
"font-awesome": "^4.6.3",
"tether": "^1.3.2",
"bootstrap-daterangepicker": "^2.1.22",
"moment": "^2.13.0"
}
}
......@@ -7,13 +7,15 @@ const InformationSection = React.createClass({
<hr/>
<p>Please enter your query using the options below...</p>
<p>The range field accepts values like:</p>
<p>The range field uses fuzzy matching accepts values like:</p>
<ul>
<li>"Today"</li>
<li>"June 20 2016 to now"</li>
<li>"May 18 8:00am to May 18 2:00pm"</li>
<li>"1 year ago"</li>
</ul>
<p><strong>OR,</strong> alternatively you can select to use the date picker from the options menu, for
more fine-grained range control.</p>
</div>
);
}
......
const OptionsPanel = React.createClass({
getInitialState: function() {
return {datePickerInfo: 'Using the Date Picker allows for more fine-grained range choosing'
+ ' instead of using fuzzy string matching.',
slidingWindowInfo: 'Using a Sliding Window searching method may provide more results'
+ ' as the default search method doesn\'t ensure that the limit is reached.'};
},
componentDidMount: function() {
$('[data-toggle="popover"]').popover({
trigger: 'focus'
});
},
handleButtonClick: function(event) {
var button = $(event.target);
var text = button.text().split(' ')[0];
button.text((text == 'Show' ? 'Hide' : 'Show') + ' Options');
},
handleRangeOptionChange: function(event) {
var checkbox = $(event.target);
var checked = checkbox.is(':checked');
var name = checkbox.attr('name');
var optionType = 'range';
this.props.onChange({checkbox: checkbox, checked: checked,
name: name, type: optionType});
},
render: function() {
return (
<div style={{'padding-bottom': '1em'}}>
<a onClick={this.handleButtonClick} className="btn btn-primary-outline btn-sm" data-toggle="collapse" href="#collapse-container">Show Options</a>
<div id="collapse-container" className="collapse" style={{'padding-top': '1em'}}>
<div className="card" id="options-card" >
<div className="card-block">
<h4 className="card-title">Options</h4>
</div>
<div className="card-block" style={{'padding-top': '0px'}}>
<p>Choose the additional options you want to use:</p>
<div id="options">
<label className="checkbox-inline">
<input onChange={this.handleRangeOptionChange} type="checkbox" id="optionUseDatePicker" name="useDateRangePicker" />
Use Date Picker
&nbsp;
<a href="#"
data-toggle="popover"
title="Date Picker"
data-content={this.state.datePickerInfo}>
<i className="fa fa-question-circle-o" aria-hidden="true"></i>
</a>
</label>
<label className="checkbox-inline">
<input type="checkbox" id="optionUseDatePicker" value="" />
Use Sliding Window Search
&nbsp;
<a href="#"
data-toggle="popover"
title="Sliding Window Search"
data-content={this.state.slidingWindowInfo}>
<i className="fa fa-question-circle-o" aria-hidden="true"></i></a>
</label>
</div>
</div>
</div>
</div>
</div>
);
}
});
module.exports = OptionsPanel;
const RangeField = React.createClass({
getInitialState: function() {
return {default: 'today',
range: 'today'};
range: 'today',
useDateRangePicker: false};
},
handleChange: function(event) {
let oldValue = this.state.range;
......@@ -13,18 +14,67 @@ const RangeField = React.createClass({
this.props.onChange(event, oldValue, newValue);
},
handleDatePickerChange: function(event, picker) {
var startDate = picker.startDate.format('MMMM DD YYYY');
var endDate = picker.endDate.format('MMMM DD YYYY');
var oldValue = this.state.range;
var newValue = startDate + ' to ' + endDate;
this.setState({range: newValue});
this.props.onChange(event, oldValue, newValue);
},
componentDidUpdate: function(prevProps, prevState) {
if (this.state.useDateRangePicker) {
var range = this.state.range == 'today' ? moment().format('MMMM DD YYYY') + ' to ' + moment().format('MMMM DD YYYY') : this.state.range;
$('#range span').html(range);
$('#range').daterangepicker({
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
'Last 7 Days': [moment().subtract(6, 'days'), moment()],
'Last 30 Days': [moment().subtract(29, 'days'), moment()],
'This Month': [moment().startOf('month'), moment().endOf('month')],
'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
}
});
$('#range').on('apply.daterangepicker', this.handleDatePickerChange);
}
},
render: function() {
return (
<fieldset className="form-group">
<label for="range"><strong>&nbsp;Range&nbsp;</strong></label>
<input
type="text"
id="range"
className="form-control"
placeholder={this.state.default}
onChange={this.handleChange}/>
</fieldset>
);
if (this.state.useDateRangePicker) {
var rangeDivStyle = {
background: 'white',
cursor: 'pointer',
padding: '5px 10px',
border: '1px solid #ccc'
};
return (
<fieldset className="form-group">
<label for="range"><strong>&nbsp;Range&nbsp;</strong></label>
<div className="form-control" id="range" style={rangeDivStyle}>
<i class="glyphicon glyphicon-calendar fa fa-calendar"></i>&nbsp;
<span></span><b class="caret"></b>
</div>
</fieldset>
);
}
else {
return (
<fieldset className="form-group">
<label for="range"><strong>&nbsp;Range&nbsp;</strong></label>
<input
type="text"
id="range"
className="form-control"
placeholder={this.state.default}
onChange={this.handleChange}/>
</fieldset>
);
}
}
});
......
......@@ -33,11 +33,11 @@ const ResultsPanel = React.createClass({
<h4 className="card-title">Results</h4>
{!noSubmissions ? <div id="info" className="alert alert-info">{this.state.info}</div> : null}
</div>
<div className="card-block">
<div className="card-block" style={{'padding-top': '0em'}}>
<div className="list-group" id="results">
{this.state.hasError ? <div className="alert alert-danger">{this.state.error.msg}</div> : null}
{!noSubmissions ? submissions : null}
{this.state.loading ? <div id="loading"><strong>Loading...</strong></div> : null}
{this.state.loading ? <progress id="progress" className="progress progress-striped progress-animated" value="100" max="100">Loading</progress> : null}
</div>
</div>
</div>
......
const ResultsPanel = require('./ResultsPanel.js');
const OptionsPanel = require('./OptionsPanel.js');
const {SubredditField, RangeField, SortField, LimitField} = require('./Fields.js');
const SearchForm = React.createClass({
......@@ -79,6 +80,13 @@ const SearchForm = React.createClass({
query: this.serializeQuery(newParams)
});
},
handleOptionChange: function(option) {
if (option.type == 'range') {
this.refs.rangeField.setState({
useDateRangePicker: option.checked
});
}
},
render: function() {
return (
<div>
......@@ -93,6 +101,7 @@ const SearchForm = React.createClass({
<br/>
<OptionsPanel onChange={this.handleOptionChange} ref="optionsPanel" />
<ResultsPanel ref="resultsPanel" />
</div>
);
......
......@@ -7,7 +7,16 @@
<script src="{{ url_for('static', filename='bower_components/jquery/dist/jquery.min.js') }}"></script>
<link rel="stylesheet" href="../static/bootstrap.min.css">
<script src="{{ url_for('static', filename='bower_components/tether/dist/js/tether.min.js') }}"></script>
<script src="{{ url_for('static', filename='bower_components/bootstrap/dist/js/bootstrap.min.js') }}"></script>
<link rel="stylesheet" href="{{ url_for('static', filename='bower_components/bootstrap/dist/css/bootstrap.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='bower_components/font-awesome/css/font-awesome.min.css') }}">
<script src="{{ url_for('static', filename='bower_components/moment/min/moment.min.js') }}"></script>
<script src="{{ url_for('static', filename='bower_components/bootstrap-daterangepicker/daterangepicker.js') }}"></script>
<link rel="stylesheet" href="{{ url_for('static', filename='bower_components/bootstrap-daterangepicker/daterangepicker.css') }}">
</head>
<body>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment