parse hash fragment for datepicker state (incl. custom dates & group by option)

This commit is contained in:
Danny van Kooten 2018-12-04 11:53:40 +01:00
parent e88bf64a39
commit 97b17e0284
1 changed files with 60 additions and 23 deletions

View File

@ -81,17 +81,38 @@ const availablePeriods = {
} }
} }
function hashParams() {
var params = {},
match,
matches = window.location.hash.substring(2).split("&");
for(var i=0; i<matches.length; i++) {
match = matches[i].split('=')
params[match[0]] = decodeURIComponent(match[1]);
}
return params;
}
class DatePicker extends Component { class DatePicker extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
let params = hashParams();
this.state = { this.state = {
period: window.location.hash.substring(2) || window.localStorage.getItem('period') || '1w', period: params.p || window.localStorage.getItem('period') || '1w',
startDate: now, startDate: new Date(params.s),
endDate: now, endDate: new Date(params.e),
groupBy: 'day', groupBy: params.g || 'day',
}
this.state.diff = this.calculateDiff(this.state.startDate, this.state.endDate)
if(this.state.period !== 'custom') {
this.updateDatesFromPeriod(this.state.period, params.g)
} else {
this.props.onChange(this.state);
} }
this.updateDatesFromPeriod(this.state.period)
} }
componentDidMount() { componentDidMount() {
@ -103,16 +124,16 @@ class DatePicker extends Component {
} }
@bind @bind
updateDatesFromPeriod(period) { updateDatesFromPeriod(period, groupBy) {
if(typeof(availablePeriods[period]) !== "object") { if(typeof(availablePeriods[period]) !== "object") {
period = "1w"; period = "1w";
} }
let p = availablePeriods[period]; let p = availablePeriods[period];
this.setDateRange(p.start(), p.end(), period); this.setDateRange(p.start(), p.end(), period, groupBy);
} }
@bind @bind
setDateRange(start, end, period) { setDateRange(start, end, period, groupBy) {
// don't update state if start > end. user may be busy picking dates. // don't update state if start > end. user may be busy picking dates.
if(start > end) { if(start > end) {
return; return;
@ -122,16 +143,20 @@ class DatePicker extends Component {
start.setHours(0, 0, 0); start.setHours(0, 0, 0);
end.setHours(23, 59, 59); end.setHours(23, 59, 59);
let diff = Math.round((end - start) / 1000 / 60 / 60 / 24) let diff = this.calculateDiff(start, end)
let groupBy = 'day'; if(!groupBy) {
if(diff >= 31) { groupBy = 'day';
groupBy = 'month';
} else if( diff < 2) { if(diff >= 31) {
groupBy = 'hour'; groupBy = 'month';
} else if( diff < 2) {
groupBy = 'hour';
}
} }
this.setState({ this.setState({
period: period || '', period: period,
startDate: start, startDate: start,
endDate: end, endDate: end,
diff: diff, diff: diff,
@ -142,14 +167,24 @@ class DatePicker extends Component {
if(!this.timeout) { if(!this.timeout) {
this.timeout = window.setTimeout(() => { this.timeout = window.setTimeout(() => {
this.props.onChange(this.state); this.props.onChange(this.state);
this.updateURL()
this.timeout = null; this.timeout = null;
window.localStorage.setItem('period', this.state.period)
window.history.replaceState(this.state, null, `#!${this.state.period}`)
}, 5) }, 5)
} }
} }
calculateDiff(start, end) {
return Math.round((end - start) / 1000 / 60 / 60 / 24)
}
updateURL() {
if(this.state.period !== 'custom') {
window.history.replaceState(this.state, null, `#!p=${this.state.period}&g=${this.state.groupBy}`)
} else {
window.history.replaceState(this.state, null, `#!p=custom&s=${encodeURIComponent(this.state.startDate.toISOString())}&e=${encodeURIComponent(this.state.endDate.toISOString())}&g=${this.state.groupBy}`)
}
}
@bind @bind
setPeriod(e) { setPeriod(e) {
e.preventDefault(); e.preventDefault();
@ -159,6 +194,7 @@ class DatePicker extends Component {
return; return;
} }
window.localStorage.setItem('period', this.state.period)
this.updateDatesFromPeriod(newPeriod); this.updateDatesFromPeriod(newPeriod);
} }
@ -168,12 +204,12 @@ class DatePicker extends Component {
@bind @bind
setStartDate(date) { setStartDate(date) {
this.setDateRange(date, this.state.endDate, '') this.setDateRange(date, this.state.endDate, 'custom')
} }
@bind @bind
setEndDate(date) { setEndDate(date) {
this.setDateRange(this.state.startDate, date, '') this.setDateRange(this.state.startDate, date, 'custom')
} }
@bind @bind
@ -211,6 +247,7 @@ class DatePicker extends Component {
groupBy: e.target.getAttribute('data-value') groupBy: e.target.getAttribute('data-value')
}) })
this.props.onChange(this.state); this.props.onChange(this.state);
this.updateURL()
} }
render(props, state) { render(props, state) {
@ -232,9 +269,9 @@ class DatePicker extends Component {
<li><Pikadayer value={this.dateValue(state.startDate)} onSelect={this.setStartDate} /> <span></span> <Pikadayer value={this.dateValue(state.endDate)} onSelect={this.setEndDate} /></li> <li><Pikadayer value={this.dateValue(state.startDate)} onSelect={this.setStartDate} /> <span></span> <Pikadayer value={this.dateValue(state.endDate)} onSelect={this.setEndDate} /></li>
</ul> </ul>
<ul> <ul>
{state.diff < 31 ? (<li class={classNames({ current: 'hour' === state.groupBy })}><a href="#" data-value="hour" onClick={this.setGroupBy}>Hourly</a></li>) : ''} {state.diff < 31 ? (<li class={classNames({ current: 'hour' === state.groupBy })}><a href="javascript:;" data-value="hour" onClick={this.setGroupBy}>Hourly</a></li>) : ''}
<li class={classNames({ current: 'day' === state.groupBy })}><a href="#" data-value="day" onClick={this.setGroupBy}>Daily</a></li> <li class={classNames({ current: 'day' === state.groupBy })}><a href="javascript:;" data-value="day" onClick={this.setGroupBy}>Daily</a></li>
{state.diff >= 31 ? (<li class={classNames({ current: 'month' === state.groupBy })}><a href="#" data-value="month" onClick={this.setGroupBy}>Monthly</a></li>) : ''} {state.diff >= 31 ? (<li class={classNames({ current: 'month' === state.groupBy })}><a href="javascript:;" data-value="month" onClick={this.setGroupBy}>Monthly</a></li>) : ''}
</ul> </ul>
</nav> </nav>
) )