import React from 'react'; import moment from 'moment'; import {Actions, DatabaseStore, DateUtils, SyncbackEventTask} from 'nylas-exports'; import {DatePicker, RetinaImg, ScrollRegion, TabGroupRegion, TimePicker} from 'nylas-component-kit'; import EventParticipantsInput from './event-participants-input'; export default class CalendarEventPopover extends React.Component { static propTypes = { event: React.PropTypes.object.isRequired, } constructor(props) { super(props) const {description, start, end, location, participants} = this.props.event; this.state = {description, start, end, location} this.state.title = this.props.event.displayTitle() this.state.editing = false; this.state.participants = participants || [] } componentWillReceiveProps = (nextProps) => { const {description, start, end, location, participants} = nextProps.event; this.setState({description, start, end, location}) this.setState({ participants: participants || [], title: nextProps.event.displayTitle(), }) } onEdit = () => { this.setState({editing: true}) } getStartMoment = () => moment(this.state.start * 1000); getEndMoment = () => moment(this.state.end * 1000); saveEdits = () => { const event = this.props.event.clone(); const keys = ['title', 'description', 'location', 'participants'] for (const key of keys) { event[key] = this.state[key] } // TODO: How will this affect the event if the when object was originally // a datespan, with start_date and end_date attributes? event.when.start_time = this.state.start; event.when.end_time = this.state.end; DatabaseStore.inTransaction((t) => { this.setState({editing: false}); // TODO: where's the best place to put this? return t.persistModel(event) }).then(() => { const task = new SyncbackEventTask(event.clientId); Actions.queueTask(task); }); } extractNotesFromDescription(node) { const els = node.querySelectorAll('meta[itemprop=description]'); let notes = null; if (els.length) { notes = Array.from(els).map(el => el.content).join('\n'); } else { notes = node.innerText; } while (true) { const nextNotes = notes.replace('\n\n', '\n'); if (nextNotes === notes) { break; } notes = nextNotes; } return notes; } // If on the hour, formats as "3 PM", else formats as "3:15 PM" formatTime(momentTime) { const min = momentTime.minutes(); if (min === 0) { return momentTime.format("h A"); } return momentTime.format("h:mm A"); } updateParticipants = (participants) => { this.setState({participants}) } updateField = (key, value) => { const updates = {} updates[key] = value; this.setState(updates) } _onChangeDay = (newTimestamp) => { const newDay = moment(newTimestamp) const start = this.getStartMoment(); const end = this.getEndMoment(); start.year(newDay.year()) end.year(newDay.year()) start.dayOfYear(newDay.dayOfYear()) end.dayOfYear(newDay.dayOfYear()) this.setState({start: start.unix(), end: end.unix()}) } _onChangeStartTime = (newTimestamp) => { const newStart = moment(newTimestamp) let newEnd = this.getEndMoment(); if (newEnd.isSameOrBefore(newStart)) { const leftInDay = moment(newStart).endOf('day').diff(newStart) const move = Math.min(leftInDay, moment.duration(1, 'hour').asMilliseconds()); newEnd = moment(newStart).add(move, 'ms') } this.setState({start: newStart.unix(), end: newEnd.unix()}) } _onChangeEndTime = (newTimestamp) => { const newEnd = moment(newTimestamp) let newStart = this.getStartMoment(); if (newStart.isSameOrAfter(newEnd)) { const sinceDay = moment(newEnd).diff(newEnd.startOf('day')) const move = Math.min(sinceDay, moment.duration(1, 'hour').asMilliseconds()); newStart = moment(newEnd).subtract(move, 'ms'); } this.setState({end: newEnd.unix(), start: newStart.unix()}) } renderTime() { const startMoment = this.getStartMoment(); const endMoment = this.getEndMoment(); const date = startMoment.format('dddd, MMMM D'); // e.g. Tuesday, February 22 const timeRange = `${this.formatTime(startMoment)} - ${this.formatTime(endMoment)}` return (
{date}
{timeRange}
) } renderEditableTime() { const startVal = (this.state.start) * 1000; const endVal = (this.state.end) * 1000; return (
to {moment().tz(DateUtils.timeZone).format("z")}   on  
) } renderParticipants(participants) { const names = [] for (let i = 0; i < participants.length; i++) { names.push(
{participants[i].name}
); } return names; } renderEditable = () => { const {title, description, start, end, location, participants} = this.state; const fragment = document.createDocumentFragment(); const descriptionRoot = document.createElement('root') fragment.appendChild(descriptionRoot) descriptionRoot.innerHTML = description; const notes = this.extractNotesFromDescription(descriptionRoot); return (
{ this.updateField('title', e.target.value) }} />
{ this.updateField('location', e.target.value) }} />
{this.renderEditableTime(start, end)}
Invitees:
{ this.updateField('participants', val) }} />
Notes:
{ this.updateField('description', e.target.value) }} />
Save Actions.closePopover()}>Cancel
) } render() { if (this.state.editing) { return this.renderEditable(); } const {title, description, location, participants} = this.state; const fragment = document.createDocumentFragment(); const descriptionRoot = document.createElement('root') fragment.appendChild(descriptionRoot) descriptionRoot.innerHTML = description; const notes = this.extractNotesFromDescription(descriptionRoot); return (
{title}
{location}
{this.renderTime()}
Invitees:
{this.renderParticipants(participants)}
Notes:
{notes}
); } }