Mailspring/internal_packages/thread-snooze/lib/snooze-popover-body.jsx
Juan Tejada a5ee197660 feat(snooze): Adds initial design pass and update snooze popover
Summary:
- Add FixedPopover, an absolutely positioned popover component to use for swipe snoozing:
  - This component needs to be finished, as its current behavior is primarily for the snooze plugin
- Updates popover.cjsx to properly render pointer for thesnooze popover for the `down` direction
- Adds new design assets
- Adds date input to snooze popover

Test Plan: - TODO

Reviewers: evan, bengotow

Reviewed By: bengotow

Differential Revision: https://phab.nylas.com/D2624
2016-02-23 20:03:42 -08:00

163 lines
3.7 KiB
JavaScript

/** @babel */
import _ from 'underscore';
import React, {Component, PropTypes} from 'react';
import {Actions, DateUtils} from 'nylas-exports'
import {RetinaImg} from 'nylas-component-kit';
import SnoozeActions from './snooze-actions'
import {DATE_FORMAT_LONG} from './snooze-constants'
const SnoozeOptions = [
[
'Later Today',
'Tonight',
'Tomorrow',
],
[
'This Weekend',
'Next Week',
'Next Month',
],
]
const SnoozeDateGenerators = {
'Later Today': DateUtils.laterToday,
'Tonight': DateUtils.tonight,
'Tomorrow': DateUtils.tomorrow,
'This Weekend': DateUtils.thisWeekend,
'Next Week': DateUtils.nextWeek,
'Next Month': DateUtils.nextMonth,
}
const SnoozeIconNames = {
'Later Today': 'later',
'Tonight': 'tonight',
'Tomorrow': 'tomorrow',
'This Weekend': 'weekend',
'Next Week': 'week',
'Next Month': 'month',
}
class SnoozePopoverBody extends Component {
static displayName = 'SnoozePopoverBody';
static propTypes = {
threads: PropTypes.array.isRequired,
swipeCallback: PropTypes.func,
};
static defaultProps = {
swipeCallback: ()=> {},
};
constructor() {
super();
this.state = {
inputDate: null,
}
}
onSnooze(dateGenerator) {
const utcDate = dateGenerator().utc()
const formatted = DateUtils.format(utcDate)
SnoozeActions.snoozeThreads(this.props.threads, formatted);
this.props.swipeCallback(true);
Actions.closePopover();
}
onBlur = ()=> {
if (this._focusingInput) {
this._focusingInput = false;
return;
}
this.props.swipeCallback(false);
Actions.closePopover();
};
onKeyDown = (event)=> {
if (event.key === "Escape") {
this.props.swipeCallback(false);
Actions.closePopover()
}
};
onInputChange = (event)=> {
this.updateInputDateValue(event.target.value)
};
onInputKeyDown = (event)=> {
if (["Enter", "Return"].includes(event.key)) {
this.onSnooze(()=> this.state.inputDate)
}
};
onInputMouseDown = ()=> {
this._focusingInput = true;
};
updateInputDateValue = _.debounce((dateValue)=> {
const inputDate = DateUtils.fromString(dateValue)
this.setState({inputDate})
}, 250);
renderItem = (label)=> {
const dateGenerator = SnoozeDateGenerators[label];
const iconName = SnoozeIconNames[label]
const iconPath = `nylas://thread-snooze/assets/ic-snoozepopover-${iconName}@2x.png`
return (
<div
key={label}
className="snooze-item"
onMouseDown={this.onSnooze.bind(this, dateGenerator)}>
<RetinaImg
url={iconPath}
mode={RetinaImg.ContentIsMask} />
{label}
</div>
)
};
renderRow = (options, idx)=> {
const items = _.map(options, this.renderItem)
return (
<div key={`snooze-popover-row-${idx}`} className="snooze-row">
{items}
</div>
);
};
renderInputRow = (inputDate)=> {
let formatted = null
if (inputDate) {
formatted = 'Snooze until ' + DateUtils.format(inputDate, DATE_FORMAT_LONG)
}
return (
<div className="snooze-input">
<input
type="text"
tabIndex="1"
placeholder="Or type a time, e.g. Next monday at 2pm"
onMouseDown={this.onInputMouseDown}
onKeyDown={this.onInputKeyDown}
onChange={this.onInputChange}/>
<em className="input-date-value">{formatted}</em>
</div>
);
};
render() {
const {inputDate} = this.state
const rows = SnoozeOptions.map(this.renderRow)
return (
<div className="snooze-container" onBlur={this.onBlur} onKeyDown={this.onKeyDown}>
{rows}
{this.renderInputRow(inputDate)}
</div>
);
}
}
export default SnoozePopoverBody;