diff --git a/build/config/eslint.json b/build/config/eslint.json index 905a80e23..672f41f80 100644 --- a/build/config/eslint.json +++ b/build/config/eslint.json @@ -11,6 +11,7 @@ }, "rules": { "react/prop-types": [2, {"ignore": ["children"]}], + "react/no-multi-comp": [1], "eqeqeq": [2, "smart"], "id-length": [0], "object-curly-spacing": [0], diff --git a/internal_packages/send-later/lib/main.js b/internal_packages/send-later/lib/main.js new file mode 100644 index 000000000..bbed9857c --- /dev/null +++ b/internal_packages/send-later/lib/main.js @@ -0,0 +1,22 @@ +/** @babel */ +import {ComponentRegistry} from 'nylas-exports' +import SendLaterPopover from './send-later-popover' +import SendLaterStore from './send-later-store' +import SendLaterStatus from './send-later-status' + +export function activate() { + SendLaterStore.activate() + ComponentRegistry.register(SendLaterPopover, {role: 'Composer:ActionButton'}) + ComponentRegistry.register(SendLaterStatus, {role: 'DraftList:DraftStatus'}) +} + +export function deactivate() { + ComponentRegistry.unregister(SendLaterPopover) + ComponentRegistry.unregister(SendLaterStatus) + SendLaterStore.deactivate() +} + +export function serialize() { + +} + diff --git a/internal_packages/send-later/lib/send-later-actions.js b/internal_packages/send-later/lib/send-later-actions.js new file mode 100644 index 000000000..e96a42b07 --- /dev/null +++ b/internal_packages/send-later/lib/send-later-actions.js @@ -0,0 +1,13 @@ +/** @babel */ +import Reflux from 'reflux'; + +const SendLaterActions = Reflux.createActions([ + 'sendLater', + 'cancelSendLater', +]) + +for (const key in SendLaterActions) { + SendLaterActions[key].sync = true +} + +export default SendLaterActions diff --git a/internal_packages/send-later/lib/send-later-constants.js b/internal_packages/send-later/lib/send-later-constants.js new file mode 100644 index 000000000..908192aa6 --- /dev/null +++ b/internal_packages/send-later/lib/send-later-constants.js @@ -0,0 +1,6 @@ +/** @babel */ +export const PLUGIN_ID = "aqx344zhdh6jyabqokejknkvr" +export const PLUGIN_NAME = "Send Later" +export const DATE_FORMAT_LONG = 'ddd, MMM D, YYYY h:mmA' +export const DATE_FORMAT_SHORT = 'MMM D h:mmA' + diff --git a/internal_packages/send-later/lib/send-later-popover.jsx b/internal_packages/send-later/lib/send-later-popover.jsx new file mode 100644 index 000000000..55f583760 --- /dev/null +++ b/internal_packages/send-later/lib/send-later-popover.jsx @@ -0,0 +1,158 @@ +/** @babel */ +import _ from 'underscore' +import React, {Component, PropTypes} from 'react' +import {DateUtils} from 'nylas-exports' +import {Popover} from 'nylas-component-kit' +import SendLaterActions from './send-later-actions' +import SendLaterStore from './send-later-store' +import {DATE_FORMAT_SHORT, DATE_FORMAT_LONG} from './send-later-constants' + + +const SendLaterOptions = { + 'In 1 hour': DateUtils.in1Hour, + 'Later Today': DateUtils.laterToday, + 'Tomorrow Morning': DateUtils.tomorrow, + 'Tomorrow Evening': DateUtils.tomorrowEvening, + 'This Weekend': DateUtils.thisWeekend, + 'Next Week': DateUtils.nextWeek, +} + +class SendLaterPopover extends Component { + static displayName = 'SendLaterPopover'; + + static propTypes = { + draftClientId: PropTypes.string, + }; + + constructor(props) { + super(props) + this.state = { + inputSendDate: null, + isScheduled: SendLaterStore.isScheduled(this.props.draftClientId), + } + } + + componentDidMount() { + this.unsubscribe = SendLaterStore.listen(this.onScheduledMessagesChanged) + } + + componentWillUnmount() { + this.unsubscribe() + } + + onSendLater = (momentDate)=> { + const utcDate = momentDate.utc() + const formatted = DateUtils.format(utcDate) + SendLaterActions.sendLater(this.props.draftClientId, formatted) + + this.setState({isScheduled: null, inputSendDate: null}) + this.refs.popover.close() + }; + + onCancelSendLater = ()=> { + SendLaterActions.cancelSendLater(this.props.draftClientId) + this.setState({inputSendDate: null}) + this.refs.popover.close() + }; + + onScheduledMessagesChanged = ()=> { + const isScheduled = SendLaterStore.isScheduled(this.props.draftClientId) + if (isScheduled !== this.state.isScheduled) { + this.setState({isScheduled}); + } + }; + + onInputChange = (event)=> { + this.updateInputSendDateValue(event.target.value) + }; + + getButtonLabel = (isScheduled)=> { + return isScheduled ? '✅ Scheduled' : 'Send Later'; + }; + + updateInputSendDateValue = _.debounce((dateValue)=> { + const inputSendDate = DateUtils.fromString(dateValue) + this.setState({inputSendDate}) + }, 250); + + renderItems() { + return Object.keys(SendLaterOptions).map((label)=> { + const date = SendLaterOptions[label]() + const formatted = DateUtils.format(date, DATE_FORMAT_SHORT) + return ( +